Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
share/object_server.c
- Committer:
- terencez
- Date:
- 2017-05-11
- Revision:
- 16:31c387e94b6d
- Parent:
- 15:d0f20339c1ad
File content as of revision 16:31c387e94b6d:
/******************************************************************************* * * Copyright (c) 2013, 2014 Intel Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Eclipse Distribution License v1.0 which accompany this distribution. * * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html * The Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * David Navarro, Intel Corporation - initial API and implementation * Julien Vermillard, Sierra Wireless * Bosch Software Innovations GmbH - Please refer to git log * Pascal Rieux - Please refer to git log * *******************************************************************************/ /* * Resources: * * Name | ID | Operations | Instances | Mandatory | Type | Range | Units | * Short ID | 0 | R | Single | Yes | Integer | 1-65535 | | * Lifetime | 1 | R/W | Single | Yes | Integer | | s | * Default Min Period | 2 | R/W | Single | No | Integer | | s | * Default Max Period | 3 | R/W | Single | No | Integer | | s | * Disable | 4 | E | Single | No | | | | * Disable Timeout | 5 | R/W | Single | No | Integer | | s | * Notification Storing | 6 | R/W | Single | Yes | Boolean | | | * Binding | 7 | R/W | Single | Yes | String | | | * Registration Update | 8 | E | Single | Yes | | | | * */ #include "liblwm2m.h" #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct _server_instance_ { struct _server_instance_ * next; // matches lwm2m_list_t::next uint16_t instanceId; // matches lwm2m_list_t::id uint16_t shortServerId; uint32_t lifetime; uint32_t defaultMinPeriod; uint32_t defaultMaxPeriod; uint32_t disableTimeout; bool storing; char binding[4]; } server_instance_t; static uint8_t prv_get_value(lwm2m_data_t * dataP, server_instance_t * targetP) { switch (dataP->id) { case LWM2M_SERVER_SHORT_ID_ID: lwm2m_data_encode_int(targetP->shortServerId, dataP); return COAP_205_CONTENT; case LWM2M_SERVER_LIFETIME_ID: lwm2m_data_encode_int(targetP->lifetime, dataP); return COAP_205_CONTENT; case LWM2M_SERVER_MIN_PERIOD_ID: lwm2m_data_encode_int(targetP->defaultMinPeriod, dataP); return COAP_205_CONTENT; case LWM2M_SERVER_MAX_PERIOD_ID: lwm2m_data_encode_int(targetP->defaultMaxPeriod, dataP); return COAP_205_CONTENT; case LWM2M_SERVER_DISABLE_ID: return COAP_405_METHOD_NOT_ALLOWED; case LWM2M_SERVER_TIMEOUT_ID: lwm2m_data_encode_int(targetP->disableTimeout, dataP); return COAP_205_CONTENT; case LWM2M_SERVER_STORING_ID: lwm2m_data_encode_bool(targetP->storing, dataP); return COAP_205_CONTENT; case LWM2M_SERVER_BINDING_ID: lwm2m_data_encode_string(targetP->binding, dataP); return COAP_205_CONTENT; case LWM2M_SERVER_UPDATE_ID: return COAP_405_METHOD_NOT_ALLOWED; default: return COAP_404_NOT_FOUND; } } static uint8_t prv_server_read(uint16_t instanceId, int * numDataP, lwm2m_data_t ** dataArrayP, lwm2m_object_t * objectP) { server_instance_t * targetP; uint8_t result; int i; targetP = (server_instance_t *)lwm2m_list_find(objectP->instanceList, instanceId); if (NULL == targetP) return COAP_404_NOT_FOUND; // is the server asking for the full instance ? if (*numDataP == 0) { uint16_t resList[] = { LWM2M_SERVER_SHORT_ID_ID, LWM2M_SERVER_LIFETIME_ID, LWM2M_SERVER_MIN_PERIOD_ID, LWM2M_SERVER_MAX_PERIOD_ID, LWM2M_SERVER_TIMEOUT_ID, LWM2M_SERVER_STORING_ID, LWM2M_SERVER_BINDING_ID }; int nbRes = sizeof(resList)/sizeof(uint16_t); *dataArrayP = lwm2m_data_new(nbRes); if (*dataArrayP == NULL) return COAP_500_INTERNAL_SERVER_ERROR; *numDataP = nbRes; for (i = 0 ; i < nbRes ; i++) { (*dataArrayP)[i].id = resList[i]; } } i = 0; do { result = prv_get_value((*dataArrayP) + i, targetP); i++; } while (i < *numDataP && result == COAP_205_CONTENT); return result; } static uint8_t prv_server_discover(uint16_t instanceId, int * numDataP, lwm2m_data_t ** dataArrayP, lwm2m_object_t * objectP) { uint8_t result; int i; result = COAP_205_CONTENT; // is the server asking for the full object ? if (*numDataP == 0) { uint16_t resList[] = { LWM2M_SERVER_SHORT_ID_ID, LWM2M_SERVER_LIFETIME_ID, LWM2M_SERVER_MIN_PERIOD_ID, LWM2M_SERVER_MAX_PERIOD_ID, LWM2M_SERVER_DISABLE_ID, LWM2M_SERVER_TIMEOUT_ID, LWM2M_SERVER_STORING_ID, LWM2M_SERVER_BINDING_ID, LWM2M_SERVER_UPDATE_ID }; int nbRes = sizeof(resList) / sizeof(uint16_t); *dataArrayP = lwm2m_data_new(nbRes); if (*dataArrayP == NULL) return COAP_500_INTERNAL_SERVER_ERROR; *numDataP = nbRes; for (i = 0; i < nbRes; i++) { (*dataArrayP)[i].id = resList[i]; } } else { for (i = 0; i < *numDataP && result == COAP_205_CONTENT; i++) { switch ((*dataArrayP)[i].id) { case LWM2M_SERVER_SHORT_ID_ID: case LWM2M_SERVER_LIFETIME_ID: case LWM2M_SERVER_MIN_PERIOD_ID: case LWM2M_SERVER_MAX_PERIOD_ID: case LWM2M_SERVER_DISABLE_ID: case LWM2M_SERVER_TIMEOUT_ID: case LWM2M_SERVER_STORING_ID: case LWM2M_SERVER_BINDING_ID: case LWM2M_SERVER_UPDATE_ID: break; default: result = COAP_404_NOT_FOUND; } } } return result; } static uint8_t prv_set_int_value(lwm2m_data_t * dataArray, uint32_t * data) { uint8_t result; int64_t value; if (1 == lwm2m_data_decode_int(dataArray, &value)) { if (value >= 0 && value <= 0xFFFFFFFF) { *data = value; result = COAP_204_CHANGED; } else { result = COAP_406_NOT_ACCEPTABLE; } } else { result = COAP_400_BAD_REQUEST; } return result; } static uint8_t prv_server_write(uint16_t instanceId, int numData, lwm2m_data_t * dataArray, lwm2m_object_t * objectP) { server_instance_t * targetP; int i; uint8_t result; targetP = (server_instance_t *)lwm2m_list_find(objectP->instanceList, instanceId); if (NULL == targetP) { return COAP_404_NOT_FOUND; } i = 0; do { switch (dataArray[i].id) { case LWM2M_SERVER_SHORT_ID_ID: { uint32_t value = targetP->shortServerId; result = prv_set_int_value(dataArray + i, &value); if (COAP_204_CHANGED == result) { if (0 < value && 0xFFFF >= value) { targetP->shortServerId = value; } else { result = COAP_406_NOT_ACCEPTABLE; } } } break; case LWM2M_SERVER_LIFETIME_ID: result = prv_set_int_value(dataArray + i, (uint32_t *)&(targetP->lifetime)); break; case LWM2M_SERVER_MIN_PERIOD_ID: result = prv_set_int_value(dataArray + i, &(targetP->defaultMinPeriod)); break; case LWM2M_SERVER_MAX_PERIOD_ID: result = prv_set_int_value(dataArray + i, &(targetP->defaultMaxPeriod)); break; case LWM2M_SERVER_DISABLE_ID: result = COAP_405_METHOD_NOT_ALLOWED; break; case LWM2M_SERVER_TIMEOUT_ID: result = prv_set_int_value(dataArray + i, &(targetP->disableTimeout)); break; case LWM2M_SERVER_STORING_ID: { bool value; if (1 == lwm2m_data_decode_bool(dataArray + i, &value)) { targetP->storing = value; result = COAP_204_CHANGED; } else { result = COAP_400_BAD_REQUEST; } } break; case LWM2M_SERVER_BINDING_ID: if ((dataArray[i].type == LWM2M_TYPE_STRING || dataArray[i].type == LWM2M_TYPE_OPAQUE) && dataArray[i].value.asBuffer.length > 0 && dataArray[i].value.asBuffer.length <= 3 && (strncmp((char*)dataArray[i].value.asBuffer.buffer, "U", dataArray[i].value.asBuffer.length) == 0 || strncmp((char*)dataArray[i].value.asBuffer.buffer, "UQ", dataArray[i].value.asBuffer.length) == 0 || strncmp((char*)dataArray[i].value.asBuffer.buffer, "S", dataArray[i].value.asBuffer.length) == 0 || strncmp((char*)dataArray[i].value.asBuffer.buffer, "SQ", dataArray[i].value.asBuffer.length) == 0 || strncmp((char*)dataArray[i].value.asBuffer.buffer, "US", dataArray[i].value.asBuffer.length) == 0 || strncmp((char*)dataArray[i].value.asBuffer.buffer, "UQS", dataArray[i].value.asBuffer.length) == 0)) { strncpy(targetP->binding, (char*)dataArray[i].value.asBuffer.buffer, dataArray[i].value.asBuffer.length); result = COAP_204_CHANGED; } else { result = COAP_400_BAD_REQUEST; } break; case LWM2M_SERVER_UPDATE_ID: result = COAP_405_METHOD_NOT_ALLOWED; break; default: return COAP_404_NOT_FOUND; } i++; } while (i < numData && result == COAP_204_CHANGED); return result; } static uint8_t prv_server_execute(uint16_t instanceId, uint16_t resourceId, uint8_t * buffer, int length, lwm2m_object_t * objectP) { server_instance_t * targetP; targetP = (server_instance_t *)lwm2m_list_find(objectP->instanceList, instanceId); if (NULL == targetP) return COAP_404_NOT_FOUND; switch (resourceId) { case LWM2M_SERVER_DISABLE_ID: // executed in core, if COAP_204_CHANGED is returned if (0 < targetP->disableTimeout) return COAP_204_CHANGED; else return COAP_405_METHOD_NOT_ALLOWED; case LWM2M_SERVER_UPDATE_ID: // executed in core, if COAP_204_CHANGED is returned return COAP_204_CHANGED; default: return COAP_405_METHOD_NOT_ALLOWED; } } static uint8_t prv_server_delete(uint16_t id, lwm2m_object_t * objectP) { server_instance_t * serverInstance; objectP->instanceList = lwm2m_list_remove(objectP->instanceList, id, (lwm2m_list_t **)&serverInstance); if (NULL == serverInstance) return COAP_404_NOT_FOUND; lwm2m_free(serverInstance); return COAP_202_DELETED; } static uint8_t prv_server_create(uint16_t instanceId, int numData, lwm2m_data_t * dataArray, lwm2m_object_t * objectP) { server_instance_t * serverInstance; uint8_t result; serverInstance = (server_instance_t *)lwm2m_malloc(sizeof(server_instance_t)); if (NULL == serverInstance) return COAP_500_INTERNAL_SERVER_ERROR; memset(serverInstance, 0, sizeof(server_instance_t)); serverInstance->instanceId = instanceId; objectP->instanceList = LWM2M_LIST_ADD(objectP->instanceList, serverInstance); result = prv_server_write(instanceId, numData, dataArray, objectP); if (result != COAP_204_CHANGED) { (void)prv_server_delete(instanceId, objectP); } else { result = COAP_201_CREATED; } return result; } void copy_server_object(lwm2m_object_t * objectDest, lwm2m_object_t * objectSrc) { memcpy(objectDest, objectSrc, sizeof(lwm2m_object_t)); objectDest->instanceList = NULL; objectDest->userData = NULL; server_instance_t * instanceSrc = (server_instance_t *)objectSrc->instanceList; server_instance_t * previousInstanceDest = NULL; while (instanceSrc != NULL) { server_instance_t * instanceDest = (server_instance_t *)lwm2m_malloc(sizeof(server_instance_t)); if (NULL == instanceDest) { return; } memcpy(instanceDest, instanceSrc, sizeof(server_instance_t)); // not sure it's necessary: strcpy(instanceDest->binding, instanceSrc->binding); instanceSrc = (server_instance_t *)instanceSrc->next; if (previousInstanceDest == NULL) { objectDest->instanceList = (lwm2m_list_t *)instanceDest; } else { previousInstanceDest->next = instanceDest; } previousInstanceDest = instanceDest; } } void display_server_object(lwm2m_object_t * object) { #ifdef WITH_LOGS fprintf(stdout, " /%u: Server object, instances:\r\n", object->objID); server_instance_t * serverInstance = (server_instance_t *)object->instanceList; while (serverInstance != NULL) { fprintf(stdout, " /%u/%u: instanceId: %u, shortServerId: %u, lifetime: %u, storing: %s, binding: %s\r\n", object->objID, serverInstance->instanceId, serverInstance->instanceId, serverInstance->shortServerId, serverInstance->lifetime, serverInstance->storing ? "true" : "false", serverInstance->binding); serverInstance = (server_instance_t *)serverInstance->next; } #endif } lwm2m_object_t * get_server_object(int serverId, const char* binding, int lifetime, bool storing) { lwm2m_object_t * serverObj; serverObj = (lwm2m_object_t *)lwm2m_malloc(sizeof(lwm2m_object_t)); if (NULL != serverObj) { server_instance_t * serverInstance; memset(serverObj, 0, sizeof(lwm2m_object_t)); serverObj->objID = 1; // Manually create an hardcoded server serverInstance = (server_instance_t *)lwm2m_malloc(sizeof(server_instance_t)); if (NULL == serverInstance) { lwm2m_free(serverObj); return NULL; } memset(serverInstance, 0, sizeof(server_instance_t)); serverInstance->instanceId = 0; serverInstance->shortServerId = serverId; serverInstance->lifetime = lifetime; serverInstance->storing = storing; memcpy (serverInstance->binding, binding, strlen(binding)+1); serverObj->instanceList = LWM2M_LIST_ADD(serverObj->instanceList, serverInstance); serverObj->readFunc = prv_server_read; serverObj->discoverFunc = prv_server_discover; serverObj->writeFunc = prv_server_write; serverObj->createFunc = prv_server_create; serverObj->deleteFunc = prv_server_delete; serverObj->executeFunc = prv_server_execute; } return serverObj; } void clean_server_object(lwm2m_object_t * object) { while (object->instanceList != NULL) { server_instance_t * serverInstance = (server_instance_t *)object->instanceList; object->instanceList = object->instanceList->next; lwm2m_free(serverInstance); } }