Contiki-NG
lwm2m-notification-queue.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017, RISE SICS AB.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holder nor the names of its
14  * contributors may be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS
18  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28  * OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 /**
32  * \addtogroup lwm2m
33  * @{
34  */
35 
36 /**
37  * \file
38  * Implementation of functions to manage the queue to store notifications
39  when waiting for the response to the update message in Queue Mode.
40  * \author
41  * Carlos Gonzalo Peces <carlosgp143@gmail.com>
42  */
43 /*---------------------------------------------------------------------------*/
45 
46 #if LWM2M_QUEUE_MODE_ENABLED
47 
48 #include "lwm2m-queue-mode.h"
49 #include "lwm2m-engine.h"
50 #include "coap-engine.h"
51 #include "lib/memb.h"
52 #include "lib/list.h"
53 #include <string.h>
54 #include <inttypes.h>
55 #include <stdlib.h>
56 #include <stdio.h>
57 
58 /* Log configuration */
59 #include "coap-log.h"
60 #define LOG_MODULE "lwm2m-notification-queue"
61 #define LOG_LEVEL LOG_LEVEL_LWM2M
62 
63 #ifdef LWM2M_NOTIFICATION_QUEUE_CONF_LENGTH
64 #define LWM2M_NOTIFICATION_QUEUE_LENGTH LWM2M_NOTIFICATION_QUEUE_CONF_LENGTH
65 #else
66 #define LWM2M_NOTIFICATION_QUEUE_LENGTH COAP_MAX_OBSERVERS
67 #endif
68 
69 /*---------------------------------------------------------------------------*/
70 /* Queue to store the notifications in the period when the client has woken up, sent the update and it's waiting for the server response*/
71 MEMB(notification_memb, notification_path_t, LWM2M_NOTIFICATION_QUEUE_LENGTH); /* Length + 1 to allocate the new path to add */
72 LIST(notification_paths_queue);
73 /*---------------------------------------------------------------------------*/
74 void
75 lwm2m_notification_queue_init(void)
76 {
77  list_init(notification_paths_queue);
78 }
79 /*---------------------------------------------------------------------------*/
80 static void
81 extend_path(notification_path_t *path_object, char *path, int path_size)
82 {
83  switch(path_object->level) {
84  case 1:
85  snprintf(path, path_size, "%u", path_object->reduced_path[0]);
86  break;
87  case 2:
88  snprintf(path, path_size, "%u/%u", path_object->reduced_path[0], path_object->reduced_path[1]);
89  break;
90  case 3:
91  snprintf(path, path_size, "%u/%u/%u", path_object->reduced_path[0], path_object->reduced_path[1], path_object->reduced_path[2]);
92  break;
93  }
94 }
95 /*---------------------------------------------------------------------------*/
96 static int
97 is_notification_path_present(uint16_t object_id, uint16_t instance_id, uint16_t resource_id)
98 {
99  notification_path_t *iteration_path = (notification_path_t *)list_head(notification_paths_queue);
100  while(iteration_path != NULL) {
101  if(iteration_path->reduced_path[0] == object_id && iteration_path->reduced_path[1] == instance_id
102  && iteration_path->reduced_path[2] == resource_id) {
103  return 1;
104  }
105  iteration_path = iteration_path->next;
106  }
107  return 0;
108 }
109 /*---------------------------------------------------------------------------*/
110 static void
111 remove_notification_path(notification_path_t *path)
112 {
113  list_remove(notification_paths_queue, path);
114  memb_free(&notification_memb, path);
115 }
116 /*---------------------------------------------------------------------------*/
117 void
118 lwm2m_notification_queue_add_notification_path(uint16_t object_id, uint16_t instance_id, uint16_t resource_id)
119 {
120  if(is_notification_path_present(object_id, instance_id, resource_id)) {
121  LOG_DBG("Notification path already present, not queueing it\n");
122  return;
123  }
124  notification_path_t *path_object = memb_alloc(&notification_memb);
125  if(path_object == NULL) {
126  LOG_DBG("Queue is full, could not allocate new notification\n");
127  return;
128  }
129  path_object->reduced_path[0] = object_id;
130  path_object->reduced_path[1] = instance_id;
131  path_object->reduced_path[2] = resource_id;
132  path_object->level = 3;
133  list_add(notification_paths_queue, path_object);
134  LOG_DBG("Notification path added to the list: %u/%u/%u\n", object_id, instance_id, resource_id);
135 }
136 /*---------------------------------------------------------------------------*/
137 void
138 lwm2m_notification_queue_send_notifications()
139 {
140  char path[20];
141  notification_path_t *iteration_path = (notification_path_t *)list_head(notification_paths_queue);
142  notification_path_t *aux = iteration_path;
143 
144  while(iteration_path != NULL) {
145  extend_path(iteration_path, path, sizeof(path));
146 #if LWM2M_QUEUE_MODE_INCLUDE_DYNAMIC_ADAPTATION
147  if(lwm2m_queue_mode_get_dynamic_adaptation_flag()) {
148  lwm2m_queue_mode_set_handler_from_notification();
149  }
150 #endif
151  LOG_DBG("Sending stored notification with path: %s\n", path);
152  coap_notify_observers_sub(NULL, path);
153  aux = iteration_path;
154  iteration_path = iteration_path->next;
155  remove_notification_path(aux);
156  }
157 }
158 #endif /* LWM2M_QUEUE_MODE_ENABLED */
159 /** @} */
Log support for CoAP
int memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
Definition: memb.c:78
CoAP engine implementation.
Header file for functions to manage the queue to store notifications when waiting for the respons...
Linked list manipulation routines.
void * list_head(list_t list)
Get a pointer to the first element of a list.
Definition: list.c:82
Memory block allocation routines.
void list_add(list_t list, void *item)
Add an item at the end of a list.
Definition: list.c:142
Header file for the Contiki OMA LWM2M Queue Mode implementation to manage the parameters ...
void list_init(list_t list)
Initialize a list.
Definition: list.c:65
#define LIST(name)
Declare a linked list.
Definition: list.h:89
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
Definition: memb.c:59
Header file for the Contiki OMA LWM2M engine
void list_remove(list_t list, void *item)
Remove a specific element from a list.
Definition: list.c:237
#define MEMB(name, structure, num)
Declare a memory block.
Definition: memb.h:90