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.
liblwm2m.c
00001 /******************************************************************************* 00002 * 00003 * Copyright (c) 2013, 2014 Intel Corporation and others. 00004 * All rights reserved. This program and the accompanying materials 00005 * are made available under the terms of the Eclipse Public License v1.0 00006 * and Eclipse Distribution License v1.0 which accompany this distribution. 00007 * 00008 * The Eclipse Public License is available at 00009 * http://www.eclipse.org/legal/epl-v10.html 00010 * The Eclipse Distribution License is available at 00011 * http://www.eclipse.org/org/documents/edl-v10.php. 00012 * 00013 * Contributors: 00014 * David Navarro, Intel Corporation - initial API and implementation 00015 * Fabien Fleutot - Please refer to git log 00016 * Simon Bernard - Please refer to git log 00017 * Toby Jaffey - Please refer to git log 00018 * Pascal Rieux - Please refer to git log 00019 * 00020 *******************************************************************************/ 00021 00022 /* 00023 Copyright (c) 2013, 2014 Intel Corporation 00024 00025 Redistribution and use in source and binary forms, with or without modification, 00026 are permitted provided that the following conditions are met: 00027 00028 * Redistributions of source code must retain the above copyright notice, 00029 this list of conditions and the following disclaimer. 00030 * Redistributions in binary form must reproduce the above copyright notice, 00031 this list of conditions and the following disclaimer in the documentation 00032 and/or other materials provided with the distribution. 00033 * Neither the name of Intel Corporation nor the names of its contributors 00034 may be used to endorse or promote products derived from this software 00035 without specific prior written permission. 00036 00037 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00038 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00039 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00040 IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 00041 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00042 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00043 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00044 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 00045 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 00046 THE POSSIBILITY OF SUCH DAMAGE. 00047 00048 David Navarro <david.navarro@intel.com> 00049 00050 */ 00051 00052 #include "internals.h" 00053 00054 #include <stdlib.h> 00055 #include <string.h> 00056 00057 #include <stdio.h> 00058 00059 00060 lwm2m_context_t * lwm2m_init(void * userData) 00061 { 00062 lwm2m_context_t * contextP; 00063 00064 LOG("Entering"); 00065 contextP = (lwm2m_context_t *)lwm2m_malloc(sizeof(lwm2m_context_t)); 00066 if (NULL != contextP) 00067 { 00068 memset(contextP, 0, sizeof(lwm2m_context_t)); 00069 contextP->userData = userData; 00070 srand((int)lwm2m_gettime()); 00071 contextP->nextMID = rand(); 00072 } 00073 00074 return contextP; 00075 } 00076 00077 #ifdef LWM2M_CLIENT_MODE 00078 void lwm2m_deregister(lwm2m_context_t * context) 00079 { 00080 lwm2m_server_t * server = context->serverList; 00081 00082 LOG("Entering"); 00083 while (NULL != server) 00084 { 00085 registration_deregister(context, server); 00086 server = server->next; 00087 } 00088 } 00089 00090 static void prv_deleteServer(lwm2m_server_t * serverP) 00091 { 00092 // TODO parse transaction and observation to remove the ones related to this server 00093 if (NULL != serverP->location) 00094 { 00095 lwm2m_free(serverP->location); 00096 } 00097 free_block1_buffer(serverP->block1Data); 00098 lwm2m_free(serverP); 00099 } 00100 00101 static void prv_deleteServerList(lwm2m_context_t * context) 00102 { 00103 while (NULL != context->serverList) 00104 { 00105 lwm2m_server_t * server; 00106 server = context->serverList; 00107 context->serverList = server->next; 00108 prv_deleteServer(server); 00109 } 00110 } 00111 00112 static void prv_deleteBootstrapServer(lwm2m_server_t * serverP) 00113 { 00114 // TODO should we free location as in prv_deleteServer ? 00115 // TODO should we parse transaction and observation to remove the ones related to this server ? 00116 free_block1_buffer(serverP->block1Data); 00117 lwm2m_free(serverP); 00118 } 00119 00120 static void prv_deleteBootstrapServerList(lwm2m_context_t * context) 00121 { 00122 while (NULL != context->bootstrapServerList) 00123 { 00124 lwm2m_server_t * server; 00125 server = context->bootstrapServerList; 00126 context->bootstrapServerList = server->next; 00127 prv_deleteBootstrapServer(server); 00128 } 00129 } 00130 00131 static void prv_deleteObservedList(lwm2m_context_t * contextP) 00132 { 00133 while (NULL != contextP->observedList) 00134 { 00135 lwm2m_observed_t * targetP; 00136 lwm2m_watcher_t * watcherP; 00137 00138 targetP = contextP->observedList; 00139 contextP->observedList = contextP->observedList->next; 00140 00141 for (watcherP = targetP->watcherList ; watcherP != NULL ; watcherP = watcherP->next) 00142 { 00143 if (watcherP->parameters != NULL) lwm2m_free(watcherP->parameters); 00144 } 00145 LWM2M_LIST_FREE(targetP->watcherList); 00146 00147 lwm2m_free(targetP); 00148 } 00149 } 00150 #endif 00151 00152 void prv_deleteTransactionList(lwm2m_context_t * context) 00153 { 00154 while (NULL != context->transactionList) 00155 { 00156 lwm2m_transaction_t * transaction; 00157 00158 transaction = context->transactionList; 00159 context->transactionList = context->transactionList->next; 00160 transaction_free(transaction); 00161 } 00162 } 00163 00164 void lwm2m_close(lwm2m_context_t * contextP) 00165 { 00166 #ifdef LWM2M_CLIENT_MODE 00167 00168 LOG("Entering"); 00169 lwm2m_deregister(contextP); 00170 prv_deleteServerList(contextP); 00171 prv_deleteBootstrapServerList(contextP); 00172 prv_deleteObservedList(contextP); 00173 lwm2m_free(contextP->endpointName); 00174 if (contextP->msisdn != NULL) 00175 { 00176 lwm2m_free(contextP->msisdn); 00177 } 00178 if (contextP->altPath != NULL) 00179 { 00180 lwm2m_free(contextP->altPath); 00181 } 00182 00183 #endif 00184 00185 #ifdef LWM2M_SERVER_MODE 00186 while (NULL != contextP->clientList) 00187 { 00188 lwm2m_client_t * clientP; 00189 00190 clientP = contextP->clientList; 00191 contextP->clientList = contextP->clientList->next; 00192 00193 registration_freeClient(clientP); 00194 } 00195 #endif 00196 00197 prv_deleteTransactionList(contextP); 00198 lwm2m_free(contextP); 00199 } 00200 00201 #ifdef LWM2M_CLIENT_MODE 00202 static int prv_refreshServerList(lwm2m_context_t * contextP) 00203 { 00204 lwm2m_server_t * targetP; 00205 lwm2m_server_t * nextP; 00206 00207 // Remove all servers marked as dirty 00208 targetP = contextP->bootstrapServerList; 00209 contextP->bootstrapServerList = NULL; 00210 while (targetP != NULL) 00211 { 00212 nextP = targetP->next; 00213 targetP->next = NULL; 00214 if (!targetP->dirty) 00215 { 00216 targetP->status = STATE_DEREGISTERED; 00217 contextP->bootstrapServerList = (lwm2m_server_t *)LWM2M_LIST_ADD(contextP->bootstrapServerList, targetP); 00218 } 00219 else 00220 { 00221 prv_deleteServer(targetP); 00222 } 00223 targetP = nextP; 00224 } 00225 targetP = contextP->serverList; 00226 contextP->serverList = NULL; 00227 while (targetP != NULL) 00228 { 00229 nextP = targetP->next; 00230 targetP->next = NULL; 00231 if (!targetP->dirty) 00232 { 00233 // TODO: Should we revert the status to STATE_DEREGISTERED ? 00234 contextP->serverList = (lwm2m_server_t *)LWM2M_LIST_ADD(contextP->serverList, targetP); 00235 } 00236 else 00237 { 00238 prv_deleteServer(targetP); 00239 } 00240 targetP = nextP; 00241 } 00242 00243 return object_getServers(contextP); 00244 } 00245 00246 int lwm2m_configure(lwm2m_context_t * contextP, 00247 const char * endpointName, 00248 const char * msisdn, 00249 const char * altPath, 00250 uint16_t numObject, 00251 lwm2m_object_t * objectList[]) 00252 { 00253 int i; 00254 uint8_t found; 00255 00256 LOG_ARG("endpointName: \"%s\", msisdn: \"%s\", altPath: \"%s\", numObject: %d", endpointName, msisdn, altPath, numObject); 00257 // This API can be called only once for now 00258 if (contextP->endpointName != NULL || contextP->objectList != NULL) return COAP_400_BAD_REQUEST; 00259 00260 if (endpointName == NULL) return COAP_400_BAD_REQUEST; 00261 if (numObject < 3) return COAP_400_BAD_REQUEST; 00262 // Check that mandatory objects are present 00263 found = 0; 00264 for (i = 0 ; i < numObject ; i++) 00265 { 00266 if (objectList[i]->objID == LWM2M_SECURITY_OBJECT_ID) found |= 0x01; 00267 if (objectList[i]->objID == LWM2M_SERVER_OBJECT_ID) found |= 0x02; 00268 if (objectList[i]->objID == LWM2M_DEVICE_OBJECT_ID) found |= 0x04; 00269 } 00270 if (found != 0x07) return COAP_400_BAD_REQUEST; 00271 if (altPath != NULL) 00272 { 00273 if (0 == utils_isAltPathValid(altPath)) 00274 { 00275 return COAP_400_BAD_REQUEST; 00276 } 00277 if (altPath[1] == 0) 00278 { 00279 altPath = NULL; 00280 } 00281 } 00282 contextP->endpointName = lwm2m_strdup(endpointName); 00283 if (contextP->endpointName == NULL) 00284 { 00285 return COAP_500_INTERNAL_SERVER_ERROR; 00286 } 00287 00288 if (msisdn != NULL) 00289 { 00290 contextP->msisdn = lwm2m_strdup(msisdn); 00291 if (contextP->msisdn == NULL) 00292 { 00293 return COAP_500_INTERNAL_SERVER_ERROR; 00294 } 00295 } 00296 00297 if (altPath != NULL) 00298 { 00299 contextP->altPath = lwm2m_strdup(altPath); 00300 if (contextP->altPath == NULL) 00301 { 00302 return COAP_500_INTERNAL_SERVER_ERROR; 00303 } 00304 } 00305 00306 for (i = 0; i < numObject; i++) 00307 { 00308 objectList[i]->next = NULL; 00309 contextP->objectList = (lwm2m_object_t *)LWM2M_LIST_ADD(contextP->objectList, objectList[i]); 00310 } 00311 00312 return COAP_NO_ERROR; 00313 } 00314 00315 int lwm2m_add_object(lwm2m_context_t * contextP, 00316 lwm2m_object_t * objectP) 00317 { 00318 lwm2m_object_t * targetP; 00319 00320 LOG_ARG("ID: %d", objectP->objID); 00321 targetP = (lwm2m_object_t *)LWM2M_LIST_FIND(contextP->objectList, objectP->objID); 00322 if (targetP != NULL) return COAP_406_NOT_ACCEPTABLE; 00323 objectP->next = NULL; 00324 00325 contextP->objectList = (lwm2m_object_t *)LWM2M_LIST_ADD(contextP->objectList, objectP); 00326 00327 if (contextP->state == STATE_READY) 00328 { 00329 return lwm2m_update_registration(contextP, 0, true); 00330 } 00331 00332 return COAP_NO_ERROR; 00333 } 00334 00335 int lwm2m_remove_object(lwm2m_context_t * contextP, 00336 uint16_t id) 00337 { 00338 lwm2m_object_t * targetP; 00339 00340 LOG_ARG("ID: %d", id); 00341 contextP->objectList = (lwm2m_object_t *)LWM2M_LIST_RM(contextP->objectList, id, &targetP); 00342 00343 if (targetP == NULL) return COAP_404_NOT_FOUND; 00344 00345 if (contextP->state == STATE_READY) 00346 { 00347 return lwm2m_update_registration(contextP, 0, true); 00348 } 00349 00350 return 0; 00351 } 00352 00353 #endif 00354 00355 00356 int lwm2m_step(lwm2m_context_t * contextP, 00357 time_t * timeoutP) 00358 { 00359 time_t tv_sec; 00360 int result; 00361 00362 LOG_ARG("timeoutP: %" PRId64, *timeoutP); 00363 tv_sec = lwm2m_gettime(); 00364 if (tv_sec < 0) return COAP_500_INTERNAL_SERVER_ERROR; 00365 00366 #ifdef LWM2M_CLIENT_MODE 00367 LOG_ARG("State: %s", STR_STATE(contextP->state)); 00368 // state can also be modified in bootstrap_handleCommand(). 00369 00370 next_step: 00371 switch (contextP->state) 00372 { 00373 case STATE_INITIAL: 00374 if (0 != prv_refreshServerList(contextP)) return COAP_503_SERVICE_UNAVAILABLE; 00375 if (contextP->serverList != NULL) 00376 { 00377 contextP->state = STATE_REGISTER_REQUIRED; 00378 } 00379 else 00380 { 00381 // Bootstrapping 00382 contextP->state = STATE_BOOTSTRAP_REQUIRED; 00383 } 00384 goto next_step; 00385 break; 00386 00387 case STATE_BOOTSTRAP_REQUIRED: 00388 #ifdef LWM2M_BOOTSTRAP 00389 if (contextP->bootstrapServerList != NULL) 00390 { 00391 bootstrap_start(contextP); 00392 contextP->state = STATE_BOOTSTRAPPING; 00393 bootstrap_step(contextP, tv_sec, timeoutP); 00394 } 00395 else 00396 #endif 00397 { 00398 return COAP_503_SERVICE_UNAVAILABLE; 00399 } 00400 break; 00401 00402 #ifdef LWM2M_BOOTSTRAP 00403 case STATE_BOOTSTRAPPING: 00404 switch (bootstrap_getStatus(contextP)) 00405 { 00406 case STATE_BS_FINISHED: 00407 contextP->state = STATE_INITIAL; 00408 goto next_step; 00409 break; 00410 00411 case STATE_BS_FAILED: 00412 return COAP_503_SERVICE_UNAVAILABLE; 00413 00414 default: 00415 // keep on waiting 00416 bootstrap_step(contextP, tv_sec, timeoutP); 00417 break; 00418 } 00419 break; 00420 #endif 00421 case STATE_REGISTER_REQUIRED: 00422 result = registration_start(contextP); 00423 if (COAP_NO_ERROR != result) return result; 00424 contextP->state = STATE_REGISTERING; 00425 break; 00426 00427 case STATE_REGISTERING: 00428 { 00429 switch (registration_getStatus(contextP)) 00430 { 00431 case STATE_REGISTERED: 00432 contextP->state = STATE_READY; 00433 break; 00434 00435 case STATE_REG_FAILED: 00436 // TODO avoid infinite loop by checking the bootstrap info is different 00437 contextP->state = STATE_BOOTSTRAP_REQUIRED; 00438 goto next_step; 00439 break; 00440 00441 case STATE_REG_PENDING: 00442 default: 00443 // keep on waiting 00444 break; 00445 } 00446 } 00447 break; 00448 00449 case STATE_READY: 00450 if (registration_getStatus(contextP) == STATE_REG_FAILED) 00451 { 00452 // TODO avoid infinite loop by checking the bootstrap info is different 00453 contextP->state = STATE_BOOTSTRAP_REQUIRED; 00454 goto next_step; 00455 break; 00456 } 00457 break; 00458 00459 default: 00460 // do nothing 00461 break; 00462 } 00463 00464 observe_step(contextP, tv_sec, timeoutP); 00465 #endif 00466 00467 registration_step(contextP, tv_sec, timeoutP); 00468 transaction_step(contextP, tv_sec, timeoutP); 00469 00470 LOG_ARG("Final timeoutP: %" PRId64, *timeoutP); 00471 #ifdef LWM2M_CLIENT_MODE 00472 LOG_ARG("Final state: %s", STR_STATE(contextP->state)); 00473 #endif 00474 return 0; 00475 }
Generated on Thu Jul 14 2022 09:09:49 by
1.7.2