2017-07-25 11:04:16 -07:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2017 Linaro Limited
|
2019-01-25 14:13:07 -08:00
|
|
|
* Copyright (c) 2017-2019 Foundries.io
|
2017-07-25 11:04:16 -07:00
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
|
|
|
|
2017-07-07 11:04:03 -07:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2015, Yanzi Networks AB.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. Neither the name of the copyright holder nor the names of its
|
|
|
|
* contributors may be used to endorse or promote products derived
|
|
|
|
* from this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS
|
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
|
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
|
|
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
|
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|
|
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Original authors:
|
|
|
|
* Joakim Eriksson <joakime@sics.se>
|
|
|
|
* Niclas Finne <nfi@sics.se>
|
|
|
|
* Joel Hoglund <joel@sics.se>
|
|
|
|
*/
|
|
|
|
|
2018-09-19 11:22:19 +03:00
|
|
|
#define LOG_MODULE_NAME net_lwm2m_rd_client
|
|
|
|
#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
|
|
|
|
|
|
|
|
#include <logging/log.h>
|
|
|
|
LOG_MODULE_REGISTER(LOG_MODULE_NAME);
|
2017-07-07 11:04:03 -07:00
|
|
|
|
|
|
|
#include <zephyr/types.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <init.h>
|
2019-06-26 10:33:49 -04:00
|
|
|
#include <sys/printk.h>
|
2017-07-07 11:04:03 -07:00
|
|
|
|
|
|
|
#include "lwm2m_object.h"
|
|
|
|
#include "lwm2m_engine.h"
|
|
|
|
|
|
|
|
#define LWM2M_RD_CLIENT_URI "rd"
|
|
|
|
|
2018-06-11 14:44:30 -07:00
|
|
|
#define SECONDS_TO_UPDATE_EARLY 6
|
2017-10-10 20:58:47 -07:00
|
|
|
#define STATE_MACHINE_UPDATE_INTERVAL K_MSEC(500)
|
2017-07-07 11:04:03 -07:00
|
|
|
|
|
|
|
/* Leave room for 32 hexadeciaml digits (UUID) + NULL */
|
|
|
|
#define CLIENT_EP_LEN 33
|
|
|
|
|
2020-02-20 16:49:14 +01:00
|
|
|
/* Up to 3 characters + NULL */
|
|
|
|
#define CLIENT_BINDING_LEN sizeof("UQS")
|
|
|
|
|
2017-07-07 11:04:03 -07:00
|
|
|
/* The states for the RD client state machine */
|
|
|
|
/*
|
|
|
|
* When node is unregistered it ends up in UNREGISTERED
|
|
|
|
* and this is going to be there until use X or Y kicks it
|
|
|
|
* back into INIT again
|
|
|
|
*/
|
|
|
|
enum sm_engine_state {
|
|
|
|
ENGINE_INIT,
|
2019-02-04 11:20:31 -08:00
|
|
|
#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP)
|
|
|
|
ENGINE_DO_BOOTSTRAP_REG,
|
|
|
|
ENGINE_BOOTSTRAP_REG_SENT,
|
|
|
|
ENGINE_BOOTSTRAP_REG_DONE,
|
|
|
|
ENGINE_BOOTSTRAP_TRANS_DONE,
|
|
|
|
#endif
|
2017-07-07 11:04:03 -07:00
|
|
|
ENGINE_DO_REGISTRATION,
|
|
|
|
ENGINE_REGISTRATION_SENT,
|
|
|
|
ENGINE_REGISTRATION_DONE,
|
2020-02-24 16:44:52 +01:00
|
|
|
ENGINE_REGISTRATION_DONE_RX_OFF,
|
2017-07-07 11:04:03 -07:00
|
|
|
ENGINE_UPDATE_SENT,
|
|
|
|
ENGINE_DEREGISTER,
|
|
|
|
ENGINE_DEREGISTER_SENT,
|
|
|
|
ENGINE_DEREGISTER_FAILED,
|
|
|
|
ENGINE_DEREGISTERED
|
|
|
|
};
|
|
|
|
|
|
|
|
struct lwm2m_rd_client_info {
|
2019-01-25 21:43:52 -08:00
|
|
|
u32_t lifetime;
|
2017-08-23 22:33:38 -07:00
|
|
|
struct lwm2m_ctx *ctx;
|
2017-07-07 11:04:03 -07:00
|
|
|
u8_t engine_state;
|
|
|
|
u8_t use_bootstrap;
|
|
|
|
u8_t trigger_update;
|
|
|
|
|
|
|
|
s64_t last_update;
|
2020-02-24 16:44:52 +01:00
|
|
|
s64_t last_tx;
|
2017-07-07 11:04:03 -07:00
|
|
|
|
|
|
|
char ep_name[CLIENT_EP_LEN];
|
|
|
|
char server_ep[CLIENT_EP_LEN];
|
2017-09-11 22:20:36 -07:00
|
|
|
|
|
|
|
lwm2m_ctx_event_cb_t event_cb;
|
2018-05-15 11:45:21 -07:00
|
|
|
} client;
|
2017-07-07 11:04:03 -07:00
|
|
|
|
|
|
|
/* buffers */
|
|
|
|
static char query_buffer[64]; /* allocate some data for queries and updates */
|
|
|
|
static u8_t client_data[256]; /* allocate some data for the RD */
|
|
|
|
|
2020-02-24 16:44:52 +01:00
|
|
|
void engine_update_tx_time(void)
|
|
|
|
{
|
|
|
|
client.last_tx = k_uptime_get();
|
|
|
|
}
|
|
|
|
|
2018-05-15 11:45:21 -07:00
|
|
|
static void set_sm_state(u8_t sm_state)
|
2017-07-07 11:04:03 -07:00
|
|
|
{
|
2017-09-11 22:20:36 -07:00
|
|
|
enum lwm2m_rd_client_event event = LWM2M_RD_CLIENT_EVENT_NONE;
|
|
|
|
|
|
|
|
/* Determine if a callback to the app is needed */
|
2019-01-25 22:36:47 -08:00
|
|
|
#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP)
|
|
|
|
if (sm_state == ENGINE_BOOTSTRAP_REG_DONE) {
|
|
|
|
event = LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_REG_COMPLETE;
|
|
|
|
} else if (sm_state == ENGINE_BOOTSTRAP_TRANS_DONE) {
|
|
|
|
event = LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_TRANSFER_COMPLETE;
|
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
if (client.engine_state == ENGINE_UPDATE_SENT &&
|
|
|
|
sm_state == ENGINE_REGISTRATION_DONE) {
|
2017-09-11 22:20:36 -07:00
|
|
|
event = LWM2M_RD_CLIENT_EVENT_REG_UPDATE_COMPLETE;
|
|
|
|
} else if (sm_state == ENGINE_REGISTRATION_DONE) {
|
|
|
|
event = LWM2M_RD_CLIENT_EVENT_REGISTRATION_COMPLETE;
|
2020-02-24 16:44:52 +01:00
|
|
|
} else if (sm_state == ENGINE_REGISTRATION_DONE_RX_OFF) {
|
|
|
|
event = LWM2M_RD_CLIENT_EVENT_QUEUE_MODE_RX_OFF;
|
2017-09-11 22:20:36 -07:00
|
|
|
} else if ((sm_state == ENGINE_INIT ||
|
|
|
|
sm_state == ENGINE_DEREGISTERED) &&
|
2019-01-25 22:36:47 -08:00
|
|
|
(client.engine_state >= ENGINE_DO_REGISTRATION &&
|
2019-08-29 18:31:58 +09:00
|
|
|
client.engine_state <= ENGINE_DEREGISTER_SENT)) {
|
2017-09-11 22:20:36 -07:00
|
|
|
event = LWM2M_RD_CLIENT_EVENT_DISCONNECT;
|
|
|
|
}
|
|
|
|
|
2017-07-07 11:04:03 -07:00
|
|
|
/* TODO: add locking? */
|
2018-05-15 11:45:21 -07:00
|
|
|
client.engine_state = sm_state;
|
2017-09-11 22:20:36 -07:00
|
|
|
|
2018-05-15 11:45:21 -07:00
|
|
|
if (event > LWM2M_RD_CLIENT_EVENT_NONE && client.event_cb) {
|
|
|
|
client.event_cb(client.ctx, event);
|
2017-09-11 22:20:36 -07:00
|
|
|
}
|
2017-07-07 11:04:03 -07:00
|
|
|
}
|
|
|
|
|
2018-05-15 11:45:21 -07:00
|
|
|
static bool sm_is_registered(void)
|
2017-08-25 14:14:04 -07:00
|
|
|
{
|
2018-05-15 11:45:21 -07:00
|
|
|
return (client.engine_state >= ENGINE_REGISTRATION_DONE &&
|
|
|
|
client.engine_state <= ENGINE_DEREGISTER_FAILED);
|
2017-08-25 14:14:04 -07:00
|
|
|
}
|
|
|
|
|
2018-05-15 11:45:21 -07:00
|
|
|
static u8_t get_sm_state(void)
|
2017-07-07 11:04:03 -07:00
|
|
|
{
|
|
|
|
/* TODO: add locking? */
|
2018-05-15 11:45:21 -07:00
|
|
|
return client.engine_state;
|
2017-09-01 01:22:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void sm_handle_timeout_state(struct lwm2m_message *msg,
|
|
|
|
enum sm_engine_state sm_state)
|
|
|
|
{
|
2017-09-11 22:20:36 -07:00
|
|
|
enum lwm2m_rd_client_event event = LWM2M_RD_CLIENT_EVENT_NONE;
|
2017-09-01 01:22:30 -07:00
|
|
|
|
2019-01-25 22:36:47 -08:00
|
|
|
#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP)
|
|
|
|
if (client.engine_state == ENGINE_BOOTSTRAP_REG_SENT) {
|
|
|
|
event = LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_REG_FAILURE;
|
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
if (client.engine_state == ENGINE_REGISTRATION_SENT) {
|
2017-09-11 22:20:36 -07:00
|
|
|
event = LWM2M_RD_CLIENT_EVENT_REGISTRATION_FAILURE;
|
2018-05-15 11:45:21 -07:00
|
|
|
} else if (client.engine_state == ENGINE_UPDATE_SENT) {
|
2017-09-11 22:20:36 -07:00
|
|
|
event = LWM2M_RD_CLIENT_EVENT_REG_UPDATE_FAILURE;
|
2018-05-15 11:45:21 -07:00
|
|
|
} else if (client.engine_state == ENGINE_DEREGISTER_SENT) {
|
2017-09-11 22:20:36 -07:00
|
|
|
event = LWM2M_RD_CLIENT_EVENT_DEREGISTER_FAILURE;
|
|
|
|
} else {
|
|
|
|
/* TODO: unknown timeout state */
|
|
|
|
}
|
|
|
|
|
2018-05-15 11:45:21 -07:00
|
|
|
set_sm_state(sm_state);
|
2017-09-11 22:20:36 -07:00
|
|
|
|
2018-05-15 11:45:21 -07:00
|
|
|
if (event > LWM2M_RD_CLIENT_EVENT_NONE && client.event_cb) {
|
|
|
|
client.event_cb(client.ctx, event);
|
2017-09-11 22:20:36 -07:00
|
|
|
}
|
2017-09-01 01:22:30 -07:00
|
|
|
}
|
|
|
|
|
2018-05-15 11:45:21 -07:00
|
|
|
/* force re-update with remote peer */
|
2017-07-07 11:04:03 -07:00
|
|
|
void engine_trigger_update(void)
|
|
|
|
{
|
2018-05-15 11:45:21 -07:00
|
|
|
/* TODO: add locking? */
|
2018-11-29 11:23:03 -08:00
|
|
|
client.trigger_update = 1U;
|
2017-07-07 11:04:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/* state machine reply callbacks */
|
|
|
|
|
2019-01-25 22:36:47 -08:00
|
|
|
#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP)
|
2017-09-19 16:04:32 -07:00
|
|
|
static int do_bootstrap_reply_cb(const struct coap_packet *response,
|
|
|
|
struct coap_reply *reply,
|
2017-07-07 11:04:03 -07:00
|
|
|
const struct sockaddr *from)
|
|
|
|
{
|
|
|
|
u8_t code;
|
|
|
|
|
2017-09-19 16:04:32 -07:00
|
|
|
code = coap_header_get_code(response);
|
2018-09-19 11:22:19 +03:00
|
|
|
LOG_DBG("Bootstrap callback (code:%u.%u)",
|
|
|
|
COAP_RESPONSE_CODE_CLASS(code),
|
|
|
|
COAP_RESPONSE_CODE_DETAIL(code));
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2017-09-19 16:04:32 -07:00
|
|
|
if (code == COAP_RESPONSE_CODE_CHANGED) {
|
2019-01-25 22:36:47 -08:00
|
|
|
LOG_INF("Bootstrap registration done!");
|
|
|
|
set_sm_state(ENGINE_BOOTSTRAP_REG_DONE);
|
2017-09-19 16:04:32 -07:00
|
|
|
} else if (code == COAP_RESPONSE_CODE_NOT_FOUND) {
|
2019-01-25 22:36:47 -08:00
|
|
|
/* TODO: try and find another bootstrap server entry? */
|
2018-09-19 11:22:19 +03:00
|
|
|
LOG_ERR("Failed: NOT_FOUND. Not Retrying.");
|
2018-05-15 11:45:21 -07:00
|
|
|
set_sm_state(ENGINE_DO_REGISTRATION);
|
2017-09-19 16:04:32 -07:00
|
|
|
} else if (code == COAP_RESPONSE_CODE_FORBIDDEN) {
|
2019-01-25 22:36:47 -08:00
|
|
|
/* TODO: try and find another bootstrap server entry? */
|
2018-09-19 11:22:19 +03:00
|
|
|
LOG_ERR("Failed: 4.03 - Forbidden. Not Retrying.");
|
2018-05-15 11:45:21 -07:00
|
|
|
set_sm_state(ENGINE_DO_REGISTRATION);
|
2017-07-07 11:04:03 -07:00
|
|
|
} else {
|
|
|
|
/* TODO: Read payload for error message? */
|
2018-09-19 11:22:19 +03:00
|
|
|
LOG_ERR("Failed with code %u.%u. Retrying ...",
|
|
|
|
COAP_RESPONSE_CODE_CLASS(code),
|
|
|
|
COAP_RESPONSE_CODE_DETAIL(code));
|
2018-05-15 11:45:21 -07:00
|
|
|
set_sm_state(ENGINE_INIT);
|
2017-07-07 11:04:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-01-25 22:36:47 -08:00
|
|
|
static void do_bootstrap_reg_timeout_cb(struct lwm2m_message *msg)
|
2017-09-01 01:22:30 -07:00
|
|
|
{
|
2018-09-19 11:22:19 +03:00
|
|
|
LOG_WRN("Bootstrap Timeout");
|
2017-09-01 01:22:30 -07:00
|
|
|
|
2019-01-25 22:36:47 -08:00
|
|
|
/* TODO:
|
|
|
|
* Look for the "next" BOOTSTRAP server entry in our security info
|
|
|
|
*/
|
|
|
|
|
2017-09-01 01:22:30 -07:00
|
|
|
/* Restart from scratch */
|
|
|
|
sm_handle_timeout_state(msg, ENGINE_INIT);
|
|
|
|
}
|
2019-01-25 22:36:47 -08:00
|
|
|
#endif
|
2017-09-01 01:22:30 -07:00
|
|
|
|
2017-09-19 16:04:32 -07:00
|
|
|
static int do_registration_reply_cb(const struct coap_packet *response,
|
|
|
|
struct coap_reply *reply,
|
2017-07-07 11:04:03 -07:00
|
|
|
const struct sockaddr *from)
|
|
|
|
{
|
2017-09-19 16:04:32 -07:00
|
|
|
struct coap_option options[2];
|
2017-07-07 11:04:03 -07:00
|
|
|
u8_t code;
|
2018-05-15 11:45:21 -07:00
|
|
|
int ret;
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2017-09-19 16:04:32 -07:00
|
|
|
code = coap_header_get_code(response);
|
2018-09-19 11:22:19 +03:00
|
|
|
LOG_DBG("Registration callback (code:%u.%u)",
|
|
|
|
COAP_RESPONSE_CODE_CLASS(code),
|
|
|
|
COAP_RESPONSE_CODE_DETAIL(code));
|
2017-07-07 11:04:03 -07:00
|
|
|
|
|
|
|
/* check state and possibly set registration to done */
|
2017-09-19 16:04:32 -07:00
|
|
|
if (code == COAP_RESPONSE_CODE_CREATED) {
|
|
|
|
ret = coap_find_options(response, COAP_OPTION_LOCATION_PATH,
|
2017-07-07 11:04:03 -07:00
|
|
|
options, 2);
|
|
|
|
if (ret < 2) {
|
2018-09-19 11:22:19 +03:00
|
|
|
LOG_ERR("Unexpected endpoint data returned.");
|
2017-07-07 11:04:03 -07:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* option[0] should be "rd" */
|
|
|
|
|
2018-05-15 11:45:21 -07:00
|
|
|
if (options[1].len + 1 > sizeof(client.server_ep)) {
|
2018-09-19 11:22:19 +03:00
|
|
|
LOG_ERR("Unexpected length of query: "
|
2017-07-07 11:04:03 -07:00
|
|
|
"%u (expected %zu)\n",
|
|
|
|
options[1].len,
|
2018-05-15 11:45:21 -07:00
|
|
|
sizeof(client.server_ep));
|
2017-07-07 11:04:03 -07:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2018-05-15 11:45:21 -07:00
|
|
|
memcpy(client.server_ep, options[1].value,
|
2017-07-07 11:04:03 -07:00
|
|
|
options[1].len);
|
2018-05-15 11:45:21 -07:00
|
|
|
client.server_ep[options[1].len] = '\0';
|
|
|
|
set_sm_state(ENGINE_REGISTRATION_DONE);
|
2018-09-19 11:22:19 +03:00
|
|
|
LOG_INF("Registration Done (EP='%s')",
|
2019-05-29 16:49:18 -07:00
|
|
|
log_strdup(client.server_ep));
|
2017-07-07 11:04:03 -07:00
|
|
|
|
|
|
|
return 0;
|
2017-09-19 16:04:32 -07:00
|
|
|
} else if (code == COAP_RESPONSE_CODE_NOT_FOUND) {
|
2018-09-19 11:22:19 +03:00
|
|
|
LOG_ERR("Failed: NOT_FOUND. Not Retrying.");
|
2018-05-15 11:45:21 -07:00
|
|
|
set_sm_state(ENGINE_REGISTRATION_DONE);
|
2017-07-07 11:04:03 -07:00
|
|
|
return 0;
|
2017-09-19 16:04:32 -07:00
|
|
|
} else if (code == COAP_RESPONSE_CODE_FORBIDDEN) {
|
2018-09-19 11:22:19 +03:00
|
|
|
LOG_ERR("Failed: 4.03 - Forbidden. Not Retrying.");
|
2018-05-15 11:45:21 -07:00
|
|
|
set_sm_state(ENGINE_REGISTRATION_DONE);
|
2017-07-10 15:56:55 -03:00
|
|
|
return 0;
|
2017-07-07 11:04:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO: Read payload for error message? */
|
2017-07-10 15:56:55 -03:00
|
|
|
/* Possible error response codes: 4.00 Bad request */
|
2018-09-19 11:22:19 +03:00
|
|
|
LOG_ERR("failed with code %u.%u. Re-init network",
|
|
|
|
COAP_RESPONSE_CODE_CLASS(code),
|
|
|
|
COAP_RESPONSE_CODE_DETAIL(code));
|
2019-01-25 22:36:47 -08:00
|
|
|
|
2018-05-15 11:45:21 -07:00
|
|
|
set_sm_state(ENGINE_INIT);
|
2017-07-07 11:04:03 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-09-01 01:22:30 -07:00
|
|
|
static void do_registration_timeout_cb(struct lwm2m_message *msg)
|
|
|
|
{
|
2018-09-19 11:22:19 +03:00
|
|
|
LOG_WRN("Registration Timeout");
|
2017-09-01 01:22:30 -07:00
|
|
|
|
|
|
|
/* Restart from scratch */
|
|
|
|
sm_handle_timeout_state(msg, ENGINE_INIT);
|
|
|
|
}
|
|
|
|
|
2017-09-19 16:04:32 -07:00
|
|
|
static int do_update_reply_cb(const struct coap_packet *response,
|
|
|
|
struct coap_reply *reply,
|
2017-07-07 11:04:03 -07:00
|
|
|
const struct sockaddr *from)
|
|
|
|
{
|
|
|
|
u8_t code;
|
|
|
|
|
2017-09-19 16:04:32 -07:00
|
|
|
code = coap_header_get_code(response);
|
2018-09-19 11:22:19 +03:00
|
|
|
LOG_INF("Update callback (code:%u.%u)",
|
|
|
|
COAP_RESPONSE_CODE_CLASS(code),
|
|
|
|
COAP_RESPONSE_CODE_DETAIL(code));
|
2017-07-07 11:04:03 -07:00
|
|
|
|
|
|
|
/* If NOT_FOUND just continue on */
|
2017-09-19 16:04:32 -07:00
|
|
|
if ((code == COAP_RESPONSE_CODE_CHANGED) ||
|
|
|
|
(code == COAP_RESPONSE_CODE_CREATED)) {
|
2018-05-15 11:45:21 -07:00
|
|
|
set_sm_state(ENGINE_REGISTRATION_DONE);
|
2018-09-19 11:22:19 +03:00
|
|
|
LOG_INF("Update Done");
|
2017-07-07 11:04:03 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO: Read payload for error message? */
|
|
|
|
/* Possible error response codes: 4.00 Bad request & 4.04 Not Found */
|
2018-09-19 11:22:19 +03:00
|
|
|
LOG_ERR("Failed with code %u.%u. Retrying registration",
|
|
|
|
COAP_RESPONSE_CODE_CLASS(code),
|
|
|
|
COAP_RESPONSE_CODE_DETAIL(code));
|
2018-05-15 11:45:21 -07:00
|
|
|
set_sm_state(ENGINE_DO_REGISTRATION);
|
2017-07-07 11:04:03 -07:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-09-01 01:22:30 -07:00
|
|
|
static void do_update_timeout_cb(struct lwm2m_message *msg)
|
|
|
|
{
|
2018-09-19 11:22:19 +03:00
|
|
|
LOG_WRN("Registration Update Timeout");
|
2017-09-01 01:22:30 -07:00
|
|
|
|
|
|
|
/* Re-do registration */
|
|
|
|
sm_handle_timeout_state(msg, ENGINE_DO_REGISTRATION);
|
|
|
|
}
|
|
|
|
|
2017-09-19 16:04:32 -07:00
|
|
|
static int do_deregister_reply_cb(const struct coap_packet *response,
|
|
|
|
struct coap_reply *reply,
|
2017-07-07 11:04:03 -07:00
|
|
|
const struct sockaddr *from)
|
|
|
|
{
|
|
|
|
u8_t code;
|
|
|
|
|
2017-09-19 16:04:32 -07:00
|
|
|
code = coap_header_get_code(response);
|
2018-09-19 11:22:19 +03:00
|
|
|
LOG_DBG("Deregister callback (code:%u.%u)",
|
|
|
|
COAP_RESPONSE_CODE_CLASS(code),
|
|
|
|
COAP_RESPONSE_CODE_DETAIL(code));
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2017-09-19 16:04:32 -07:00
|
|
|
if (code == COAP_RESPONSE_CODE_DELETED) {
|
2019-08-29 18:31:58 +09:00
|
|
|
LOG_INF("Deregistration success");
|
|
|
|
lwm2m_engine_context_close(client.ctx);
|
2018-05-15 11:45:21 -07:00
|
|
|
set_sm_state(ENGINE_DEREGISTERED);
|
2017-07-07 11:04:03 -07:00
|
|
|
} else {
|
2018-09-19 11:22:19 +03:00
|
|
|
LOG_ERR("failed with code %u.%u",
|
|
|
|
COAP_RESPONSE_CODE_CLASS(code),
|
|
|
|
COAP_RESPONSE_CODE_DETAIL(code));
|
2018-05-15 11:45:21 -07:00
|
|
|
if (get_sm_state() == ENGINE_DEREGISTER_SENT) {
|
|
|
|
set_sm_state(ENGINE_DEREGISTER_FAILED);
|
2017-07-07 11:04:03 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-09-01 01:22:30 -07:00
|
|
|
static void do_deregister_timeout_cb(struct lwm2m_message *msg)
|
|
|
|
{
|
2018-09-19 11:22:19 +03:00
|
|
|
LOG_WRN("De-Registration Timeout");
|
2017-09-01 01:22:30 -07:00
|
|
|
|
|
|
|
/* Abort de-registration and start from scratch */
|
|
|
|
sm_handle_timeout_state(msg, ENGINE_INIT);
|
|
|
|
}
|
|
|
|
|
2019-01-25 22:36:47 -08:00
|
|
|
static int sm_select_next_sec_inst(bool bootstrap_server,
|
|
|
|
int *sec_obj_inst, u32_t *lifetime)
|
2019-01-25 21:43:52 -08:00
|
|
|
{
|
|
|
|
char pathstr[MAX_RESOURCE_LEN];
|
|
|
|
int ret, end, i, obj_inst_id, found = -1;
|
|
|
|
bool temp;
|
|
|
|
|
|
|
|
/* lookup existing index */
|
|
|
|
i = lwm2m_security_inst_id_to_index(*sec_obj_inst);
|
|
|
|
if (i < 0) {
|
|
|
|
*sec_obj_inst = -1;
|
|
|
|
i = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* store end marker, due to looping */
|
|
|
|
end = (i == -1 ? CONFIG_LWM2M_SECURITY_INSTANCE_COUNT : i);
|
|
|
|
|
|
|
|
/* loop through servers starting from the index after the current one */
|
2019-02-04 11:20:31 -08:00
|
|
|
for (i++; i < end; i++) {
|
2019-01-25 21:43:52 -08:00
|
|
|
if (i >= CONFIG_LWM2M_SECURITY_INSTANCE_COUNT) {
|
|
|
|
i = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
obj_inst_id = lwm2m_security_index_to_inst_id(i);
|
|
|
|
if (obj_inst_id < 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-02-04 11:20:31 -08:00
|
|
|
/* Query for bootstrap support */
|
2019-01-25 21:43:52 -08:00
|
|
|
snprintk(pathstr, sizeof(pathstr), "0/%d/1",
|
|
|
|
obj_inst_id);
|
|
|
|
ret = lwm2m_engine_get_bool(pathstr, &temp);
|
|
|
|
if (ret < 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-01-25 22:36:47 -08:00
|
|
|
#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP)
|
|
|
|
if (temp == bootstrap_server) {
|
|
|
|
#else
|
2019-01-25 21:43:52 -08:00
|
|
|
if (temp == false) {
|
2019-01-25 22:36:47 -08:00
|
|
|
#endif
|
2019-01-25 21:43:52 -08:00
|
|
|
found = obj_inst_id;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (found > -1) {
|
|
|
|
*sec_obj_inst = found;
|
|
|
|
|
|
|
|
/* query the lifetime */
|
|
|
|
/* TODO: use Short Server ID to link to server info */
|
|
|
|
snprintk(pathstr, sizeof(pathstr), "1/%d/1",
|
|
|
|
obj_inst_id);
|
|
|
|
if (lwm2m_engine_get_u32(pathstr, lifetime) < 0) {
|
|
|
|
*lifetime = CONFIG_LWM2M_ENGINE_DEFAULT_LIFETIME;
|
|
|
|
LOG_DBG("Using default lifetime: %u", *lifetime);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*sec_obj_inst < 0) {
|
|
|
|
/* no servers found */
|
2019-02-04 11:20:31 -08:00
|
|
|
LOG_WRN("sec_obj_inst: No matching servers found.");
|
2019-01-25 21:43:52 -08:00
|
|
|
return -ENOENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-07-07 11:04:03 -07:00
|
|
|
/* state machine step functions */
|
|
|
|
|
2018-05-15 11:45:21 -07:00
|
|
|
static int sm_do_init(void)
|
2017-07-07 11:04:03 -07:00
|
|
|
{
|
2019-02-04 11:20:31 -08:00
|
|
|
client.ctx->sec_obj_inst = -1;
|
2018-11-29 11:23:03 -08:00
|
|
|
client.trigger_update = 0U;
|
2019-01-25 22:36:47 -08:00
|
|
|
client.lifetime = 0U;
|
|
|
|
|
|
|
|
/* Do bootstrap or registration */
|
2019-02-04 11:20:31 -08:00
|
|
|
#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP)
|
|
|
|
set_sm_state(ENGINE_DO_BOOTSTRAP_REG);
|
2017-07-07 11:04:03 -07:00
|
|
|
#else
|
2019-01-25 22:36:47 -08:00
|
|
|
set_sm_state(ENGINE_DO_REGISTRATION);
|
2017-07-07 11:04:03 -07:00
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-01-25 22:36:47 -08:00
|
|
|
#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP)
|
|
|
|
static int sm_do_bootstrap_reg(void)
|
2017-07-07 11:04:03 -07:00
|
|
|
{
|
2017-09-01 01:11:43 -07:00
|
|
|
struct lwm2m_message *msg;
|
|
|
|
int ret;
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2019-02-04 11:23:35 -08:00
|
|
|
/* clear out existing connection data */
|
|
|
|
if (client.ctx->sock_fd > -1) {
|
|
|
|
lwm2m_engine_context_close(client.ctx);
|
|
|
|
}
|
2017-09-01 01:11:43 -07:00
|
|
|
|
2019-01-25 22:36:47 -08:00
|
|
|
client.ctx->bootstrap_mode = true;
|
|
|
|
ret = sm_select_next_sec_inst(client.ctx->bootstrap_mode,
|
|
|
|
&client.ctx->sec_obj_inst,
|
|
|
|
&client.lifetime);
|
|
|
|
if (ret < 0) {
|
2019-02-04 11:20:31 -08:00
|
|
|
/* no bootstrap server found, let's move to registration */
|
|
|
|
LOG_WRN("Bootstrap server not found! Try normal registration.");
|
|
|
|
set_sm_state(ENGINE_DO_REGISTRATION);
|
2019-01-25 22:36:47 -08:00
|
|
|
return ret;
|
|
|
|
}
|
2017-09-01 01:11:43 -07:00
|
|
|
|
2019-01-25 22:36:47 -08:00
|
|
|
if (client.lifetime == 0U) {
|
|
|
|
client.lifetime = CONFIG_LWM2M_ENGINE_DEFAULT_LIFETIME;
|
|
|
|
}
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2019-01-25 22:36:47 -08:00
|
|
|
LOG_INF("Bootstrap started with endpoint '%s' with client lifetime %d",
|
2019-05-29 16:49:18 -07:00
|
|
|
log_strdup(client.ep_name), client.lifetime);
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2019-01-25 22:36:47 -08:00
|
|
|
ret = lwm2m_engine_start(client.ctx);
|
|
|
|
if (ret < 0) {
|
|
|
|
LOG_ERR("Cannot init LWM2M engine (%d)", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
msg = lwm2m_get_message(client.ctx);
|
|
|
|
if (!msg) {
|
|
|
|
LOG_ERR("Unable to get a lwm2m message!");
|
|
|
|
ret = -ENOMEM;
|
|
|
|
goto cleanup_engine;
|
|
|
|
}
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2019-01-25 22:36:47 -08:00
|
|
|
msg->type = COAP_TYPE_CON;
|
|
|
|
msg->code = COAP_METHOD_POST;
|
|
|
|
msg->mid = 0U;
|
|
|
|
msg->reply_cb = do_bootstrap_reply_cb;
|
|
|
|
msg->message_timeout_cb = do_bootstrap_reg_timeout_cb;
|
2017-12-04 21:53:16 -08:00
|
|
|
|
2019-01-25 22:36:47 -08:00
|
|
|
ret = lwm2m_init_message(msg);
|
|
|
|
if (ret) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2019-01-25 22:36:47 -08:00
|
|
|
/* TODO: handle return error */
|
|
|
|
coap_packet_append_option(&msg->cpkt, COAP_OPTION_URI_PATH,
|
|
|
|
"bs", strlen("bs"));
|
|
|
|
|
|
|
|
snprintk(query_buffer, sizeof(query_buffer) - 1, "ep=%s",
|
|
|
|
client.ep_name);
|
|
|
|
/* TODO: handle return error */
|
|
|
|
coap_packet_append_option(&msg->cpkt, COAP_OPTION_URI_QUERY,
|
|
|
|
query_buffer, strlen(query_buffer));
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2019-01-25 22:36:47 -08:00
|
|
|
/* log the bootstrap attempt */
|
|
|
|
LOG_DBG("Register ID with bootstrap server as '%s'",
|
2019-05-29 16:49:18 -07:00
|
|
|
log_strdup(query_buffer));
|
2019-01-25 22:36:47 -08:00
|
|
|
|
|
|
|
ret = lwm2m_send_message(msg);
|
|
|
|
if (ret < 0) {
|
|
|
|
LOG_ERR("Error sending LWM2M packet (err:%d).",
|
|
|
|
ret);
|
|
|
|
goto cleanup;
|
2017-07-07 11:04:03 -07:00
|
|
|
}
|
2019-01-25 22:36:47 -08:00
|
|
|
|
|
|
|
set_sm_state(ENGINE_BOOTSTRAP_REG_SENT);
|
2017-09-01 01:11:43 -07:00
|
|
|
return 0;
|
2017-07-07 11:04:03 -07:00
|
|
|
|
|
|
|
cleanup:
|
2017-10-11 11:29:54 -07:00
|
|
|
lwm2m_reset_message(msg, true);
|
2019-01-25 22:36:47 -08:00
|
|
|
cleanup_engine:
|
|
|
|
lwm2m_engine_context_close(client.ctx);
|
2017-07-07 11:04:03 -07:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-01-25 22:36:47 -08:00
|
|
|
static int sm_bootstrap_reg_done(void)
|
2017-07-07 11:04:03 -07:00
|
|
|
{
|
2019-01-25 22:36:47 -08:00
|
|
|
LOG_INF("Bootstrap registration done.");
|
|
|
|
return 0;
|
|
|
|
}
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2019-01-25 22:36:47 -08:00
|
|
|
void engine_bootstrap_finish(void)
|
|
|
|
{
|
|
|
|
LOG_INF("Bootstrap data transfer done!");
|
|
|
|
set_sm_state(ENGINE_BOOTSTRAP_TRANS_DONE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int sm_bootstrap_trans_done(void)
|
|
|
|
{
|
|
|
|
/* close down context resources */
|
|
|
|
lwm2m_engine_context_close(client.ctx);
|
|
|
|
|
|
|
|
/* reset security object instance */
|
|
|
|
client.ctx->sec_obj_inst = -1;
|
|
|
|
|
|
|
|
set_sm_state(ENGINE_DO_REGISTRATION);
|
2017-07-07 11:04:03 -07:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2019-01-25 22:36:47 -08:00
|
|
|
#endif
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2018-05-15 11:45:21 -07:00
|
|
|
static int sm_send_registration(bool send_obj_support_data,
|
2017-09-19 16:04:32 -07:00
|
|
|
coap_reply_t reply_cb,
|
2017-09-01 01:11:43 -07:00
|
|
|
lwm2m_message_timeout_cb_t timeout_cb)
|
2017-07-07 11:04:03 -07:00
|
|
|
{
|
2017-09-01 01:11:43 -07:00
|
|
|
struct lwm2m_message *msg;
|
2017-10-19 16:27:32 -07:00
|
|
|
u16_t client_data_len;
|
2017-09-01 01:11:43 -07:00
|
|
|
int ret;
|
2020-02-20 16:49:14 +01:00
|
|
|
char binding[CLIENT_BINDING_LEN];
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2018-05-15 11:45:21 -07:00
|
|
|
msg = lwm2m_get_message(client.ctx);
|
2017-09-01 01:11:43 -07:00
|
|
|
if (!msg) {
|
2018-09-19 11:22:19 +03:00
|
|
|
LOG_ERR("Unable to get a lwm2m message!");
|
2017-09-01 01:11:43 -07:00
|
|
|
return -ENOMEM;
|
|
|
|
}
|
2017-09-01 00:27:10 -07:00
|
|
|
|
2017-07-07 11:04:03 -07:00
|
|
|
/* remember the last reg time */
|
2018-05-15 11:45:21 -07:00
|
|
|
client.last_update = k_uptime_get();
|
2017-09-01 01:11:43 -07:00
|
|
|
|
2017-09-19 16:04:32 -07:00
|
|
|
msg->type = COAP_TYPE_CON;
|
|
|
|
msg->code = COAP_METHOD_POST;
|
2018-11-29 11:23:03 -08:00
|
|
|
msg->mid = 0U;
|
2017-09-01 01:11:43 -07:00
|
|
|
msg->reply_cb = reply_cb;
|
|
|
|
msg->message_timeout_cb = timeout_cb;
|
|
|
|
|
|
|
|
ret = lwm2m_init_message(msg);
|
2017-07-07 11:04:03 -07:00
|
|
|
if (ret) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2017-09-19 16:04:32 -07:00
|
|
|
/* TODO: handle return error */
|
|
|
|
coap_packet_append_option(&msg->cpkt, COAP_OPTION_URI_PATH,
|
|
|
|
LWM2M_RD_CLIENT_URI,
|
|
|
|
strlen(LWM2M_RD_CLIENT_URI));
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2018-05-15 11:45:21 -07:00
|
|
|
if (!sm_is_registered()) {
|
2017-07-07 11:04:03 -07:00
|
|
|
/* include client endpoint in URI QUERY on 1st registration */
|
2017-09-19 16:04:32 -07:00
|
|
|
coap_append_option_int(&msg->cpkt, COAP_OPTION_CONTENT_FORMAT,
|
|
|
|
LWM2M_FORMAT_APP_LINK_FORMAT);
|
2017-10-11 13:49:46 -07:00
|
|
|
snprintk(query_buffer, sizeof(query_buffer) - 1,
|
2017-07-05 10:54:31 +08:00
|
|
|
"lwm2m=%s", LWM2M_PROTOCOL_VERSION);
|
2017-09-19 16:04:32 -07:00
|
|
|
/* TODO: handle return error */
|
|
|
|
coap_packet_append_option(&msg->cpkt, COAP_OPTION_URI_QUERY,
|
|
|
|
query_buffer, strlen(query_buffer));
|
2017-10-11 13:49:46 -07:00
|
|
|
snprintk(query_buffer, sizeof(query_buffer) - 1,
|
2018-05-15 11:45:21 -07:00
|
|
|
"ep=%s", client.ep_name);
|
2017-09-19 16:04:32 -07:00
|
|
|
/* TODO: handle return error */
|
|
|
|
coap_packet_append_option(&msg->cpkt, COAP_OPTION_URI_QUERY,
|
|
|
|
query_buffer, strlen(query_buffer));
|
2017-07-07 11:04:03 -07:00
|
|
|
} else {
|
|
|
|
/* include server endpoint in URI PATH otherwise */
|
2017-09-19 16:04:32 -07:00
|
|
|
/* TODO: handle return error */
|
|
|
|
coap_packet_append_option(&msg->cpkt, COAP_OPTION_URI_PATH,
|
2018-05-15 11:45:21 -07:00
|
|
|
client.server_ep,
|
|
|
|
strlen(client.server_ep));
|
2017-07-07 11:04:03 -07:00
|
|
|
}
|
|
|
|
|
2017-10-11 13:49:46 -07:00
|
|
|
snprintk(query_buffer, sizeof(query_buffer) - 1,
|
2018-05-15 11:45:21 -07:00
|
|
|
"lt=%d", client.lifetime);
|
2017-09-19 16:04:32 -07:00
|
|
|
/* TODO: handle return error */
|
|
|
|
coap_packet_append_option(&msg->cpkt, COAP_OPTION_URI_QUERY,
|
|
|
|
query_buffer, strlen(query_buffer));
|
|
|
|
|
2020-02-20 16:49:14 +01:00
|
|
|
lwm2m_engine_get_binding(binding);
|
|
|
|
/* UDP is a default binding, no need to add option if UDP is used. */
|
|
|
|
if (strcmp(binding, "U") != 0) {
|
|
|
|
snprintk(query_buffer, sizeof(query_buffer) - 1,
|
|
|
|
"b=%s", binding);
|
|
|
|
/* TODO: handle return error */
|
|
|
|
coap_packet_append_option(&msg->cpkt, COAP_OPTION_URI_QUERY,
|
|
|
|
query_buffer, strlen(query_buffer));
|
|
|
|
}
|
2017-07-07 11:04:03 -07:00
|
|
|
|
|
|
|
if (send_obj_support_data) {
|
2017-10-19 16:27:32 -07:00
|
|
|
ret = coap_packet_append_payload_marker(&msg->cpkt);
|
|
|
|
if (ret < 0) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2017-07-07 11:04:03 -07:00
|
|
|
/* generate the rd data */
|
|
|
|
client_data_len = lwm2m_get_rd_data(client_data,
|
2017-09-19 16:04:32 -07:00
|
|
|
sizeof(client_data));
|
2019-01-25 14:13:07 -08:00
|
|
|
ret = buf_append(CPKT_BUF_WRITE(&msg->cpkt), client_data,
|
|
|
|
client_data_len);
|
|
|
|
if (ret < 0) {
|
2017-07-07 11:04:03 -07:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-01 01:11:43 -07:00
|
|
|
ret = lwm2m_send_message(msg);
|
|
|
|
if (ret < 0) {
|
2018-09-19 11:22:19 +03:00
|
|
|
LOG_ERR("Error sending LWM2M packet (err:%d).", ret);
|
2017-07-07 11:04:03 -07:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* log the registration attempt */
|
2018-09-19 11:22:19 +03:00
|
|
|
LOG_DBG("registration sent [%s]",
|
2019-05-29 16:49:18 -07:00
|
|
|
log_strdup(lwm2m_sprint_ip_addr(&client.ctx->remote_addr)));
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2017-09-01 01:11:43 -07:00
|
|
|
return 0;
|
2017-07-07 11:04:03 -07:00
|
|
|
|
|
|
|
cleanup:
|
2017-10-11 11:29:54 -07:00
|
|
|
lwm2m_reset_message(msg, true);
|
2017-07-07 11:04:03 -07:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-05-15 11:45:21 -07:00
|
|
|
static int sm_do_registration(void)
|
2017-07-07 11:04:03 -07:00
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
2019-02-04 11:23:35 -08:00
|
|
|
/* clear out existing connection data */
|
|
|
|
if (client.ctx->sock_fd > -1) {
|
|
|
|
lwm2m_engine_context_close(client.ctx);
|
|
|
|
}
|
2019-01-25 21:43:52 -08:00
|
|
|
|
2019-01-25 22:36:47 -08:00
|
|
|
client.ctx->bootstrap_mode = false;
|
|
|
|
ret = sm_select_next_sec_inst(client.ctx->bootstrap_mode,
|
|
|
|
&client.ctx->sec_obj_inst,
|
2019-01-25 21:43:52 -08:00
|
|
|
&client.lifetime);
|
|
|
|
if (ret < 0) {
|
2019-01-25 22:36:47 -08:00
|
|
|
LOG_ERR("Unable to find a valid security instance.");
|
2019-01-25 21:43:52 -08:00
|
|
|
set_sm_state(ENGINE_INIT);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2019-01-25 22:36:47 -08:00
|
|
|
if (client.lifetime == 0U) {
|
2019-01-25 21:43:52 -08:00
|
|
|
client.lifetime = CONFIG_LWM2M_ENGINE_DEFAULT_LIFETIME;
|
|
|
|
}
|
|
|
|
|
|
|
|
LOG_INF("RD Client started with endpoint '%s' with client lifetime %d",
|
2019-05-29 16:49:18 -07:00
|
|
|
log_strdup(client.ep_name), client.lifetime);
|
2019-01-25 21:43:52 -08:00
|
|
|
|
|
|
|
ret = lwm2m_engine_start(client.ctx);
|
|
|
|
if (ret < 0) {
|
|
|
|
LOG_ERR("Cannot init LWM2M engine (%d)", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-02-18 21:46:52 -08:00
|
|
|
ret = sm_send_registration(true,
|
|
|
|
do_registration_reply_cb,
|
|
|
|
do_registration_timeout_cb);
|
|
|
|
if (!ret) {
|
|
|
|
set_sm_state(ENGINE_REGISTRATION_SENT);
|
|
|
|
} else {
|
|
|
|
LOG_ERR("Registration err: %d", ret);
|
|
|
|
lwm2m_engine_context_close(client.ctx);
|
|
|
|
/* exit and try again */
|
2017-07-07 11:04:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-05-15 11:45:21 -07:00
|
|
|
static int sm_registration_done(void)
|
2017-07-07 11:04:03 -07:00
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
bool forced_update;
|
|
|
|
|
2018-06-11 14:44:30 -07:00
|
|
|
/*
|
|
|
|
* check for lifetime seconds - SECONDS_TO_UPDATE_EARLY
|
|
|
|
* so that we can update early and avoid lifetime timeout
|
|
|
|
*/
|
2018-05-15 11:45:21 -07:00
|
|
|
if (sm_is_registered() &&
|
|
|
|
(client.trigger_update ||
|
|
|
|
((client.lifetime - SECONDS_TO_UPDATE_EARLY) <=
|
|
|
|
(k_uptime_get() - client.last_update) / 1000))) {
|
|
|
|
forced_update = client.trigger_update;
|
2018-11-29 11:23:03 -08:00
|
|
|
client.trigger_update = 0U;
|
2018-05-15 11:45:21 -07:00
|
|
|
ret = sm_send_registration(forced_update,
|
2017-09-01 01:22:30 -07:00
|
|
|
do_update_reply_cb,
|
|
|
|
do_update_timeout_cb);
|
2017-07-07 11:04:03 -07:00
|
|
|
if (!ret) {
|
2018-05-15 11:45:21 -07:00
|
|
|
set_sm_state(ENGINE_UPDATE_SENT);
|
2017-07-07 11:04:03 -07:00
|
|
|
} else {
|
2018-09-19 11:22:19 +03:00
|
|
|
LOG_ERR("Registration update err: %d", ret);
|
2019-01-25 22:36:47 -08:00
|
|
|
lwm2m_engine_context_close(client.ctx);
|
|
|
|
/* perform full registration */
|
2019-02-18 21:44:30 -08:00
|
|
|
set_sm_state(ENGINE_DO_REGISTRATION);
|
2017-07-07 11:04:03 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-24 16:44:52 +01:00
|
|
|
if (IS_ENABLED(CONFIG_LWM2M_QUEUE_MODE_ENABLED) &&
|
|
|
|
(client.engine_state != ENGINE_REGISTRATION_DONE_RX_OFF) &&
|
|
|
|
(((k_uptime_get() - client.last_tx) / 1000) >=
|
|
|
|
CONFIG_LWM2M_QUEUE_MODE_UPTIME)) {
|
|
|
|
set_sm_state(ENGINE_REGISTRATION_DONE_RX_OFF);
|
|
|
|
}
|
|
|
|
|
2017-07-07 11:04:03 -07:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-05-15 11:45:21 -07:00
|
|
|
static int sm_do_deregister(void)
|
2017-07-07 11:04:03 -07:00
|
|
|
{
|
2017-09-01 01:11:43 -07:00
|
|
|
struct lwm2m_message *msg;
|
2017-07-07 11:04:03 -07:00
|
|
|
int ret;
|
|
|
|
|
2018-05-15 11:45:21 -07:00
|
|
|
msg = lwm2m_get_message(client.ctx);
|
2017-09-01 01:11:43 -07:00
|
|
|
if (!msg) {
|
2018-09-19 11:22:19 +03:00
|
|
|
LOG_ERR("Unable to get a lwm2m message!");
|
2017-09-01 01:11:43 -07:00
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
2017-09-19 16:04:32 -07:00
|
|
|
msg->type = COAP_TYPE_CON;
|
|
|
|
msg->code = COAP_METHOD_DELETE;
|
2018-11-29 11:23:03 -08:00
|
|
|
msg->mid = 0U;
|
2017-09-01 01:11:43 -07:00
|
|
|
msg->reply_cb = do_deregister_reply_cb;
|
2017-09-01 01:22:30 -07:00
|
|
|
msg->message_timeout_cb = do_deregister_timeout_cb;
|
2017-09-01 00:27:10 -07:00
|
|
|
|
2017-09-01 01:11:43 -07:00
|
|
|
ret = lwm2m_init_message(msg);
|
2017-07-07 11:04:03 -07:00
|
|
|
if (ret) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2017-09-19 16:04:32 -07:00
|
|
|
/* TODO: handle return error */
|
2019-08-29 18:31:58 +09:00
|
|
|
coap_packet_append_option(&msg->cpkt, COAP_OPTION_URI_PATH,
|
|
|
|
LWM2M_RD_CLIENT_URI,
|
|
|
|
strlen(LWM2M_RD_CLIENT_URI));
|
|
|
|
/* include server endpoint in URI PATH */
|
2017-09-19 16:04:32 -07:00
|
|
|
coap_packet_append_option(&msg->cpkt, COAP_OPTION_URI_PATH,
|
2018-05-15 11:45:21 -07:00
|
|
|
client.server_ep,
|
|
|
|
strlen(client.server_ep));
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2019-05-29 16:49:18 -07:00
|
|
|
LOG_INF("Deregister from '%s'", log_strdup(client.server_ep));
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2017-09-01 01:11:43 -07:00
|
|
|
ret = lwm2m_send_message(msg);
|
2017-07-07 11:04:03 -07:00
|
|
|
if (ret < 0) {
|
2018-09-19 11:22:19 +03:00
|
|
|
LOG_ERR("Error sending LWM2M packet (err:%d).", ret);
|
2017-07-07 11:04:03 -07:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2018-05-15 11:45:21 -07:00
|
|
|
set_sm_state(ENGINE_DEREGISTER_SENT);
|
2017-09-01 01:11:43 -07:00
|
|
|
return 0;
|
2017-07-07 11:04:03 -07:00
|
|
|
|
|
|
|
cleanup:
|
2017-10-11 11:29:54 -07:00
|
|
|
lwm2m_reset_message(msg, true);
|
2019-01-25 22:36:47 -08:00
|
|
|
lwm2m_engine_context_close(client.ctx);
|
2017-07-07 11:04:03 -07:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-01-25 22:47:58 -08:00
|
|
|
static void lwm2m_rd_client_service(struct k_work *work)
|
2017-07-07 11:04:03 -07:00
|
|
|
{
|
2018-05-15 11:45:21 -07:00
|
|
|
if (client.ctx) {
|
|
|
|
switch (get_sm_state()) {
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2017-10-10 20:58:47 -07:00
|
|
|
case ENGINE_INIT:
|
2018-05-15 11:45:21 -07:00
|
|
|
sm_do_init();
|
2017-10-10 20:58:47 -07:00
|
|
|
break;
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2019-01-25 22:36:47 -08:00
|
|
|
#if defined(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP)
|
|
|
|
case ENGINE_DO_BOOTSTRAP_REG:
|
|
|
|
sm_do_bootstrap_reg();
|
2017-10-10 20:58:47 -07:00
|
|
|
break;
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2019-01-25 22:36:47 -08:00
|
|
|
case ENGINE_BOOTSTRAP_REG_SENT:
|
|
|
|
/* wait for bootstrap registration done */
|
2017-10-10 20:58:47 -07:00
|
|
|
break;
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2019-01-25 22:36:47 -08:00
|
|
|
case ENGINE_BOOTSTRAP_REG_DONE:
|
|
|
|
sm_bootstrap_reg_done();
|
|
|
|
/* wait for transfer done */
|
2017-10-10 20:58:47 -07:00
|
|
|
break;
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2019-01-25 22:36:47 -08:00
|
|
|
case ENGINE_BOOTSTRAP_TRANS_DONE:
|
|
|
|
sm_bootstrap_trans_done();
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
|
2017-10-10 20:58:47 -07:00
|
|
|
case ENGINE_DO_REGISTRATION:
|
2018-05-15 11:45:21 -07:00
|
|
|
sm_do_registration();
|
2017-10-10 20:58:47 -07:00
|
|
|
break;
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2017-10-10 20:58:47 -07:00
|
|
|
case ENGINE_REGISTRATION_SENT:
|
|
|
|
/* wait registration to be done or timeout */
|
|
|
|
break;
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2017-10-10 20:58:47 -07:00
|
|
|
case ENGINE_REGISTRATION_DONE:
|
2020-02-24 16:44:52 +01:00
|
|
|
case ENGINE_REGISTRATION_DONE_RX_OFF:
|
2018-05-15 11:45:21 -07:00
|
|
|
sm_registration_done();
|
2017-10-10 20:58:47 -07:00
|
|
|
break;
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2017-10-10 20:58:47 -07:00
|
|
|
case ENGINE_UPDATE_SENT:
|
|
|
|
/* wait update to be done or abort */
|
|
|
|
break;
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2017-10-10 20:58:47 -07:00
|
|
|
case ENGINE_DEREGISTER:
|
2018-05-15 11:45:21 -07:00
|
|
|
sm_do_deregister();
|
2017-10-10 20:58:47 -07:00
|
|
|
break;
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2017-10-10 20:58:47 -07:00
|
|
|
case ENGINE_DEREGISTER_SENT:
|
|
|
|
/* wait for deregister to be done or reset */
|
|
|
|
break;
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2017-10-10 20:58:47 -07:00
|
|
|
case ENGINE_DEREGISTER_FAILED:
|
|
|
|
break;
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2017-10-10 20:58:47 -07:00
|
|
|
case ENGINE_DEREGISTERED:
|
|
|
|
break;
|
2017-07-07 11:04:03 -07:00
|
|
|
|
2017-10-10 20:58:47 -07:00
|
|
|
default:
|
2018-09-19 11:22:19 +03:00
|
|
|
LOG_ERR("Unhandled state: %d", get_sm_state());
|
2017-07-07 11:04:03 -07:00
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-25 21:43:52 -08:00
|
|
|
void lwm2m_rd_client_start(struct lwm2m_ctx *client_ctx, const char *ep_name,
|
|
|
|
lwm2m_ctx_event_cb_t event_cb)
|
2017-07-07 11:04:03 -07:00
|
|
|
{
|
2018-05-15 11:45:21 -07:00
|
|
|
client.ctx = client_ctx;
|
|
|
|
client.event_cb = event_cb;
|
2019-01-25 21:43:52 -08:00
|
|
|
|
2018-05-15 11:45:21 -07:00
|
|
|
set_sm_state(ENGINE_INIT);
|
|
|
|
strncpy(client.ep_name, ep_name, CLIENT_EP_LEN - 1);
|
2019-08-29 18:31:58 +09:00
|
|
|
LOG_INF("Start LWM2M Client: %s", log_strdup(client.ep_name));
|
|
|
|
}
|
|
|
|
|
|
|
|
void lwm2m_rd_client_stop(struct lwm2m_ctx *client_ctx,
|
|
|
|
lwm2m_ctx_event_cb_t event_cb)
|
|
|
|
{
|
|
|
|
client.ctx = client_ctx;
|
|
|
|
client.event_cb = event_cb;
|
|
|
|
|
|
|
|
set_sm_state(ENGINE_DEREGISTER);
|
|
|
|
LOG_INF("Stop LWM2M Client: %s", log_strdup(client.ep_name));
|
2017-07-07 11:04:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static int lwm2m_rd_client_init(struct device *dev)
|
|
|
|
{
|
2017-10-10 20:58:47 -07:00
|
|
|
return lwm2m_engine_add_service(lwm2m_rd_client_service,
|
|
|
|
STATE_MACHINE_UPDATE_INTERVAL);
|
2017-07-07 11:04:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
SYS_INIT(lwm2m_rd_client_init, APPLICATION,
|
|
|
|
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|