blob: abe060a54bebdc33ec7d2040005ed3ee559961ff [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/*******************************************************************************
2 *
3 * Copyright (c) 2013, 2014 Intel Corporation and others.
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * and Eclipse Distribution License v1.0 which accompany this distribution.
7 *
8 * The Eclipse Public License is available at
9 * http://www.eclipse.org/legal/epl-v10.html
10 * The Eclipse Distribution License is available at
11 * http://www.eclipse.org/org/documents/edl-v10.php.
12 *
13 * Contributors:
14 * David Navarro, Intel Corporation - initial API and implementation
15 * domedambrosio - Please refer to git log
16 * Toby Jaffey - Please refer to git log
17 * Bosch Software Innovations GmbH - Please refer to git log
18 * Pascal Rieux - Please refer to git log
19 *
20 *******************************************************************************/
21/*
22 Copyright (c) 2013, 2014 Intel Corporation
23
24 Redistribution and use in source and binary forms, with or without modification,
25 are permitted provided that the following conditions are met:
26
27 * Redistributions of source code must retain the above copyright notice,
28 this list of conditions and the following disclaimer.
29 * Redistributions in binary form must reproduce the above copyright notice,
30 this list of conditions and the following disclaimer in the documentation
31 and/or other materials provided with the distribution.
32 * Neither the name of Intel Corporation nor the names of its contributors
33 may be used to endorse or promote products derived from this software
34 without specific prior written permission.
35
36 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
37 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
38 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
39 IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
40 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
41 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
43 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
44 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
45 THE POSSIBILITY OF SUCH DAMAGE.
46
47 David Navarro <david.navarro@intel.com>
48
49*/
50
51#include "internals.h"
52#include <stdio.h>
53
54
55#ifdef LWM2M_CLIENT_MODE
56coap_status_t handle_dm_request(lwm2m_context_t * contextP,
57 lwm2m_uri_t * uriP,
58 void * fromSessionH,
59 coap_packet_t * message,
60 coap_packet_t * response)
61{
62 coap_status_t result;
63 lwm2m_server_t * serverP = NULL;
64#ifdef LWM2M_BOOTSTRAP
65 lwm2m_server_t * bsServerP = NULL;
66#endif
67
68 serverP = prv_findServer(contextP, fromSessionH);
69 if (NULL == serverP)
70 {
71#ifdef LWM2M_BOOTSTRAP
72 bsServerP = utils_findBootstrapServer(contextP, fromSessionH);
73 if (NULL == bsServerP)
74 {
75 // No server found
76 return COAP_IGNORE;
77 }
78#else
79 return COAP_IGNORE;
80#endif
81 }
82
83#ifdef LWM2M_BOOTSTRAP
84 if (contextP->bsState != BOOTSTRAP_PENDING)
85 {
86 if (NULL != bsServerP)
87 {
88 // server initiated bootstrap?
89 // currently not implemented.
90 return NOT_IMPLEMENTED_5_01;
91 }
92 if ( serverP->status != STATE_REGISTERED &&
93 serverP->status != STATE_REG_UPDATE_PENDING)
94 {
95 return COAP_IGNORE;
96 }
97 }
98 else
99 {
100 if (NULL != serverP)
101 {
102 // Request form management server during bootstrap.
103 return UNAUTHORIZED_4_01;
104 }
105 }
106#endif
107
108 switch (message->code)
109 {
110 case COAP_GET:
111 {
112 uint8_t * buffer = NULL;
113 size_t length = 0;
114
115 result = object_read(contextP, uriP, &buffer, &length);
116 if (COAP_205_CONTENT == result)
117 {
118 if (IS_OPTION(message, COAP_OPTION_OBSERVE))
119 {
120 result = handle_observe_request(contextP, uriP, serverP, message, response);
121 }
122 if (COAP_205_CONTENT == result)
123 {
124 coap_set_payload(response, buffer, length);
125 // lwm2m_handle_packet will free buffer
126 }
127 else
128 {
129 lwm2m_free(buffer);
130 }
131 }
132 }
133 break;
134
135 case COAP_POST:
136 {
137#ifdef LWM2M_BOOTSTRAP
138 /* no POST during bootstrap */
139 if (contextP->bsState == BOOTSTRAP_PENDING) return METHOD_NOT_ALLOWED_4_05;
140#endif
141 if (!LWM2M_URI_IS_SET_INSTANCE(uriP))
142 {
143 result = object_create(contextP, uriP, message->payload, message->payload_len);
144 if (result == COAP_201_CREATED)
145 {
146 //longest uri is /65535/65535 = 12 + 1 (null) chars
147 char location_path[13] = "";
148 //instanceId expected
149 if ((uriP->flag & LWM2M_URI_FLAG_INSTANCE_ID) == 0)
150 {
151 result = COAP_500_INTERNAL_SERVER_ERROR;
152 break;
153 }
154
155 if (sprintf(location_path, "/%d/%d", uriP->objectId, uriP->instanceId) < 0)
156 {
157 result = COAP_500_INTERNAL_SERVER_ERROR;
158 break;
159 }
160 coap_set_header_location_path(response, location_path);
161 }
162 }
163 else if (!LWM2M_URI_IS_SET_RESOURCE(uriP))
164 {
165 if (object_isInstanceNew(contextP, uriP->objectId, uriP->instanceId))
166 {
167 result = object_create(contextP, uriP, message->payload, message->payload_len);
168 }
169 else
170 {
171 result = object_write(contextP, uriP, message->payload, message->payload_len);
172 }
173 }
174 else
175 {
176 result = object_execute(contextP, uriP, message->payload, message->payload_len);
177 }
178 }
179 break;
180
181 case COAP_PUT:
182 {
183 if (LWM2M_URI_IS_SET_INSTANCE(uriP))
184 {
185#ifdef LWM2M_BOOTSTRAP
186 if (contextP->bsState == BOOTSTRAP_PENDING && object_isInstanceNew(contextP, uriP->objectId, uriP->instanceId))
187 {
188 result = object_create(contextP, uriP, message->payload, message->payload_len);
189 if (COAP_201_CREATED == result)
190 {
191 result = COAP_204_CHANGED;
192 }
193 }
194 else
195#endif
196 {
197 result = object_write(contextP, uriP, message->payload, message->payload_len);
198 }
199 }
200 else
201 {
202 result = BAD_REQUEST_4_00;
203 }
204 }
205 break;
206
207 case COAP_DELETE:
208 {
209 if (LWM2M_URI_IS_SET_INSTANCE(uriP) && !LWM2M_URI_IS_SET_RESOURCE(uriP))
210 {
211 result = object_delete(contextP, uriP);
212 }
213 else
214 {
215 result = BAD_REQUEST_4_00;
216 }
217 }
218 break;
219
220 default:
221 result = BAD_REQUEST_4_00;
222 break;
223 }
224
225 return result;
226}
227
228static void management_delete_all_instances(lwm2m_object_t * object)
229{
230 if (NULL != object->deleteFunc)
231 {
232 while (NULL != object->instanceList)
233 {
234 object->deleteFunc(object->instanceList->id, object);
235 }
236 }
237}
238
239coap_status_t handle_delete_all(lwm2m_context_t * context)
240{
241 lwm2m_object_t ** objectList = context->objectList;
242 if (NULL != objectList)
243 {
244 int i;
245 for (i = 0 ; i < context->numObject ; i++)
246 {
247 // Only security and server objects are deleted upon a DEL /
248 switch (objectList[i]->objID)
249 {
250 case LWM2M_SECURITY_OBJECT_ID:
251 case LWM2M_SERVER_OBJECT_ID:
252 management_delete_all_instances(objectList[i]);
253 break;
254 default:
255 break;
256 }
257 }
258 }
259 return DELETED_2_02;
260}
261#endif
262
263#ifdef LWM2M_SERVER_MODE
264
265#define ID_AS_STRING_MAX_LEN 8
266
267static void dm_result_callback(lwm2m_transaction_t * transacP,
268 void * message)
269{
270 dm_data_t * dataP = (dm_data_t *)transacP->userData;
271
272 if (message == NULL)
273 {
274 dataP->callback(((lwm2m_client_t*)transacP->peerP)->internalID,
275 &dataP->uri,
276 COAP_503_SERVICE_UNAVAILABLE,
277 NULL, 0,
278 dataP->userData);
279 }
280 else
281 {
282 coap_packet_t * packet = (coap_packet_t *)message;
283
284 //if packet is a CREATE response and the instanceId was assigned by the client
285 if (packet->code == COAP_201_CREATED
286 && packet->location_path != NULL)
287 {
288 char * locationString = NULL;
289 int result = 0;
290 lwm2m_uri_t locationUri;
291
292 locationString = coap_get_multi_option_as_string(packet->location_path);
293 if (locationString == NULL)
294 {
295 LOG("Error: coap_get_multi_option_as_string() failed for Location_path option in dm_result_callback()\n");
296 return;
297 }
298
299 result = lwm2m_stringToUri(locationString, strlen(locationString), &locationUri);
300 if (result == 0)
301 {
302 LOG("Error: lwm2m_stringToUri() failed for Location_path option in dm_result_callback()\n");
303 lwm2m_free(locationString);
304 return;
305 }
306
307 ((dm_data_t*)transacP->userData)->uri.instanceId = locationUri.instanceId;
308 ((dm_data_t*)transacP->userData)->uri.flag = locationUri.flag;
309
310 lwm2m_free(locationString);
311 }
312
313 dataP->callback(((lwm2m_client_t*)transacP->peerP)->internalID,
314 &dataP->uri,
315 packet->code,
316 packet->payload,
317 packet->payload_len,
318 dataP->userData);
319 }
320 lwm2m_free(dataP);
321}
322
323static int prv_make_operation(lwm2m_context_t * contextP,
324 uint16_t clientID,
325 lwm2m_uri_t * uriP,
326 coap_method_t method,
327 uint8_t * buffer,
328 int length,
329 lwm2m_result_callback_t callback,
330 void * userData)
331{
332 lwm2m_client_t * clientP;
333 lwm2m_transaction_t * transaction;
334 dm_data_t * dataP;
335
336 clientP = (lwm2m_client_t *)lwm2m_list_find((lwm2m_list_t *)contextP->clientList, clientID);
337 if (clientP == NULL) return COAP_404_NOT_FOUND;
338
339 transaction = transaction_new(COAP_TYPE_CON, method, clientP->altPath, uriP, contextP->nextMID++, 4, NULL, ENDPOINT_CLIENT, (void *)clientP);
340 if (transaction == NULL) return INTERNAL_SERVER_ERROR_5_00;
341
342 if (buffer != NULL)
343 {
344 // TODO: Take care of fragmentation
345 coap_set_payload(transaction->message, buffer, length);
346 }
347
348 if (callback != NULL)
349 {
350 dataP = (dm_data_t *)lwm2m_malloc(sizeof(dm_data_t));
351 if (dataP == NULL)
352 {
353 transaction_free(transaction);
354 return COAP_500_INTERNAL_SERVER_ERROR;
355 }
356 memcpy(&dataP->uri, uriP, sizeof(lwm2m_uri_t));
357 dataP->callback = callback;
358 dataP->userData = userData;
359
360 transaction->callback = dm_result_callback;
361 transaction->userData = (void *)dataP;
362 }
363
364 contextP->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(contextP->transactionList, transaction);
365
366 return transaction_send(contextP, transaction);
367}
368
369int lwm2m_dm_read(lwm2m_context_t * contextP,
370 uint16_t clientID,
371 lwm2m_uri_t * uriP,
372 lwm2m_result_callback_t callback,
373 void * userData)
374{
375 return prv_make_operation(contextP, clientID, uriP,
376 COAP_GET, NULL, 0,
377 callback, userData);
378}
379
380int lwm2m_dm_write(lwm2m_context_t * contextP,
381 uint16_t clientID,
382 lwm2m_uri_t * uriP,
383 uint8_t * buffer,
384 int length,
385 lwm2m_result_callback_t callback,
386 void * userData)
387{
388 if (!LWM2M_URI_IS_SET_INSTANCE(uriP)
389 || length == 0)
390 {
391 return COAP_400_BAD_REQUEST;
392 }
393
394 if (LWM2M_URI_IS_SET_RESOURCE(uriP))
395 {
396 return prv_make_operation(contextP, clientID, uriP,
397 COAP_PUT, buffer, length,
398 callback, userData);
399 }
400 else
401 {
402 return prv_make_operation(contextP, clientID, uriP,
403 COAP_POST, buffer, length,
404 callback, userData);
405 }
406}
407
408int lwm2m_dm_execute(lwm2m_context_t * contextP,
409 uint16_t clientID,
410 lwm2m_uri_t * uriP,
411 uint8_t * buffer,
412 int length,
413 lwm2m_result_callback_t callback,
414 void * userData)
415{
416 if (!LWM2M_URI_IS_SET_RESOURCE(uriP))
417 {
418 return COAP_400_BAD_REQUEST;
419 }
420
421 return prv_make_operation(contextP, clientID, uriP,
422 COAP_POST, buffer, length,
423 callback, userData);
424}
425
426int lwm2m_dm_create(lwm2m_context_t * contextP,
427 uint16_t clientID,
428 lwm2m_uri_t * uriP,
429 uint8_t * buffer,
430 int length,
431 lwm2m_result_callback_t callback,
432 void * userData)
433{
434 if (LWM2M_URI_IS_SET_RESOURCE(uriP)
435 || length == 0)
436 {
437 return COAP_400_BAD_REQUEST;
438 }
439
440 return prv_make_operation(contextP, clientID, uriP,
441 COAP_POST, buffer, length,
442 callback, userData);
443}
444
445int lwm2m_dm_delete(lwm2m_context_t * contextP,
446 uint16_t clientID,
447 lwm2m_uri_t * uriP,
448 lwm2m_result_callback_t callback,
449 void * userData)
450{
451 if (!LWM2M_URI_IS_SET_INSTANCE(uriP)
452 || LWM2M_URI_IS_SET_RESOURCE(uriP))
453 {
454 return COAP_400_BAD_REQUEST;
455 }
456
457 return prv_make_operation(contextP, clientID, uriP,
458 COAP_DELETE, NULL, 0,
459 callback, userData);
460}
461#endif