pick up wakaama files from https://github.com/eclipse/wakaama

Revision:
0:c2dff8cbb91a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/liblwm2m.c	Wed Apr 19 11:27:34 2017 +0000
@@ -0,0 +1,475 @@
+/*******************************************************************************
+ *
+ * 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
+ *    Fabien Fleutot - Please refer to git log
+ *    Simon Bernard - Please refer to git log
+ *    Toby Jaffey - Please refer to git log
+ *    Pascal Rieux - Please refer to git log
+ *    
+ *******************************************************************************/
+
+/*
+ Copyright (c) 2013, 2014 Intel Corporation
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+     * Redistributions of source code must retain the above copyright notice,
+       this list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above copyright notice,
+       this list of conditions and the following disclaimer in the documentation
+       and/or other materials provided with the distribution.
+     * Neither the name of Intel Corporation nor the names of its contributors
+       may be used to endorse or promote products derived from this software
+       without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ THE POSSIBILITY OF SUCH DAMAGE.
+
+ David Navarro <david.navarro@intel.com>
+
+*/
+
+#include "internals.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <stdio.h>
+
+
+lwm2m_context_t * lwm2m_init(void * userData)
+{
+    lwm2m_context_t * contextP;
+
+    LOG("Entering");
+    contextP = (lwm2m_context_t *)lwm2m_malloc(sizeof(lwm2m_context_t));
+    if (NULL != contextP)
+    {
+        memset(contextP, 0, sizeof(lwm2m_context_t));
+        contextP->userData = userData;
+        srand((int)lwm2m_gettime());
+        contextP->nextMID = rand();
+    }
+
+    return contextP;
+}
+
+#ifdef LWM2M_CLIENT_MODE
+void lwm2m_deregister(lwm2m_context_t * context)
+{
+    lwm2m_server_t * server = context->serverList;
+
+    LOG("Entering");
+    while (NULL != server)
+    {
+        registration_deregister(context, server);
+        server = server->next;
+    }
+}
+
+static void prv_deleteServer(lwm2m_server_t * serverP)
+{
+    // TODO parse transaction and observation to remove the ones related to this server
+    if (NULL != serverP->location)
+    {
+        lwm2m_free(serverP->location);
+    }
+    free_block1_buffer(serverP->block1Data);
+    lwm2m_free(serverP);
+}
+
+static void prv_deleteServerList(lwm2m_context_t * context)
+{
+    while (NULL != context->serverList)
+    {
+        lwm2m_server_t * server;
+        server = context->serverList;
+        context->serverList = server->next;
+        prv_deleteServer(server);
+    }
+}
+
+static void prv_deleteBootstrapServer(lwm2m_server_t * serverP)
+{
+    // TODO should we free location as in prv_deleteServer ?
+    // TODO should we parse transaction and observation to remove the ones related to this server ?
+    free_block1_buffer(serverP->block1Data);
+    lwm2m_free(serverP);
+}
+
+static void prv_deleteBootstrapServerList(lwm2m_context_t * context)
+{
+    while (NULL != context->bootstrapServerList)
+    {
+        lwm2m_server_t * server;
+        server = context->bootstrapServerList;
+        context->bootstrapServerList = server->next;
+        prv_deleteBootstrapServer(server);
+    }
+}
+
+static void prv_deleteObservedList(lwm2m_context_t * contextP)
+{
+    while (NULL != contextP->observedList)
+    {
+        lwm2m_observed_t * targetP;
+        lwm2m_watcher_t * watcherP;
+
+        targetP = contextP->observedList;
+        contextP->observedList = contextP->observedList->next;
+
+        for (watcherP = targetP->watcherList ; watcherP != NULL ; watcherP = watcherP->next)
+        {
+            if (watcherP->parameters != NULL) lwm2m_free(watcherP->parameters);
+        }
+        LWM2M_LIST_FREE(targetP->watcherList);
+
+        lwm2m_free(targetP);
+    }
+}
+#endif
+
+void prv_deleteTransactionList(lwm2m_context_t * context)
+{
+    while (NULL != context->transactionList)
+    {
+        lwm2m_transaction_t * transaction;
+
+        transaction = context->transactionList;
+        context->transactionList = context->transactionList->next;
+        transaction_free(transaction);
+    }
+}
+
+void lwm2m_close(lwm2m_context_t * contextP)
+{
+#ifdef LWM2M_CLIENT_MODE
+
+    LOG("Entering");
+    lwm2m_deregister(contextP);
+    prv_deleteServerList(contextP);
+    prv_deleteBootstrapServerList(contextP);
+    prv_deleteObservedList(contextP);
+    lwm2m_free(contextP->endpointName);
+    if (contextP->msisdn != NULL)
+    {
+        lwm2m_free(contextP->msisdn);
+    }
+    if (contextP->altPath != NULL)
+    {
+        lwm2m_free(contextP->altPath);
+    }
+
+#endif
+
+#ifdef LWM2M_SERVER_MODE
+    while (NULL != contextP->clientList)
+    {
+        lwm2m_client_t * clientP;
+
+        clientP = contextP->clientList;
+        contextP->clientList = contextP->clientList->next;
+
+        registration_freeClient(clientP);
+    }
+#endif
+
+    prv_deleteTransactionList(contextP);
+    lwm2m_free(contextP);
+}
+
+#ifdef LWM2M_CLIENT_MODE
+static int prv_refreshServerList(lwm2m_context_t * contextP)
+{
+    lwm2m_server_t * targetP;
+    lwm2m_server_t * nextP;
+
+    // Remove all servers marked as dirty
+    targetP = contextP->bootstrapServerList;
+    contextP->bootstrapServerList = NULL;
+    while (targetP != NULL)
+    {
+        nextP = targetP->next;
+        targetP->next = NULL;
+        if (!targetP->dirty)
+        {
+            targetP->status = STATE_DEREGISTERED;
+            contextP->bootstrapServerList = (lwm2m_server_t *)LWM2M_LIST_ADD(contextP->bootstrapServerList, targetP);
+        }
+        else
+        {
+            prv_deleteServer(targetP);
+        }
+        targetP = nextP;
+    }
+    targetP = contextP->serverList;
+    contextP->serverList = NULL;
+    while (targetP != NULL)
+    {
+        nextP = targetP->next;
+        targetP->next = NULL;
+        if (!targetP->dirty)
+        {
+            // TODO: Should we revert the status to STATE_DEREGISTERED ?
+            contextP->serverList = (lwm2m_server_t *)LWM2M_LIST_ADD(contextP->serverList, targetP);
+        }
+        else
+        {
+            prv_deleteServer(targetP);
+        }
+        targetP = nextP;
+    }
+
+    return object_getServers(contextP);
+}
+
+int lwm2m_configure(lwm2m_context_t * contextP,
+                    const char * endpointName,
+                    const char * msisdn,
+                    const char * altPath,
+                    uint16_t numObject,
+                    lwm2m_object_t * objectList[])
+{
+    int i;
+    uint8_t found;
+
+    LOG_ARG("endpointName: \"%s\", msisdn: \"%s\", altPath: \"%s\", numObject: %d", endpointName, msisdn, altPath, numObject);
+    // This API can be called only once for now
+    if (contextP->endpointName != NULL || contextP->objectList != NULL) return COAP_400_BAD_REQUEST;
+
+    if (endpointName == NULL) return COAP_400_BAD_REQUEST;
+    if (numObject < 3) return COAP_400_BAD_REQUEST;
+    // Check that mandatory objects are present
+    found = 0;
+    for (i = 0 ; i < numObject ; i++)
+    {
+        if (objectList[i]->objID == LWM2M_SECURITY_OBJECT_ID) found |= 0x01;
+        if (objectList[i]->objID == LWM2M_SERVER_OBJECT_ID) found |= 0x02;
+        if (objectList[i]->objID == LWM2M_DEVICE_OBJECT_ID) found |= 0x04;
+    }
+    if (found != 0x07) return COAP_400_BAD_REQUEST;
+    if (altPath != NULL)
+    {
+        if (0 == utils_isAltPathValid(altPath))
+        {
+            return COAP_400_BAD_REQUEST;
+        }
+        if (altPath[1] == 0)
+        {
+            altPath = NULL;
+        }
+    }
+    contextP->endpointName = lwm2m_strdup(endpointName);
+    if (contextP->endpointName == NULL)
+    {
+        return COAP_500_INTERNAL_SERVER_ERROR;
+    }
+
+    if (msisdn != NULL)
+    {
+        contextP->msisdn = lwm2m_strdup(msisdn);
+        if (contextP->msisdn == NULL)
+        {
+            return COAP_500_INTERNAL_SERVER_ERROR;
+        }
+    }
+
+    if (altPath != NULL)
+    {
+        contextP->altPath = lwm2m_strdup(altPath);
+        if (contextP->altPath == NULL)
+        {
+            return COAP_500_INTERNAL_SERVER_ERROR;
+        }
+    }
+
+    for (i = 0; i < numObject; i++)
+    {
+        objectList[i]->next = NULL;
+        contextP->objectList = (lwm2m_object_t *)LWM2M_LIST_ADD(contextP->objectList, objectList[i]);
+    }
+
+    return COAP_NO_ERROR;
+}
+
+int lwm2m_add_object(lwm2m_context_t * contextP,
+                     lwm2m_object_t * objectP)
+{
+    lwm2m_object_t * targetP;
+
+    LOG_ARG("ID: %d", objectP->objID);
+    targetP = (lwm2m_object_t *)LWM2M_LIST_FIND(contextP->objectList, objectP->objID);
+    if (targetP != NULL) return COAP_406_NOT_ACCEPTABLE;
+    objectP->next = NULL;
+
+    contextP->objectList = (lwm2m_object_t *)LWM2M_LIST_ADD(contextP->objectList, objectP);
+
+    if (contextP->state == STATE_READY)
+    {
+        return lwm2m_update_registration(contextP, 0, true);
+    }
+
+    return COAP_NO_ERROR;
+}
+
+int lwm2m_remove_object(lwm2m_context_t * contextP,
+                        uint16_t id)
+{
+    lwm2m_object_t * targetP;
+
+    LOG_ARG("ID: %d", id);
+    contextP->objectList = (lwm2m_object_t *)LWM2M_LIST_RM(contextP->objectList, id, &targetP);
+
+    if (targetP == NULL) return COAP_404_NOT_FOUND;
+
+    if (contextP->state == STATE_READY)
+    {
+        return lwm2m_update_registration(contextP, 0, true);
+    }
+
+    return 0;
+}
+
+#endif
+
+
+int lwm2m_step(lwm2m_context_t * contextP,
+               time_t * timeoutP)
+{
+    time_t tv_sec;
+    int result;
+
+    LOG_ARG("timeoutP: %" PRId64, *timeoutP);
+    tv_sec = lwm2m_gettime();
+    if (tv_sec < 0) return COAP_500_INTERNAL_SERVER_ERROR;
+
+#ifdef LWM2M_CLIENT_MODE
+    LOG_ARG("State: %s", STR_STATE(contextP->state));
+    // state can also be modified in bootstrap_handleCommand().
+
+next_step:
+    switch (contextP->state)
+    {
+    case STATE_INITIAL:
+        if (0 != prv_refreshServerList(contextP)) return COAP_503_SERVICE_UNAVAILABLE;
+        if (contextP->serverList != NULL)
+        {
+            contextP->state = STATE_REGISTER_REQUIRED;
+        }
+        else
+        {
+            // Bootstrapping
+            contextP->state = STATE_BOOTSTRAP_REQUIRED;
+        }
+        goto next_step;
+        break;
+
+    case STATE_BOOTSTRAP_REQUIRED:
+#ifdef LWM2M_BOOTSTRAP
+        if (contextP->bootstrapServerList != NULL)
+        {
+            bootstrap_start(contextP);
+            contextP->state = STATE_BOOTSTRAPPING;
+            bootstrap_step(contextP, tv_sec, timeoutP);
+        }
+        else
+#endif
+        {
+            return COAP_503_SERVICE_UNAVAILABLE;
+        }
+        break;
+
+#ifdef LWM2M_BOOTSTRAP
+    case STATE_BOOTSTRAPPING:
+        switch (bootstrap_getStatus(contextP))
+        {
+        case STATE_BS_FINISHED:
+            contextP->state = STATE_INITIAL;
+            goto next_step;
+            break;
+
+        case STATE_BS_FAILED:
+            return COAP_503_SERVICE_UNAVAILABLE;
+
+        default:
+            // keep on waiting
+            bootstrap_step(contextP, tv_sec, timeoutP);
+            break;
+        }
+        break;
+#endif
+    case STATE_REGISTER_REQUIRED:
+        result = registration_start(contextP);
+        if (COAP_NO_ERROR != result) return result;
+        contextP->state = STATE_REGISTERING;
+        break;
+
+    case STATE_REGISTERING:
+    {
+        switch (registration_getStatus(contextP))
+        {
+        case STATE_REGISTERED:
+            contextP->state = STATE_READY;
+            break;
+
+        case STATE_REG_FAILED:
+            // TODO avoid infinite loop by checking the bootstrap info is different
+            contextP->state = STATE_BOOTSTRAP_REQUIRED;
+            goto next_step;
+            break;
+
+        case STATE_REG_PENDING:
+        default:
+            // keep on waiting
+            break;
+        }
+    }
+    break;
+
+    case STATE_READY:
+        if (registration_getStatus(contextP) == STATE_REG_FAILED)
+        {
+            // TODO avoid infinite loop by checking the bootstrap info is different
+            contextP->state = STATE_BOOTSTRAP_REQUIRED;
+            goto next_step;
+            break;
+        }
+        break;
+
+    default:
+        // do nothing
+        break;
+    }
+
+    observe_step(contextP, tv_sec, timeoutP);
+#endif
+
+    registration_step(contextP, tv_sec, timeoutP);
+    transaction_step(contextP, tv_sec, timeoutP);
+
+    LOG_ARG("Final timeoutP: %" PRId64, *timeoutP);
+#ifdef LWM2M_CLIENT_MODE
+    LOG_ARG("Final state: %s", STR_STATE(contextP->state));
+#endif
+    return 0;
+}