terence zhang / Mbed OS mbed-os-example-wakaama

Dependencies:   C12832 LM75B

Revision:
4:35892233a85d
Parent:
2:5a8853c481ad
--- a/object_server.c	Fri Apr 28 18:13:27 2017 +0800
+++ b/object_server.c	Fri Apr 28 18:20:36 2017 +0800
@@ -13,6 +13,8 @@
  * 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
  *    
  *******************************************************************************/
 
@@ -26,243 +28,398 @@
  *  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    | String  |         |       |
- *  Binding              |  7 |    R/W     |  Single   |    Yes    |         |         |       |
+ *  Notification Storing |  6 |    R/W     |  Single   |    Yes    | Boolean |         |       |
+ *  Binding              |  7 |    R/W     |  Single   |    Yes    | String  |         |       |
  *  Registration Update  |  8 |     E      |  Single   |    Yes    |         |         |       |
  *
  */
 
-#include "internals.h"
+#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;
+    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_DISABLE_ID:
+        return COAP_405_METHOD_NOT_ALLOWED;
+
+    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;
 
-#ifdef LWM2M_CLIENT_MODE
-#define RESOURCE_SHORTID_ID     0
-#define RESOURCE_LIFETIME_ID    1
-#define RESOURCE_MINPERIOD_ID   2
-#define RESOURCE_MAXPERIOD_ID   3
-#define RESOURCE_DISABLE_ID     4
-#define RESOURCE_TIMEOUT_ID     5
-#define RESOURCE_STORING_ID     6
-#define RESOURCE_BINDING_ID     7
-#define RESOURCE_UPDATE_ID      8
+    // 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_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;
+}
 
-#define LIFETIME_DEFAULT        86400
+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;
 
-coap_status_t object_server_read(lwm2m_context_t * contextP,
-                                 lwm2m_uri_t * uriP,
-                                 char ** bufferP,
-                                 int * lengthP)
-{
-    if (!LWM2M_URI_IS_SET_INSTANCE(uriP))
+    // is the server asking for the full object ?
+    if (*numDataP == 0)
     {
-        return COAP_501_NOT_IMPLEMENTED;
+        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
     {
-        lwm2m_server_t * serverP;
+        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;
+            }
+        }
+    }
 
-        serverP = (lwm2m_server_t *)lwm2m_list_find((lwm2m_list_t *)contextP->serverList, uriP->instanceId);
-        if (serverP == NULL) return COAP_404_NOT_FOUND;
+    return result;
+}
 
-        if (!LWM2M_URI_IS_SET_RESOURCE(uriP))
+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)
         {
-            return COAP_501_NOT_IMPLEMENTED;
+            *data = value;
+            result = COAP_204_CHANGED;
         }
         else
         {
-            switch (uriP->resourceId)
+            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;
+
+            result = prv_set_int_value(dataArray + i, &value);
+            if (COAP_204_CHANGED == result)
             {
-            case RESOURCE_SHORTID_ID:
-                *lengthP = lwm2m_int32ToPlainText(serverP->shortID, bufferP);
-                if (0 != *lengthP)
+                if (0 < value && value <= 0xFFFF)
                 {
-                    return COAP_205_CONTENT;
+                    targetP->shortServerId = value;
                 }
                 else
                 {
-                    return COAP_500_INTERNAL_SERVER_ERROR;
+                    result = COAP_406_NOT_ACCEPTABLE;
                 }
-                break;
-
-            case RESOURCE_LIFETIME_ID:
-                {
-                    int lifetime = serverP->lifetime;
-                    if (lifetime == 0) lifetime = LIFETIME_DEFAULT;
-
-                    *lengthP = lwm2m_int32ToPlainText(lifetime,bufferP);
+            }
+        }
+        break;
 
-                    if (0 != *lengthP)
-                    {
-                        return COAP_205_CONTENT;
-                    }
-                    else
-                    {
-                        return COAP_500_INTERNAL_SERVER_ERROR;
-                    }
-                }
-                break;
+        case LWM2M_SERVER_LIFETIME_ID:
+            result = prv_set_int_value(dataArray + i, (uint32_t *)&(targetP->lifetime));
+            break;
 
