net: lwm2m: Allow to acknowledge request early from the callback
LwM2M engine by default sends piggybacked responses for requests after all callbacks are executed. This approach however isn't good enough if the application callback executes some lenghty operations (for instance during FW update). Delaying the ACK may result in unnecessary retransmissions. This commits adds an API function which allows to send an early empty ACK from the application callback. This prevents further retransmissions from the server side. After all callbacks are executed, the LwM2M engine will send the response as a separate CON message. Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
This commit is contained in:
parent
df8f6c282b
commit
4331c05f17
2 changed files with 91 additions and 0 deletions
|
@ -80,6 +80,13 @@ struct lwm2m_ctx {
|
|||
struct k_delayed_work retransmit_work;
|
||||
struct sys_mutex send_lock;
|
||||
|
||||
/** A pointer to currently processed request, for internal LwM2M engine
|
||||
* use. The underlying type is ``struct lwm2m_message``, but since it's
|
||||
* declared in a private header and not exposed to the application,
|
||||
* it's stored as a void pointer.
|
||||
*/
|
||||
void *processed_req;
|
||||
|
||||
#if defined(CONFIG_LWM2M_DTLS_SUPPORT)
|
||||
/** TLS tag is set by client as a reference used when the
|
||||
* LwM2M engine calls tls_credential_(add|delete)
|
||||
|
@ -831,6 +838,19 @@ int lwm2m_engine_delete_res_inst(char *pathstr);
|
|||
*/
|
||||
int lwm2m_engine_start(struct lwm2m_ctx *client_ctx);
|
||||
|
||||
/**
|
||||
* @brief Acknowledge the currently processed request with an empty ACK.
|
||||
*
|
||||
* LwM2M engine by default sends piggybacked responses for requests.
|
||||
* This function allows to send an empty ACK for a request earlier (from the
|
||||
* application callback). The LwM2M engine will then send the actual response
|
||||
* as a separate CON message after all callbacks are executed.
|
||||
*
|
||||
* @param[in] client_ctx LwM2M context
|
||||
*
|
||||
*/
|
||||
void lwm2m_acknowledge(struct lwm2m_ctx *client_ctx);
|
||||
|
||||
/**
|
||||
* @brief LwM2M RD client events
|
||||
*
|
||||
|
|
|
@ -1076,6 +1076,27 @@ cleanup:
|
|||
return ret;
|
||||
}
|
||||
|
||||
void lwm2m_acknowledge(struct lwm2m_ctx *client_ctx)
|
||||
{
|
||||
struct lwm2m_message *request;
|
||||
|
||||
if (client_ctx == NULL || client_ctx->processed_req == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
request = (struct lwm2m_message *)client_ctx->processed_req;
|
||||
|
||||
if (request->acknowledged) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (lwm2m_send_empty_ack(client_ctx, request->mid) < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
request->acknowledged = true;
|
||||
}
|
||||
|
||||
uint16_t lwm2m_get_rd_data(uint8_t *client_data, uint16_t size)
|
||||
{
|
||||
struct lwm2m_engine_obj *obj;
|
||||
|
@ -3766,6 +3787,42 @@ error:
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lwm2m_response_promote_to_con(struct lwm2m_message *msg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
msg->type = COAP_TYPE_CON;
|
||||
msg->mid = coap_next_id();
|
||||
|
||||
/* Since the response CoAP packet is already generated at this point,
|
||||
* tweak the specific fields manually:
|
||||
* - CoAP message type (byte 0, bits 2 and 3)
|
||||
* - CoAP message id (bytes 2 and 3)
|
||||
*/
|
||||
msg->cpkt.data[0] &= ~(0x3 << 4);
|
||||
msg->cpkt.data[0] |= (msg->type & 0x3) << 4;
|
||||
msg->cpkt.data[2] = msg->mid >> 8;
|
||||
msg->cpkt.data[3] = (uint8_t) msg->mid;
|
||||
|
||||
/* Add the packet to the pending list. */
|
||||
msg->pending = coap_pending_next_unused(
|
||||
msg->ctx->pendings,
|
||||
CONFIG_LWM2M_ENGINE_MAX_PENDING);
|
||||
if (!msg->pending) {
|
||||
LOG_ERR("Unable to find a free pending to track "
|
||||
"retransmissions.");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = coap_pending_init(msg->pending, &msg->cpkt, &msg->ctx->remote_addr);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Unable to initialize a pending "
|
||||
"retransmission (err:%d).", ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void lwm2m_udp_receive(struct lwm2m_ctx *client_ctx,
|
||||
uint8_t *buf, uint16_t buf_len,
|
||||
struct sockaddr *from_addr,
|
||||
|
@ -3867,12 +3924,26 @@ static void lwm2m_udp_receive(struct lwm2m_ctx *client_ctx,
|
|||
/* skip token generation by default */
|
||||
msg->tkl = 0;
|
||||
|
||||
client_ctx->processed_req = msg;
|
||||
|
||||
/* process the response to this request */
|
||||
r = udp_request_handler(&response, msg);
|
||||
if (r < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg->acknowledged) {
|
||||
r = lwm2m_response_promote_to_con(msg);
|
||||
if (r < 0) {
|
||||
LOG_ERR("Failed to promote reponse to CON: %d",
|
||||
r);
|
||||
lwm2m_reset_message(msg, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
client_ctx->processed_req = NULL;
|
||||
|
||||
r = lwm2m_send_message(msg);
|
||||
if (r < 0) {
|
||||
LOG_ERR("Err sending response: %d", r);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue