Contiki-NG
lwm2m-server.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015-2018, Yanzi Networks 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 /**
38  * \file
39  * Implementation of the Contiki OMA LWM2M server
40  * \author
41  * Joakim Eriksson <joakime@sics.se>
42  * Niclas Finne <nfi@sics.se>
43  */
44 
45 #include <stdint.h>
46 #include "lib/list.h"
47 #include "lwm2m-object.h"
48 #include "lwm2m-engine.h"
49 #include "lwm2m-server.h"
50 #include "lwm2m-rd-client.h"
51 
52 /* Log configuration */
53 #include "coap-log.h"
54 #define LOG_MODULE "lwm2m-srv"
55 #define LOG_LEVEL LOG_LEVEL_LWM2M
56 
57 #define MAX_COUNT LWM2M_SERVER_MAX_COUNT
58 
59 static lwm2m_status_t lwm2m_callback(lwm2m_object_instance_t *object,
60  lwm2m_context_t *ctx);
61 
62 static lwm2m_object_instance_t *create_instance(uint16_t instance_id,
63  lwm2m_status_t *status);
64 static int delete_instance(uint16_t instance_id, lwm2m_status_t *status);
65 static lwm2m_object_instance_t *get_first(lwm2m_status_t *status);
66 static lwm2m_object_instance_t *get_next(lwm2m_object_instance_t *instance,
67  lwm2m_status_t *status);
68 static lwm2m_object_instance_t *get_by_id(uint16_t instance_id,
69  lwm2m_status_t *status);
70 
71 static const lwm2m_resource_id_t resources[] = {
72  RO(LWM2M_SERVER_SHORT_SERVER_ID),
73  RW(LWM2M_SERVER_LIFETIME_ID),
74  EX(LWM2M_SERVER_REG_UPDATE_TRIGGER_ID)
75 };
76 
77 static const lwm2m_object_impl_t impl = {
78  .object_id = LWM2M_OBJECT_SERVER_ID,
79  .get_first = get_first,
80  .get_next = get_next,
81  .get_by_id = get_by_id,
82  .create_instance = create_instance,
83  .delete_instance = delete_instance,
84 };
85 static lwm2m_object_t server_object = {
86  .impl = &impl,
87 };
88 
89 LIST(server_list);
90 static lwm2m_server_t server_instances[MAX_COUNT];
91 /*---------------------------------------------------------------------------*/
92 static lwm2m_object_instance_t *
93 create_instance(uint16_t instance_id, lwm2m_status_t *status)
94 {
95  lwm2m_object_instance_t *instance;
96  int i;
97 
98  instance = get_by_id(instance_id, NULL);
99  if(instance != NULL) {
100  /* An instance with this id is already registered */
101  if(status) {
102  *status = LWM2M_STATUS_OPERATION_NOT_ALLOWED;
103  }
104  return NULL;
105  }
106 
107  for(i = 0; i < MAX_COUNT; i++) {
108  if(server_instances[i].instance.instance_id == LWM2M_OBJECT_INSTANCE_NONE) {
109  server_instances[i].instance.callback = lwm2m_callback;
110  server_instances[i].instance.object_id = LWM2M_OBJECT_SERVER_ID;
111  server_instances[i].instance.instance_id = instance_id;
112  server_instances[i].instance.resource_ids = resources;
113  server_instances[i].instance.resource_count =
114  sizeof(resources) / sizeof(lwm2m_resource_id_t);
115  server_instances[i].server_id = 0;
116  server_instances[i].lifetime = 0;
117  list_add(server_list, &server_instances[i].instance);
118 
119  if(status) {
120  *status = LWM2M_STATUS_OK;
121  }
122 
123  return &server_instances[i].instance;
124  }
125  }
126 
127  if(status) {
128  *status = LWM2M_STATUS_SERVICE_UNAVAILABLE;
129  }
130 
131  return NULL;
132 }
133 /*---------------------------------------------------------------------------*/
134 static int
135 delete_instance(uint16_t instance_id, lwm2m_status_t *status)
136 {
137  lwm2m_object_instance_t *instance;
138 
139  if(status) {
140  *status = LWM2M_STATUS_OK;
141  }
142 
143  if(instance_id == LWM2M_OBJECT_INSTANCE_NONE) {
144  /* Remove all instances */
145  while((instance = list_pop(server_list)) != NULL) {
146  instance->instance_id = LWM2M_OBJECT_INSTANCE_NONE;
147  }
148  return 1;
149  }
150 
151  instance = get_by_id(instance_id, NULL);
152  if(instance != NULL) {
153  instance->instance_id = LWM2M_OBJECT_INSTANCE_NONE;
154  list_remove(server_list, instance);
155  return 1;
156  }
157 
158  return 0;
159 }
160 /*---------------------------------------------------------------------------*/
161 static lwm2m_object_instance_t *
162 get_first(lwm2m_status_t *status)
163 {
164  if(status) {
165  *status = LWM2M_STATUS_OK;
166  }
167  return list_head(server_list);
168 }
169 /*---------------------------------------------------------------------------*/
170 static lwm2m_object_instance_t *
171 get_next(lwm2m_object_instance_t *instance, lwm2m_status_t *status)
172 {
173  if(status) {
174  *status = LWM2M_STATUS_OK;
175  }
176  return instance == NULL ? NULL : instance->next;
177 }
178 /*---------------------------------------------------------------------------*/
179 static lwm2m_object_instance_t *
180 get_by_id(uint16_t instance_id, lwm2m_status_t *status)
181 {
182  lwm2m_object_instance_t *instance;
183  if(status) {
184  *status = LWM2M_STATUS_OK;
185  }
186  for(instance = list_head(server_list);
187  instance != NULL;
188  instance = instance->next) {
189  if(instance->instance_id == instance_id) {
190  return instance;
191  }
192  }
193  return NULL;
194 }
195 /*---------------------------------------------------------------------------*/
196 static lwm2m_status_t
197 lwm2m_callback(lwm2m_object_instance_t *object,
198  lwm2m_context_t *ctx)
199 {
200  int32_t value;
201  lwm2m_server_t *server;
202  server = (lwm2m_server_t *) object;
203 
204  if(ctx->operation == LWM2M_OP_WRITE) {
205  LOG_DBG("Write to: %d\n", ctx->resource_id);
206  switch(ctx->resource_id) {
207  case LWM2M_SERVER_LIFETIME_ID:
208  lwm2m_object_read_int(ctx, ctx->inbuf->buffer, ctx->inbuf->size, &value);
209  server->lifetime = value;
210  break;
211  }
212  } else if(ctx->operation == LWM2M_OP_READ) {
213  switch(ctx->resource_id) {
214  case LWM2M_SERVER_SHORT_SERVER_ID:
215  lwm2m_object_write_int(ctx, server->server_id);
216  break;
217  case LWM2M_SERVER_LIFETIME_ID:
218  lwm2m_object_write_int(ctx, server->lifetime);
219  break;
220  }
221  } else if(ctx->operation == LWM2M_OP_EXECUTE) {
222  switch(ctx->resource_id) {
223  case LWM2M_SERVER_REG_UPDATE_TRIGGER_ID:
224  lwm2m_rd_client_update_triggered();
225  break;
226  }
227  } else {
228  return LWM2M_STATUS_NOT_IMPLEMENTED;
229  }
230 
231  return LWM2M_STATUS_OK;
232 }
233 /*---------------------------------------------------------------------------*/
234 lwm2m_server_t *
235 lwm2m_server_add(uint16_t instance_id, uint16_t server_id, uint32_t lifetime)
236 {
237  lwm2m_server_t *server;
238  int i;
239 
240  for(server = list_head(server_list);
241  server;
242  server = (lwm2m_server_t *)server->instance.next) {
243  if(server->server_id == server_id) {
244  /* Found a matching server */
245  if(server->instance.instance_id != instance_id) {
246  /* Non-matching instance id */
247  LOG_DBG("non-matching instance id for server %u\n", server_id);
248  return NULL;
249  }
250  server->lifetime = lifetime;
251  return server;
252  } else if(server->instance.instance_id == instance_id) {
253  /* Right instance but wrong server id */
254  LOG_DBG("non-matching server id for instance %u\n", instance_id);
255  return NULL;
256  }
257  }
258 
259  for(i = 0; i < MAX_COUNT; i++) {
260  if(server_instances[i].instance.instance_id == LWM2M_OBJECT_INSTANCE_NONE) {
261  server_instances[i].instance.callback = lwm2m_callback;
262  server_instances[i].instance.object_id = LWM2M_OBJECT_SERVER_ID;
263  server_instances[i].instance.instance_id = instance_id;
264  server_instances[i].instance.resource_ids = resources;
265  server_instances[i].instance.resource_count =
266  sizeof(resources) / sizeof(lwm2m_resource_id_t);
267  server_instances[i].server_id = server_id;
268  server_instances[i].lifetime = lifetime;
269  list_add(server_list, &server_instances[i].instance);
270 
271  return &server_instances[i];
272  }
273  }
274 
275  LOG_WARN("no space for more servers\n");
276 
277  return NULL;
278 }
279 /*---------------------------------------------------------------------------*/
280 void
281 lwm2m_server_init(void)
282 {
283  int i;
284 
285  LOG_INFO("init\n");
286 
287  list_init(server_list);
288 
289  for(i = 0; i < MAX_COUNT; i++) {
290  server_instances[i].instance.instance_id = LWM2M_OBJECT_INSTANCE_NONE;
291  }
292  lwm2m_engine_add_generic_object(&server_object);
293 }
294 /*---------------------------------------------------------------------------*/
295 /** @} */
Log support for CoAP
Header file for the LWM2M object API
Linked list manipulation routines.
void * list_head(list_t list)
Get a pointer to the first element of a list.
Definition: list.c:82
Header file for the Contiki OMA LWM2M Registration and Bootstrap Client.
void list_add(list_t list, void *item)
Add an item at the end of a list.
Definition: list.c:142
void list_init(list_t list)
Initialize a list.
Definition: list.c:65
#define LIST(name)
Declare a linked list.
Definition: list.h:88
Header file for the Contiki OMA LWM2M engine
void * list_pop(list_t list)
Remove the first object on a list.
Definition: list.c:215
void list_remove(list_t list, void *item)
Remove a specific element from a list.
Definition: list.c:237