-            case RESOURCE_MINPERIOD_ID:
-                return COAP_404_NOT_FOUND;
-            case RESOURCE_MAXPERIOD_ID:
-                return COAP_404_NOT_FOUND;
-            case RESOURCE_TIMEOUT_ID:
-                return COAP_404_NOT_FOUND;
-            case RESOURCE_STORING_ID:
-                return COAP_501_NOT_IMPLEMENTED;
-            case RESOURCE_BINDING_ID:
-                {
-                    char * value;
-                    int len;
-                    switch (serverP->binding) {
-                    case BINDING_U:
-                        value = "U";
-                        *lengthP = 1;
-                        break;
-                    case BINDING_UQ:
-                        value = "UQ";
-                        *lengthP = 2;
-                        break;
-                    case BINDING_S:
-                        value="S";
-                        *lengthP = 1;
-                        break;
-                    case BINDING_SQ:
-                        value = "SQ";
-                        *lengthP = 2;
-                        break;
-                    case BINDING_US:
-                        value = "US";
-                        *lengthP = 2;
-                        break;
-                    case BINDING_UQS:
-                        value = "USQ";
-                        *lengthP = 3;
-                        break;
-                    default:
-                        return COAP_500_INTERNAL_SERVER_ERROR;
-                    }
-                    *bufferP = lwm2m_malloc(*lengthP);
-                    if (NULL == *bufferP) return COAP_500_INTERNAL_SERVER_ERROR;
-                    memcpy(*bufferP, value, *lengthP);
-                    return COAP_205_CONTENT;
-                }
-            default:
-                return COAP_405_METHOD_NOT_ALLOWED;
+        case LWM2M_SERVER_DISABLE_ID:
+            result = COAP_405_METHOD_NOT_ALLOWED;
+            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;
 }
 
-coap_status_t object_server_write(lwm2m_context_t * contextP,
-                                  lwm2m_uri_t * uriP,
-                                  char * buffer,
-                                  int length)
+static uint8_t prv_server_execute(uint16_t instanceId,
+                                  uint16_t resourceId,
+                                  uint8_t * buffer,
+                                  int length,
+                                  lwm2m_object_t * objectP)
+
 {
-    if (!LWM2M_URI_IS_SET_INSTANCE(uriP))
-    {
-        return COAP_501_NOT_IMPLEMENTED;
-    }
-    else
-    {
-        lwm2m_server_t * serverP;
-
-        serverP = (lwm2m_server_t *)lwm2m_list_find((lwm2m_list_t *)contextP->serverList, uriP->instanceId);
-        if (serverP == NULL) return COAP_404_NOT_FOUND;
+    server_instance_t * targetP;
 
-        if (!LWM2M_URI_IS_SET_RESOURCE(uriP))
-        {
-            return COAP_501_NOT_IMPLEMENTED;
-        }
-        else
-        {
-            switch (uriP->resourceId)
-            {
-            case RESOURCE_LIFETIME_ID:
-                return COAP_501_NOT_IMPLEMENTED;
-            case RESOURCE_MINPERIOD_ID:
-                return COAP_404_NOT_FOUND;
-            case RESOURCE_MAXPERIOD_ID:
-                return COAP_404_NOT_FOUND;
-            case RESOURCE_TIMEOUT_ID:
-                return COAP_404_NOT_FOUND;
-            case RESOURCE_STORING_ID:
-                return COAP_501_NOT_IMPLEMENTED;
-            case RESOURCE_BINDING_ID:
-                return COAP_501_NOT_IMPLEMENTED;
-            default:
-                return COAP_405_METHOD_NOT_ALLOWED;
-            }
-        }
-    }
-}
+    targetP = (server_instance_t *)lwm2m_list_find(objectP->instanceList, instanceId);
+    if (NULL == targetP) return COAP_404_NOT_FOUND;
 
