terence zhang / wakaama
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers objects.c Source File

objects.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  *    Toby Jaffey - Please refer to git log
00017  *    Benjamin Cabé - Please refer to git log
00018  *    Bosch Software Innovations GmbH - Please refer to git log
00019  *    Pascal Rieux - Please refer to git log
00020  *    
00021  *******************************************************************************/
00022 
00023 /*
00024  Copyright (c) 2013, 2014 Intel Corporation
00025 
00026  Redistribution and use in source and binary forms, with or without modification,
00027  are permitted provided that the following conditions are met:
00028 
00029      * Redistributions of source code must retain the above copyright notice,
00030        this list of conditions and the following disclaimer.
00031      * Redistributions in binary form must reproduce the above copyright notice,
00032        this list of conditions and the following disclaimer in the documentation
00033        and/or other materials provided with the distribution.
00034      * Neither the name of Intel Corporation nor the names of its contributors
00035        may be used to endorse or promote products derived from this software
00036        without specific prior written permission.
00037 
00038  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00039  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00040  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00041  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
00042  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00043  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00044  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00045  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00046  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
00047  THE POSSIBILITY OF SUCH DAMAGE.
00048 
00049  David Navarro <david.navarro@intel.com>
00050 
00051 */
00052 #include "internals.h"
00053 
00054 #ifdef LWM2M_CLIENT_MODE
00055 
00056 
00057 #include <stdlib.h>
00058 #include <string.h>
00059 #include <stdio.h>
00060 
00061 
00062 uint8_t object_checkReadable(lwm2m_context_t * contextP,
00063                              lwm2m_uri_t * uriP)
00064 {
00065     coap_status_t result;
00066     lwm2m_object_t * targetP;
00067     lwm2m_data_t * dataP = NULL;
00068     int size;
00069 
00070     LOG_URI(uriP);
00071     targetP = (lwm2m_object_t *)LWM2M_LIST_FIND(contextP->objectList, uriP->objectId);
00072     if (NULL == targetP) return COAP_404_NOT_FOUND;
00073     if (NULL == targetP->readFunc) return COAP_405_METHOD_NOT_ALLOWED;
00074 
00075     if (!LWM2M_URI_IS_SET_INSTANCE(uriP)) return COAP_205_CONTENT;
00076 
00077     if (NULL == lwm2m_list_find(targetP->instanceList, uriP->instanceId)) return COAP_404_NOT_FOUND;
00078 
00079     if (!LWM2M_URI_IS_SET_RESOURCE(uriP)) return COAP_205_CONTENT;
00080 
00081     size = 1;
00082     dataP = lwm2m_data_new(1);
00083     if (dataP == NULL) return COAP_500_INTERNAL_SERVER_ERROR;
00084 
00085     dataP->id = uriP->resourceId;
00086 
00087     result = targetP->readFunc(uriP->instanceId, &size, &dataP, targetP);
00088     lwm2m_data_free(1, dataP);
00089 
00090     return result;
00091 }
00092 
00093 uint8_t object_checkNumeric(lwm2m_context_t * contextP,
00094                             lwm2m_uri_t * uriP)
00095 {
00096     coap_status_t result;
00097     lwm2m_object_t * targetP;
00098     lwm2m_data_t * dataP = NULL;
00099     int size;
00100 
00101     LOG_URI(uriP);
00102     if (!LWM2M_URI_IS_SET_RESOURCE(uriP)) return COAP_405_METHOD_NOT_ALLOWED;
00103 
00104     targetP = (lwm2m_object_t *)LWM2M_LIST_FIND(contextP->objectList, uriP->objectId);
00105     if (NULL == targetP) return COAP_404_NOT_FOUND;
00106     if (NULL == targetP->readFunc) return COAP_405_METHOD_NOT_ALLOWED;
00107 
00108     size = 1;
00109     dataP = lwm2m_data_new(1);
00110     if (dataP == NULL) return COAP_500_INTERNAL_SERVER_ERROR;
00111 
00112     dataP->id = uriP->resourceId;
00113 
00114     result = targetP->readFunc(uriP->instanceId, &size, &dataP, targetP);
00115     if (result == COAP_205_CONTENT)
00116     {
00117         switch (dataP->type)
00118         {
00119         case LWM2M_TYPE_INTEGER:
00120         case LWM2M_TYPE_FLOAT:
00121             break;
00122         default:
00123             result = COAP_405_METHOD_NOT_ALLOWED;
00124         }
00125     }
00126 
00127     lwm2m_data_free(1, dataP);
00128 
00129     return result;
00130 }
00131 
00132 coap_status_t object_readData(lwm2m_context_t * contextP,
00133                                lwm2m_uri_t * uriP,
00134                                int * sizeP,
00135                                lwm2m_data_t ** dataP)
00136 {
00137     coap_status_t result;
00138     lwm2m_object_t * targetP;
00139 
00140     LOG_URI(uriP);
00141     targetP = (lwm2m_object_t *)LWM2M_LIST_FIND(contextP->objectList, uriP->objectId);
00142     if (NULL == targetP) return COAP_404_NOT_FOUND;
00143     if (NULL == targetP->readFunc) return COAP_405_METHOD_NOT_ALLOWED;
00144 
00145     if (LWM2M_URI_IS_SET_INSTANCE(uriP))
00146     {
00147         if (NULL == lwm2m_list_find(targetP->instanceList, uriP->instanceId)) return COAP_404_NOT_FOUND;
00148 
00149         // single instance read
00150         if (LWM2M_URI_IS_SET_RESOURCE(uriP))
00151         {
00152             *sizeP = 1;
00153             *dataP = lwm2m_data_new(*sizeP);
00154             if (*dataP == NULL) return COAP_500_INTERNAL_SERVER_ERROR;
00155 
00156             (*dataP)->id = uriP->resourceId;
00157         }
00158 
00159         result = targetP->readFunc(uriP->instanceId, sizeP, dataP, targetP);
00160     }
00161     else
00162     {
00163         // multiple object instances read
00164         lwm2m_list_t * instanceP;
00165         int i;
00166 
00167         result = COAP_205_CONTENT;
00168 
00169         *sizeP = 0;
00170         for (instanceP = targetP->instanceList; instanceP != NULL ; instanceP = instanceP->next)
00171         {
00172             (*sizeP)++;
00173         }
00174 
00175         if (*sizeP == 0)
00176         {
00177             *dataP = NULL;
00178         }
00179         else
00180         {
00181             *dataP = lwm2m_data_new(*sizeP);
00182             if (*dataP == NULL) return COAP_500_INTERNAL_SERVER_ERROR;
00183 
00184             instanceP = targetP->instanceList;
00185             i = 0;
00186             while (instanceP != NULL && result == COAP_205_CONTENT)
00187             {
00188                 result = targetP->readFunc(instanceP->id, (int*)&((*dataP)[i].value.asChildren.count), &((*dataP)[i].value.asChildren.array), targetP);
00189                 (*dataP)[i].type = LWM2M_TYPE_OBJECT_INSTANCE;
00190                 (*dataP)[i].id = instanceP->id;
00191                 i++;
00192                 instanceP = instanceP->next;
00193             }
00194         }
00195     }
00196 
00197     LOG_ARG("result: %u.%2u, size: %d", (result & 0xFF) >> 5, (result & 0x1F), *sizeP);
00198     return result;
00199 }
00200 
00201 coap_status_t object_read(lwm2m_context_t * contextP,
00202                           lwm2m_uri_t * uriP,
00203                           lwm2m_media_type_t * formatP,
00204                           uint8_t ** bufferP,
00205                           size_t * lengthP)
00206 {
00207     coap_status_t result;
00208     lwm2m_data_t * dataP = NULL;
00209     int size = 0;
00210     int res;
00211 
00212     LOG_URI(uriP);
00213     result = object_readData(contextP, uriP, &size, &dataP);
00214 
00215     if (result == COAP_205_CONTENT)
00216     {
00217         res = lwm2m_data_serialize(uriP, size, dataP, formatP, bufferP);
00218         if (res < 0)
00219         {
00220             result = COAP_500_INTERNAL_SERVER_ERROR;
00221         }
00222         else
00223         {
00224             *lengthP = (size_t)res;
00225         }
00226     }
00227     lwm2m_data_free(size, dataP);
00228 
00229     LOG_ARG("result: %u.%2u, length: %d", (result & 0xFF) >> 5, (result & 0x1F), *lengthP);
00230 
00231     return result;
00232 }
00233 
00234 coap_status_t object_write(lwm2m_context_t * contextP,
00235                            lwm2m_uri_t * uriP,
00236                            lwm2m_media_type_t format,
00237                            uint8_t * buffer,
00238                            size_t length)
00239 {
00240     coap_status_t result = NO_ERROR;
00241     lwm2m_object_t * targetP;
00242     lwm2m_data_t * dataP = NULL;
00243     int size = 0;
00244 
00245     LOG_URI(uriP);
00246     targetP = (lwm2m_object_t *)LWM2M_LIST_FIND(contextP->objectList, uriP->objectId);
00247     if (NULL == targetP)
00248     {
00249         result = COAP_404_NOT_FOUND;
00250     }
00251     else if (NULL == targetP->writeFunc)
00252     {
00253         result = COAP_405_METHOD_NOT_ALLOWED;
00254     }
00255     else
00256     {
00257         size = lwm2m_data_parse(uriP, buffer, length, format, &dataP);
00258         if (size == 0)
00259         {
00260             result = COAP_406_NOT_ACCEPTABLE;
00261         }
00262     }
00263     if (result == NO_ERROR)
00264     {
00265         result = targetP->writeFunc(uriP->instanceId, size, dataP, targetP);
00266         lwm2m_data_free(size, dataP);
00267     }
00268 
00269     LOG_ARG("result: %u.%2u", (result & 0xFF) >> 5, (result & 0x1F));
00270 
00271     return result;
00272 }
00273 
00274 coap_status_t object_execute(lwm2m_context_t * contextP,
00275                              lwm2m_uri_t * uriP,
00276                              uint8_t * buffer,
00277                              size_t length)
00278 {
00279     lwm2m_object_t * targetP;
00280 
00281     LOG_URI(uriP);
00282     targetP = (lwm2m_object_t *)LWM2M_LIST_FIND(contextP->objectList, uriP->objectId);
00283     if (NULL == targetP) return COAP_404_NOT_FOUND;
00284     if (NULL == targetP->executeFunc) return COAP_405_METHOD_NOT_ALLOWED;
00285     if (NULL == lwm2m_list_find(targetP->instanceList, uriP->instanceId)) return COAP_404_NOT_FOUND;
00286 
00287     return targetP->executeFunc(uriP->instanceId, uriP->resourceId, buffer, length, targetP);
00288 }
00289 
00290 coap_status_t object_create(lwm2m_context_t * contextP,
00291                             lwm2m_uri_t * uriP,
00292                             lwm2m_media_type_t format,
00293                             uint8_t * buffer,
00294                             size_t length)
00295 {
00296     lwm2m_object_t * targetP;
00297     lwm2m_data_t * dataP = NULL;
00298     int size = 0;
00299     uint8_t result;
00300 
00301     LOG_URI(uriP);
00302 
00303     if (length == 0 || buffer == 0)
00304     {
00305         return COAP_400_BAD_REQUEST;
00306     }
00307 
00308     targetP = (lwm2m_object_t *)LWM2M_LIST_FIND(contextP->objectList, uriP->objectId);
00309     if (NULL == targetP) return COAP_404_NOT_FOUND;
00310     if (NULL == targetP->createFunc) return COAP_405_METHOD_NOT_ALLOWED;
00311 
00312     size = lwm2m_data_parse(uriP, buffer, length, format, &dataP);
00313     if (size <= 0) return COAP_400_BAD_REQUEST;
00314 
00315     switch (dataP[0].type)
00316     {
00317     case LWM2M_TYPE_OBJECT:
00318         result = COAP_400_BAD_REQUEST;
00319         goto exit;
00320 
00321     case LWM2M_TYPE_OBJECT_INSTANCE:
00322         if (size != 1)
00323         {
00324             result = COAP_400_BAD_REQUEST;
00325             goto exit;
00326         }
00327         if (NULL != lwm2m_list_find(targetP->instanceList, dataP[0].id))
00328         {
00329             // Instance already exists
00330             result = COAP_406_NOT_ACCEPTABLE;
00331             goto exit;
00332         }
00333         result = targetP->createFunc(dataP[0].id, dataP[0].value.asChildren.count, dataP[0].value.asChildren.array, targetP);
00334         uriP->instanceId = dataP[0].id;
00335         uriP->flag |= LWM2M_URI_FLAG_INSTANCE_ID;
00336         break;
00337 
00338     default:
00339         if (!LWM2M_URI_IS_SET_INSTANCE(uriP))
00340         {
00341             uriP->instanceId = lwm2m_list_newId(targetP->instanceList);
00342             uriP->flag |= LWM2M_URI_FLAG_INSTANCE_ID;
00343         }
00344         result = targetP->createFunc(uriP->instanceId, size, dataP, targetP);
00345         break;
00346     }
00347 
00348 exit:
00349     lwm2m_data_free(size, dataP);
00350 
00351     LOG_ARG("result: %u.%2u", (result & 0xFF) >> 5, (result & 0x1F));
00352 
00353     return result;
00354 }
00355 
00356 coap_status_t object_delete(lwm2m_context_t * contextP,
00357                             lwm2m_uri_t * uriP)
00358 {
00359     lwm2m_object_t * objectP;
00360     coap_status_t result;
00361 
00362     LOG_URI(uriP);
00363     objectP = (lwm2m_object_t *)LWM2M_LIST_FIND(contextP->objectList, uriP->objectId);
00364     if (NULL == objectP) return COAP_404_NOT_FOUND;
00365     if (NULL == objectP->deleteFunc) return COAP_405_METHOD_NOT_ALLOWED;
00366 
00367     LOG("Entering");
00368 
00369     if (LWM2M_URI_IS_SET_INSTANCE(uriP))
00370     {
00371         result = objectP->deleteFunc(uriP->instanceId, objectP);
00372     }
00373     else
00374     {
00375         lwm2m_list_t * instanceP;
00376 
00377         result = COAP_202_DELETED;
00378         instanceP = objectP->instanceList;
00379         while (NULL != instanceP
00380             && result == COAP_202_DELETED)
00381         {
00382             result = objectP->deleteFunc(instanceP->id, objectP);
00383             instanceP = objectP->instanceList;
00384         }
00385     }
00386 
00387     LOG_ARG("result: %u.%2u", (result & 0xFF) >> 5, (result & 0x1F));
00388 
00389     return result;
00390 }
00391 
00392 coap_status_t object_discover(lwm2m_context_t * contextP,
00393                               lwm2m_uri_t * uriP,
00394                               lwm2m_server_t * serverP,
00395                               uint8_t ** bufferP,
00396                               size_t * lengthP)
00397 {
00398     coap_status_t result;
00399     lwm2m_object_t * targetP;
00400     lwm2m_data_t * dataP = NULL;
00401     int size = 0;
00402 
00403     LOG_URI(uriP);
00404     targetP = (lwm2m_object_t *)LWM2M_LIST_FIND(contextP->objectList, uriP->objectId);
00405     if (NULL == targetP) return COAP_404_NOT_FOUND;
00406     if (NULL == targetP->discoverFunc) return COAP_501_NOT_IMPLEMENTED;
00407 
00408     if (LWM2M_URI_IS_SET_INSTANCE(uriP))
00409     {
00410         if (NULL == lwm2m_list_find(targetP->instanceList, uriP->instanceId)) return COAP_404_NOT_FOUND;
00411 
00412         // single instance read
00413         if (LWM2M_URI_IS_SET_RESOURCE(uriP))
00414         {
00415             size = 1;
00416             dataP = lwm2m_data_new(size);
00417             if (dataP == NULL) return COAP_500_INTERNAL_SERVER_ERROR;
00418 
00419             dataP->id = uriP->resourceId;
00420         }
00421 
00422         result = targetP->discoverFunc(uriP->instanceId, &size, &dataP, targetP);
00423     }
00424     else
00425     {
00426         // multiple object instances read
00427         lwm2m_list_t * instanceP;
00428         int i;
00429 
00430         result = COAP_205_CONTENT;
00431 
00432         size = 0;
00433         for (instanceP = targetP->instanceList; instanceP != NULL ; instanceP = instanceP->next)
00434         {
00435             size++;
00436         }
00437 
00438         if (size != 0)
00439         {
00440             dataP = lwm2m_data_new(size);
00441             if (dataP == NULL) return COAP_500_INTERNAL_SERVER_ERROR;
00442 
00443             instanceP = targetP->instanceList;
00444             i = 0;
00445             while (instanceP != NULL && result == COAP_205_CONTENT)
00446             {
00447                 result = targetP->discoverFunc(instanceP->id, (int*)&(dataP[i].value.asChildren.count), &(dataP[i].value.asChildren.array), targetP);
00448                 dataP[i].type = LWM2M_TYPE_OBJECT_INSTANCE;
00449                 dataP[i].id = instanceP->id;
00450                 i++;
00451                 instanceP = instanceP->next;
00452             }
00453         }
00454     }
00455 
00456     if (result == COAP_205_CONTENT)
00457     {
00458         int len;
00459 
00460         len = discover_serialize(contextP, uriP, serverP, size, dataP, bufferP);
00461         if (len <= 0) result = COAP_500_INTERNAL_SERVER_ERROR;
00462         else *lengthP = len;
00463     }
00464     lwm2m_data_free(size, dataP);
00465 
00466     LOG_ARG("result: %u.%2u", (result & 0xFF) >> 5, (result & 0x1F));
00467 
00468     return result;
00469 }
00470 
00471 bool object_isInstanceNew(lwm2m_context_t * contextP,
00472                           uint16_t objectId,
00473                           uint16_t instanceId)
00474 {
00475     lwm2m_object_t * targetP;
00476 
00477     LOG("Entering");
00478     targetP = (lwm2m_object_t *)LWM2M_LIST_FIND(contextP->objectList, objectId);
00479     if (targetP != NULL)
00480     {
00481         if (NULL != lwm2m_list_find(targetP->instanceList, instanceId))
00482         {
00483             return false;
00484         }
00485     }
00486 
00487     return true;
00488 }
00489 
00490 static int prv_getObjectTemplate(uint8_t * buffer,
00491                                  size_t length,
00492                                  uint16_t id)
00493 {
00494     int index;
00495     int result;
00496 
00497     if (length < REG_OBJECT_MIN_LEN) return -1;
00498 
00499     buffer[0] = '<';
00500     buffer[1] = '/';
00501     index = 2;
00502 
00503     result = utils_intCopy((char *)buffer + index, length - index, id);
00504     if (result < 0) return -1;
00505     index += result;
00506 
00507     if (length - index < REG_OBJECT_MIN_LEN - 3) return -1;
00508     buffer[index] = '/';
00509     index++;
00510 
00511     return index;
00512 }
00513 
00514 int object_getRegisterPayload(lwm2m_context_t * contextP,
00515                            uint8_t * buffer,
00516                            size_t bufferLen)
00517 {
00518     size_t index;
00519     int result;
00520     lwm2m_object_t * objectP;
00521 
00522     LOG("Entering");
00523     // index can not be greater than bufferLen
00524     index = 0;
00525 
00526     result = utils_stringCopy((char *)buffer, bufferLen, REG_START);
00527     if (result < 0) return 0;
00528     index += result;
00529 
00530     if ((contextP->altPath != NULL)
00531      && (contextP->altPath[0] != 0))
00532     {
00533         result = utils_stringCopy((char *)buffer + index, bufferLen - index, contextP->altPath);
00534     }
00535     else
00536     {
00537         result = utils_stringCopy((char *)buffer + index, bufferLen - index, REG_DEFAULT_PATH);
00538     }
00539     if (result < 0) return 0;
00540     index += result;
00541 
00542     result = utils_stringCopy((char *)buffer + index, bufferLen - index, REG_LWM2M_RESOURCE_TYPE);
00543     if (result < 0) return 0;
00544     index += result;
00545 
00546     for (objectP = contextP->objectList; objectP != NULL; objectP = objectP->next)
00547     {
00548         size_t start;
00549         size_t length;
00550 
00551         if (objectP->objID == LWM2M_SECURITY_OBJECT_ID) continue;
00552 
00553         start = index;
00554         result = prv_getObjectTemplate(buffer + index, bufferLen - index, objectP->objID);
00555         if (result < 0) return 0;
00556         length = result;
00557         index += length;
00558 
00559         if (objectP->instanceList == NULL)
00560         {
00561             index--;
00562             result = utils_stringCopy((char *)buffer + index, bufferLen - index, REG_PATH_END);
00563             if (result < 0) return 0;
00564             index += result;
00565         }
00566         else
00567         {
00568             lwm2m_list_t * targetP;
00569             for (targetP = objectP->instanceList ; targetP != NULL ; targetP = targetP->next)
00570             {
00571                 if (bufferLen - index <= length) return 0;
00572 
00573                 if (index != start + length)
00574                 {
00575                     memcpy(buffer + index, buffer + start, length);
00576                     index += length;
00577                 }
00578 
00579                 result = utils_intCopy((char *)buffer + index, bufferLen - index, targetP->id);
00580                 if (result < 0) return 0;
00581                 index += result;
00582 
00583                 result = utils_stringCopy((char *)buffer + index, bufferLen - index, REG_PATH_END);
00584                 if (result < 0) return 0;
00585                 index += result;
00586             }
00587         }
00588     }
00589 
00590     if (index > 0)
00591     {
00592         index = index - 1;  // remove trailing ','
00593     }
00594 
00595     buffer[index] = 0;
00596 
00597     return index;
00598 }
00599 
00600 static lwm2m_list_t * prv_findServerInstance(lwm2m_object_t * objectP,
00601                                              uint16_t shortID)
00602 {
00603     lwm2m_list_t * instanceP;
00604 
00605     instanceP = objectP->instanceList;
00606     while (NULL != instanceP)
00607     {
00608         int64_t value;
00609         lwm2m_data_t * dataP;
00610         int size;
00611 
00612         size = 1;
00613         dataP = lwm2m_data_new(size);
00614         if (dataP == NULL) return NULL;
00615         dataP->id = LWM2M_SERVER_SHORT_ID_ID;
00616 
00617         if (objectP->readFunc(instanceP->id, &size, &dataP, objectP) != COAP_205_CONTENT)
00618         {
00619             lwm2m_data_free(size, dataP);
00620             return NULL;
00621         }
00622 
00623         if (1 == lwm2m_data_decode_int(dataP, &value))
00624         {
00625             if (value == shortID)
00626             {
00627                 lwm2m_data_free(size, dataP);
00628                 break;
00629             }
00630         }
00631         lwm2m_data_free(size, dataP);
00632         instanceP = instanceP->next;
00633     }
00634 
00635     return instanceP;
00636 }
00637 
00638 static int prv_getMandatoryInfo(lwm2m_object_t * objectP,
00639                                 uint16_t instanceID,
00640                                 lwm2m_server_t * targetP)
00641 {
00642     lwm2m_data_t * dataP;
00643     int size;
00644     int64_t value;
00645 
00646     size = 2;
00647     dataP = lwm2m_data_new(size);
00648     if (dataP == NULL) return -1;
00649     dataP[0].id = LWM2M_SERVER_LIFETIME_ID;
00650     dataP[1].id = LWM2M_SERVER_BINDING_ID;
00651 
00652     if (objectP->readFunc(instanceID, &size, &dataP, objectP) != COAP_205_CONTENT)
00653     {
00654         lwm2m_data_free(size, dataP);
00655         return -1;
00656     }
00657 
00658     if (0 == lwm2m_data_decode_int(dataP, &value)
00659      || value < 0 || value >0xFFFFFFFF)             // This is an implementation limit
00660     {
00661         lwm2m_data_free(size, dataP);
00662         return -1;
00663     }
00664     targetP->lifetime = value;
00665 
00666     targetP->binding = utils_stringToBinding(dataP[1].value.asBuffer.buffer, dataP[1].value.asBuffer.length);
00667 
00668     lwm2m_data_free(size, dataP);
00669 
00670     if (targetP->binding == BINDING_UNKNOWN)
00671     {
00672         return -1;
00673     }
00674 
00675     return 0;
00676 }
00677 
00678 int object_getServers(lwm2m_context_t * contextP)
00679 {
00680     lwm2m_object_t * objectP;
00681     lwm2m_object_t * securityObjP = NULL;
00682     lwm2m_object_t * serverObjP = NULL;
00683     lwm2m_list_t * securityInstP;   // instanceID of the server in the LWM2M Security Object
00684 
00685     LOG("Entering");
00686 
00687     for (objectP = contextP->objectList; objectP != NULL; objectP = objectP->next)
00688     {
00689         if (objectP->objID == LWM2M_SECURITY_OBJECT_ID)
00690         {
00691             securityObjP = objectP;
00692         }
00693         else if (objectP->objID == LWM2M_SERVER_OBJECT_ID)
00694         {
00695             serverObjP = objectP;
00696         }
00697     }
00698 
00699     if (NULL == securityObjP) return -1;
00700 
00701     securityInstP = securityObjP->instanceList;
00702     while (securityInstP != NULL)
00703     {
00704         if (LWM2M_LIST_FIND(contextP->bootstrapServerList, securityInstP->id) == NULL
00705          && LWM2M_LIST_FIND(contextP->serverList, securityInstP->id) == NULL)
00706         {
00707             // This server is new. eg created by last bootstrap
00708 
00709             lwm2m_data_t * dataP;
00710             int size;
00711             lwm2m_server_t * targetP;
00712             bool isBootstrap;
00713             int64_t value = 0;
00714 
00715             size = 3;
00716             dataP = lwm2m_data_new(size);
00717             if (dataP == NULL) return -1;
00718             dataP[0].id = LWM2M_SECURITY_BOOTSTRAP_ID;
00719             dataP[1].id = LWM2M_SECURITY_SHORT_SERVER_ID;
00720             dataP[2].id = LWM2M_SECURITY_HOLD_OFF_ID;
00721 
00722             if (securityObjP->readFunc(securityInstP->id, &size, &dataP, securityObjP) != COAP_205_CONTENT)
00723             {
00724                 lwm2m_data_free(size, dataP);
00725                 return -1;
00726             }
00727 
00728             targetP = (lwm2m_server_t *)lwm2m_malloc(sizeof(lwm2m_server_t));
00729             if (targetP == NULL) {
00730                 lwm2m_data_free(size, dataP);
00731                 return -1;
00732             }
00733             memset(targetP, 0, sizeof(lwm2m_server_t));
00734             targetP->secObjInstID = securityInstP->id;
00735 
00736             if (0 == lwm2m_data_decode_bool(dataP + 0, &isBootstrap))
00737             {
00738                 lwm2m_free(targetP);
00739                 lwm2m_data_free(size, dataP);
00740                 return -1;
00741             }
00742 
00743             if (0 == lwm2m_data_decode_int(dataP + 1, &value)
00744              || value < (isBootstrap ? 0 : 1) || value > 0xFFFF)                // 0 is forbidden as a Short Server ID
00745             {
00746                 lwm2m_free(targetP);
00747                 lwm2m_data_free(size, dataP);
00748                 return -1;
00749             }
00750             targetP->shortID = value;
00751 
00752             if (isBootstrap == true)
00753             {
00754                 if (0 == lwm2m_data_decode_int(dataP + 2, &value)
00755                  || value < 0 || value > 0xFFFFFFFF)             // This is an implementation limit
00756                 {
00757                     lwm2m_free(targetP);
00758                     lwm2m_data_free(size, dataP);
00759                     return -1;
00760                 }
00761                 // lifetime of a bootstrap server is set to ClientHoldOffTime
00762                 targetP->lifetime = value;
00763 
00764                 contextP->bootstrapServerList = (lwm2m_server_t*)LWM2M_LIST_ADD(contextP->bootstrapServerList, targetP);
00765             }
00766             else
00767             {
00768                 lwm2m_list_t * serverInstP;     // instanceID of the server in the LWM2M Server Object
00769 
00770                 serverInstP = prv_findServerInstance(serverObjP, targetP->shortID);
00771                 if (serverInstP == NULL)
00772                 {
00773                     lwm2m_free(targetP);
00774                     lwm2m_data_free(size, dataP);
00775                     return -1;
00776                 }
00777                 if (0 != prv_getMandatoryInfo(serverObjP, serverInstP->id, targetP))
00778                 {
00779                     lwm2m_free(targetP);
00780                     lwm2m_data_free(size, dataP);
00781                     return -1;
00782                 }
00783                 targetP->status = STATE_DEREGISTERED;
00784                 contextP->serverList = (lwm2m_server_t*)LWM2M_LIST_ADD(contextP->serverList, targetP);
00785             }
00786             lwm2m_data_free(size, dataP);
00787         }
00788         securityInstP = securityInstP->next;
00789     }
00790 
00791     return 0;
00792 }
00793 
00794 coap_status_t object_createInstance(lwm2m_context_t * contextP,
00795                                     lwm2m_uri_t * uriP,
00796                                     lwm2m_data_t * dataP)
00797 {
00798     lwm2m_object_t * targetP;
00799 
00800     LOG_URI(uriP);
00801     targetP = (lwm2m_object_t *)LWM2M_LIST_FIND(contextP->objectList, uriP->objectId);
00802     if (NULL == targetP) return COAP_404_NOT_FOUND;
00803 
00804     if (NULL == targetP->createFunc) 
00805     {
00806         return COAP_405_METHOD_NOT_ALLOWED;
00807     }
00808 
00809     return targetP->createFunc(lwm2m_list_newId(targetP->instanceList), dataP->value.asChildren.count, dataP->value.asChildren.array, targetP);
00810 }
00811 
00812 coap_status_t object_writeInstance(lwm2m_context_t * contextP,
00813                             lwm2m_uri_t * uriP,
00814                             lwm2m_data_t * dataP)
00815 {
00816     lwm2m_object_t * targetP;
00817 
00818     LOG_URI(uriP);
00819     targetP = (lwm2m_object_t *)LWM2M_LIST_FIND(contextP->objectList, uriP->objectId);
00820     if (NULL == targetP) return COAP_404_NOT_FOUND;
00821 
00822     if (NULL == targetP->writeFunc) 
00823     {
00824         return COAP_405_METHOD_NOT_ALLOWED;
00825     }
00826 
00827     return targetP->writeFunc(dataP->id, dataP->value.asChildren.count, dataP->value.asChildren.array, targetP);
00828 }
00829 
00830 #endif