Contiki-NG
Loading...
Searching...
No Matches
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
59static lwm2m_status_t lwm2m_callback(lwm2m_object_instance_t *object,
60 lwm2m_context_t *ctx);
61
62static lwm2m_object_instance_t *create_instance(uint16_t instance_id,
63 lwm2m_status_t *status);
64static int delete_instance(uint16_t instance_id, lwm2m_status_t *status);
65static lwm2m_object_instance_t *get_first(lwm2m_status_t *status);
66static lwm2m_object_instance_t *get_next(lwm2m_object_instance_t *instance,
67 lwm2m_status_t *status);
68static lwm2m_object_instance_t *get_by_id(uint16_t instance_id,
69 lwm2m_status_t *status);
70
71static 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
77static 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};
85static lwm2m_object_t server_object = {
86 .impl = &impl,
87};
88
89LIST(server_list);
90static lwm2m_server_t server_instances[MAX_COUNT];
91/*---------------------------------------------------------------------------*/
92static lwm2m_object_instance_t *
93create_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/*---------------------------------------------------------------------------*/
134static int
135delete_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/*---------------------------------------------------------------------------*/
161static lwm2m_object_instance_t *
162get_first(lwm2m_status_t *status)
163{
164 if(status) {
165 *status = LWM2M_STATUS_OK;
166 }
167 return list_head(server_list);
168}
169/*---------------------------------------------------------------------------*/
170static lwm2m_object_instance_t *
171get_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/*---------------------------------------------------------------------------*/
179static lwm2m_object_instance_t *
180get_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/*---------------------------------------------------------------------------*/
196static lwm2m_status_t
197lwm2m_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(ctx->request->src_ep);
225 break;
226 }
227 } else {
228 return LWM2M_STATUS_NOT_IMPLEMENTED;
229 }
230
231 return LWM2M_STATUS_OK;
232}
233/*---------------------------------------------------------------------------*/
234lwm2m_server_t *
235lwm2m_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/*---------------------------------------------------------------------------*/
280void
281lwm2m_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.
static void list_init(list_t list)
Initialize a list.
Definition list.h:152
#define LIST(name)
Declare a linked list.
Definition list.h:90
void list_add(list_t list, void *item)
Add an item at the end of a list.
Definition list.c:71
void list_remove(list_t list, const void *item)
Remove a specific element from a list.
Definition list.c:134
void * list_pop(list_t list)
Remove the first object on a list.
Definition list.c:122
static void * list_head(const_list_t list)
Get a pointer to the first element of a list.
Definition list.h:169
Linked list manipulation routines.
Header file for the Contiki OMA LWM2M engine.
Header file for the LWM2M object API.
Header file for the Contiki OMA LWM2M Registration and Bootstrap Client.