-coap_status_t object_server_execute(lwm2m_context_t * contextP,
-                                    lwm2m_uri_t * uriP,
-                                    char * buffer,
-                                    int length)
-{
-    lwm2m_server_t * serverP;
+    switch (resourceId)
+    {
+    case LWM2M_SERVER_DISABLE_ID:
+        // executed in core, if COAP_204_CHANGED is returned
+        return COAP_204_CHANGED;
 
-    serverP = (lwm2m_server_t *)lwm2m_list_find((lwm2m_list_t *)contextP->serverList, uriP->instanceId);
-    if (serverP == NULL) return COAP_404_NOT_FOUND;
+    case LWM2M_SERVER_UPDATE_ID:
+        // executed in core, if COAP_204_CHANGED is returned
+        return COAP_204_CHANGED;
 
-    switch (uriP->resourceId)
-    {
-    case RESOURCE_DISABLE_ID:
-        return COAP_404_NOT_FOUND;
-    case RESOURCE_UPDATE_ID:
-        return COAP_501_NOT_IMPLEMENTED;
     default:
         return COAP_405_METHOD_NOT_ALLOWED;
     }
 }
 
-coap_status_t object_server_create(lwm2m_context_t * contextP,
-                                   lwm2m_uri_t * uriP,
-                                   char * buffer,
-                                   int length)
+static uint8_t prv_server_delete(uint16_t id,
+                                 lwm2m_object_t * objectP)
 {
-    lwm2m_server_t * serverP;
+    server_instance_t * serverInstance;
 
-    serverP = (lwm2m_server_t *)lwm2m_list_find((lwm2m_list_t *)contextP->serverList, uriP->instanceId);
-    if (serverP == NULL) return COAP_404_NOT_FOUND;
+    objectP->instanceList = lwm2m_list_remove(objectP->instanceList, id, (lwm2m_list_t **)&serverInstance);
+    if (NULL == serverInstance) return COAP_404_NOT_FOUND;
 
-    return COAP_501_NOT_IMPLEMENTED;
+    lwm2m_free(serverInstance);
+
+    return COAP_202_DELETED;
 }
 
-coap_status_t object_server_delete(lwm2m_context_t * contextP,
-                                   lwm2m_uri_t * uriP)
+static uint8_t prv_server_create(uint16_t instanceId,
+                                 int numData,
+                                 lwm2m_data_t * dataArray,
+                                 lwm2m_object_t * objectP)
 {
-    lwm2m_server_t * serverP;
+    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));
 
-    serverP = (lwm2m_server_t *)lwm2m_list_find((lwm2m_list_t *)contextP->serverList, uriP->instanceId);
-    if (serverP == NULL) return COAP_404_NOT_FOUND;
+    serverInstance->instanceId = instanceId;
+    objectP->instanceList = LWM2M_LIST_ADD(objectP->instanceList, serverInstance);
+
+    result = prv_server_write(instanceId, numData, dataArray, objectP);
 
-    return COAP_501_NOT_IMPLEMENTED;
+    if (result != COAP_204_CHANGED)
+    {
+        (void)prv_server_delete(instanceId, objectP);
+    }
+    else
+    {
+        result = COAP_201_CREATED;
+    }
+
+    return result;
 }
 
-coap_status_t object_security_create(lwm2m_context_t * contextP,
-                                     lwm2m_uri_t * uriP,
-                                     char * buffer,
-                                     int length)
+lwm2m_object_t * get_server_object()
 {
-    lwm2m_server_t * serverP;
+    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;
 
-    serverP = (lwm2m_server_t *)lwm2m_list_find((lwm2m_list_t *)contextP->serverList, uriP->instanceId);
-    if (serverP == NULL) return COAP_404_NOT_FOUND;
+        // Manually create an hardcoded server
+        serverInstance = (server_instance_t *)lwm2m_malloc(sizeof(server_instance_t));
+        if (NULL == serverInstance)
+        {
+            lwm2m_free(serverObj);
+            return NULL;
+        }
 
-    return COAP_501_NOT_IMPLEMENTED;
+        memset(serverInstance, 0, sizeof(server_instance_t));
+        serverInstance->instanceId = 0;
+        serverInstance->shortServerId = 123;
+        serverInstance->lifetime = 300;
+        serverInstance->storing = false;
+        serverInstance->binding[0] = 'U';
+        serverObj->instanceList = LWM2M_LIST_ADD(serverObj->instanceList, serverInstance);
+
+        serverObj->readFunc = prv_server_read;
+        serverObj->writeFunc = prv_server_write;
+        serverObj->createFunc = prv_server_create;
+        serverObj->deleteFunc = prv_server_delete;
+        serverObj->executeFunc = prv_server_execute;
+        serverObj->discoverFunc = prv_server_discover;
+    }
+
+    return serverObj;
 }
 
-coap_status_t object_security_delete(lwm2m_context_t * contextP,
-                                     lwm2m_uri_t * uriP)
+void free_server_object(lwm2m_object_t * object)
 {
-    lwm2m_server_t * serverP;
-
-    serverP = (lwm2m_server_t *)lwm2m_list_find((lwm2m_list_t *)contextP->serverList, uriP->instanceId);
-    if (serverP == NULL) return COAP_404_NOT_FOUND;
-
-    return COAP_501_NOT_IMPLEMENTED;
+    while (object->instanceList != NULL)
+    {
+        server_instance_t * serverInstance = (server_instance_t *)object->instanceList;
+        object->instanceList = object->instanceList->next;
+        lwm2m_free(serverInstance);
+    }
+    lwm2m_free(object);
 }
-
-#endif