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.
Diff: wakaama/liblwm2m.c
- Revision:
- 5:917e1705e5c2
- Parent:
- 1:3549d3c3967c
- Child:
- 10:df97539c6ddd
--- a/wakaama/liblwm2m.c Fri Apr 28 18:20:36 2017 +0800
+++ b/wakaama/liblwm2m.c Fri Apr 28 18:30:50 2017 +0800
@@ -15,6 +15,7 @@
* 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
*
*******************************************************************************/
@@ -64,138 +65,129 @@
}
#endif
-lwm2m_context_t * lwm2m_init(char * endpointName,
- uint16_t numObject,
- lwm2m_object_t * objectList[],
- lwm2m_buffer_send_callback_t bufferSendCallback,
- void * bufferSendUserData)
+lwm2m_context_t * lwm2m_init(void * userData)
{
lwm2m_context_t * contextP;
- if (NULL == bufferSendCallback)
- return NULL;
-
-#ifdef LWM2M_CLIENT_MODE
- if (numObject != 0)
- {
- int i;
-
- for (i = 0 ; i < numObject ; i++)
- {
- if (objectList[i]->objID <= LWM2M_ACL_OBJECT_ID)
- {
- // Use of a reserved object ID
- return NULL;
- }
- }
- }
-#endif
-
+ LOG("Entering");
contextP = (lwm2m_context_t *)lwm2m_malloc(sizeof(lwm2m_context_t));
if (NULL != contextP)
{
memset(contextP, 0, sizeof(lwm2m_context_t));
- contextP->bufferSendCallback = bufferSendCallback;
- contextP->bufferSendUserData = bufferSendUserData;
- srand(time(NULL));
+ contextP->userData = userData;
+ srand((int)lwm2m_gettime());
contextP->nextMID = rand();
-#ifdef LWM2M_CLIENT_MODE
-
- contextP->endpointName = (char *)lwm2m_malloc(strlen(endpointName));
- if (contextP->endpointName == NULL)
- {
- lwm2m_free(contextP);
- return NULL;
- }
-
- strcpy(contextP->endpointName,endpointName);
- printf("name: %s, %s, %d\n",endpointName,contextP->endpointName,strlen(endpointName));
-
- //contextP->endpointName = strdup(endpointName);
-
- if (numObject != 0)
- {
- contextP->objectList = (lwm2m_object_t **)lwm2m_malloc(numObject * sizeof(lwm2m_object_t *));
- if (NULL != contextP->objectList)
- {
- memcpy(contextP->objectList, objectList, numObject * sizeof(lwm2m_object_t *));
- contextP->numObject = numObject;
- }
- else
- {
- lwm2m_free(contextP->endpointName);
- lwm2m_free(contextP);
- return NULL;
- }
- }
-#endif
}
return contextP;
}
-void lwm2m_close(lwm2m_context_t * contextP)
+#ifdef LWM2M_CLIENT_MODE
+void lwm2m_deregister(lwm2m_context_t * context)
{
- int i;
+ lwm2m_server_t * server = context->serverList;
-#ifdef LWM2M_CLIENT_MODE
- for (i = 0 ; i < contextP->numObject ; i++)
+ LOG("Entering");
+ while (NULL != server)
{
- if (NULL != contextP->objectList[i]->closeFunc)
- {
- contextP->objectList[i]->closeFunc(contextP->objectList[i]);
- }
- lwm2m_free(contextP->objectList[i]);
+ registration_deregister(context, server);
+ server = server->next;
}
+}
- if (NULL != contextP->bootstrapServer)
+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)
{
- if (NULL != contextP->bootstrapServer->uri) lwm2m_free (contextP->bootstrapServer->uri);
- if (NULL != contextP->bootstrapServer->security.privateKey) lwm2m_free (contextP->bootstrapServer->security.privateKey);
- if (NULL != contextP->bootstrapServer->security.publicKey) lwm2m_free (contextP->bootstrapServer->security.publicKey);
- lwm2m_free(contextP->bootstrapServer);
+ lwm2m_server_t * server;
+ server = context->serverList;
+ context->serverList = server->next;
+ prv_deleteServer(server);
}
-
- while (NULL != contextP->serverList)
- {
- lwm2m_server_t * targetP;
+}
- targetP = contextP->serverList;
- contextP->serverList = contextP->serverList->next;
-
- registration_deregister(contextP, targetP);
+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);
+}
- if (NULL != targetP->location) lwm2m_free(targetP->location);
- if (NULL != targetP->security.privateKey) lwm2m_free (targetP->security.privateKey);
- if (NULL != targetP->security.publicKey) lwm2m_free (targetP->security.publicKey);
- if (NULL != targetP->sms) lwm2m_free (targetP->sms);
- lwm2m_free(targetP);
+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;
- while (NULL != targetP->watcherList)
+ for (watcherP = targetP->watcherList ; watcherP != NULL ; watcherP = watcherP->next)
{
- lwm2m_watcher_t * watcherP;
+ if (watcherP->parameters != NULL) lwm2m_free(watcherP->parameters);
+ }
+ LWM2M_LIST_FREE(targetP->watcherList);
- watcherP = targetP->watcherList;
- targetP->watcherList = targetP->watcherList->next;
- lwm2m_free(watcherP);
- }
lwm2m_free(targetP);
}
+}
+#endif
- if (NULL != contextP->objectList)
+void prv_deleteTransactionList(lwm2m_context_t * context)
+{
+ while (NULL != context->transactionList)
{
- lwm2m_free(contextP->objectList);
+ 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);
}
- lwm2m_free(contextP->endpointName);
#endif
#ifdef LWM2M_SERVER_MODE
@@ -206,152 +198,286 @@
clientP = contextP->clientList;
contextP->clientList = contextP->clientList->next;
- prv_freeClient(clientP);
+ registration_freeClient(clientP);
}
#endif
- while (NULL != contextP->transactionList)
- {
- lwm2m_transaction_t * transacP;
-
- transacP = contextP->transactionList;
- contextP->transactionList = contextP->transactionList->next;
-
- transaction_free(transacP);
- }
-
+ prv_deleteTransactionList(contextP);
lwm2m_free(contextP);
}
#ifdef LWM2M_CLIENT_MODE
-void lwm2m_set_bootstrap_server(lwm2m_context_t * contextP,
- lwm2m_bootstrap_server_t * serverP)
+static int prv_refreshServerList(lwm2m_context_t * contextP)
{
- if (NULL != contextP->bootstrapServer)
+ lwm2m_server_t * targetP;
+ lwm2m_server_t * nextP;
+
+ // Remove all servers marked as dirty
+ targetP = contextP->bootstrapServerList;
+ contextP->bootstrapServerList = NULL;
+ while (targetP != NULL)
{
- if (NULL != contextP->bootstrapServer->uri) lwm2m_free (contextP->bootstrapServer->uri);
- if (NULL != contextP->bootstrapServer->security.privateKey) lwm2m_free (contextP->bootstrapServer->security.privateKey);
- if (NULL != contextP->bootstrapServer->security.publicKey) lwm2m_free (contextP->bootstrapServer->security.publicKey);
- lwm2m_free(contextP->bootstrapServer);
+ 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;
}
- contextP->bootstrapServer = serverP;
+ 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_add_server(lwm2m_context_t * contextP,
- uint16_t shortID,
- uint32_t lifetime,
- char * sms,
- lwm2m_binding_t binding,
- void * sessionH,
- lwm2m_security_t * securityP)
+int lwm2m_configure(lwm2m_context_t * contextP,
+ const char * endpointName,
+ const char * msisdn,
+ const char * altPath,
+ uint16_t numObject,
+ lwm2m_object_t * objectList[])
{
- lwm2m_server_t * serverP;
- int status = COAP_500_INTERNAL_SERVER_ERROR;
+ int i;
+ uint8_t found;
- serverP = (lwm2m_server_t *)lwm2m_malloc(sizeof(lwm2m_server_t));
- if (serverP != NULL)
+ 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++)
{
- memset(serverP, 0, sizeof(lwm2m_server_t));
- memcpy(&(serverP->security), securityP, sizeof(lwm2m_security_t));
- serverP->shortID = shortID;
- serverP->lifetime = lifetime;
- serverP->binding = binding;
- if (sms != NULL)
+ 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)
{
- // copy the SMS number
- int len = strlen(sms);
- serverP->sms = (char*) lwm2m_malloc(strlen(sms)+1);
- memcpy(serverP->sms, sms, len+1);
+ altPath = NULL;
}
- serverP->sessionH = sessionH;
- contextP->serverList = (lwm2m_server_t*)LWM2M_LIST_ADD(contextP->serverList, serverP);
+ }
+ contextP->endpointName = lwm2m_strdup(endpointName);
+ if (contextP->endpointName == NULL)
+ {
+ return COAP_500_INTERNAL_SERVER_ERROR;
+ }
- status = COAP_NO_ERROR;
+ if (msisdn != NULL)
+ {
+ contextP->msisdn = lwm2m_strdup(msisdn);
+ if (contextP->msisdn == NULL)
+ {
+ return COAP_500_INTERNAL_SERVER_ERROR;
+ }
}
- return status;
+ 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;
}
-#endif
-int lwm2m_step(lwm2m_context_t * contextP, struct timeval * timeoutP)
+int lwm2m_add_object(lwm2m_context_t * contextP,
+ lwm2m_object_t * objectP)
{
- int ret =0;
- lwm2m_transaction_t * transacP;
- struct timeval tv;
- //struct timezone tz;
-#ifdef LWM2M_SERVER_MODE
- lwm2m_client_t * clientP;
+ 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
- ret = lwm2m_gettimeofday(&tv,NULL);
- if (0!=ret)
- return COAP_500_INTERNAL_SERVER_ERROR;
+int lwm2m_step(lwm2m_context_t * contextP,
+ time_t * timeoutP)
+{
+ time_t tv_sec;
+ int result;
- transacP = contextP->transactionList;
- while (transacP != NULL)
- {
- // transaction_send() may remove transaction from the linked list
- lwm2m_transaction_t * nextP = transacP->next;
- int removed = 0;
-
- if (transacP->retrans_time <= tv.tv_sec)
- {
- removed = transaction_send(contextP, transacP);
- }
-
- if (0 == removed)
- {
- time_t interval;
+ LOG_ARG("timeoutP: %" PRId64, *timeoutP);
+ tv_sec = lwm2m_gettime();
+ if (tv_sec < 0) return COAP_500_INTERNAL_SERVER_ERROR;
- if (transacP->retrans_time > tv.tv_sec)
- {
- interval = transacP->retrans_time - tv.tv_sec;
- }
- else
- {
- interval = 1;
- }
-
- if (timeoutP->tv_sec > interval)
- {
- timeoutP->tv_sec = interval;
- }
- }
+#ifdef LWM2M_CLIENT_MODE
+ LOG_ARG("State: %s", STR_STATE(contextP->state));
+ // state can also be modified in bootstrap_handleCommand().
- transacP = nextP;
- }
-
-#ifdef LWM2M_SERVER_MODE
- // monitor clients lifetime
- clientP = contextP->clientList;
- while (clientP != NULL)
+next_step:
+ switch (contextP->state)
{
- lwm2m_client_t * nextP = clientP->next;
-
- if (clientP->endOfLife <= tv.tv_sec)
+ case STATE_INITIAL:
+ if (0 != prv_refreshServerList(contextP)) return COAP_503_SERVICE_UNAVAILABLE;
+ if (contextP->serverList != NULL)
{
- contextP->clientList = (lwm2m_client_t *)LWM2M_LIST_RM(contextP->clientList, clientP->internalID, NULL);
- if (contextP->monitorCallback != NULL)
- {
- contextP->monitorCallback(clientP->internalID, NULL, DELETED_2_02, NULL, 0, contextP->monitorUserData);
- }
- prv_freeClient(clientP);
+ contextP->state = STATE_REGISTER_REQUIRED;
}
else
{
- time_t interval;
+ // Bootstrapping
+ contextP->state = STATE_BOOTSTRAP_REQUIRED;
+ }
+ goto next_step;
+ break;
- interval = clientP->endOfLife - tv.tv_sec;
+ 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;
- if (timeoutP->tv_sec > interval)
- {
- timeoutP->tv_sec = interval;
- }
+ default:
+ // keep on waiting
+ bootstrap_step(contextP, tv_sec, timeoutP);
+ break;
}
- clientP = nextP;
+ 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;
}