terence zhang / wakaama
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers bootstrap.c Source File

bootstrap.c

00001 /*******************************************************************************
00002  *
00003  * Copyright (c) 2015 Sierra Wireless 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  *    Pascal Rieux - Please refer to git log
00015  *    Bosch Software Innovations GmbH - Please refer to git log
00016  *    David Navarro, Intel Corporation - Please refer to git log
00017  *
00018  *******************************************************************************/
00019 
00020 #include "internals.h"
00021 
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <stdio.h>
00025 
00026 #ifdef LWM2M_CLIENT_MODE
00027 #ifdef LWM2M_BOOTSTRAP
00028 
00029 #define PRV_QUERY_BUFFER_LENGTH 200
00030 
00031 
00032 static void prv_handleResponse(lwm2m_server_t * bootstrapServer,
00033                                coap_packet_t * message)
00034 {
00035     if (COAP_204_CHANGED == message->code)
00036     {
00037         LOG("Received ACK/2.04, Bootstrap pending, waiting for DEL/PUT from BS server...");
00038         bootstrapServer->status = STATE_BS_PENDING;
00039     }
00040     else
00041     {
00042         bootstrapServer->status = STATE_BS_FAILING;
00043     }
00044 }
00045 
00046 static void prv_handleBootstrapReply(lwm2m_transaction_t * transaction,
00047                                      void * message)
00048 {
00049     lwm2m_server_t * bootstrapServer = (lwm2m_server_t *)transaction->userData;
00050     coap_packet_t * coapMessage = (coap_packet_t *)message;
00051 
00052     LOG("Entering");
00053 
00054     if (bootstrapServer->status == STATE_BS_INITIATED)
00055     {
00056         if (NULL != coapMessage && COAP_TYPE_RST != coapMessage->type)
00057         {
00058             prv_handleResponse(bootstrapServer, coapMessage);
00059         }
00060         else
00061         {
00062             bootstrapServer->status = STATE_BS_FAILING;
00063         }
00064     }
00065 }
00066 
00067 // start a device initiated bootstrap
00068 static void prv_requestBootstrap(lwm2m_context_t * context,
00069                                  lwm2m_server_t * bootstrapServer)
00070 {
00071     char query[PRV_QUERY_BUFFER_LENGTH];
00072     int query_length = 0;
00073     int res;
00074 
00075     LOG("Entering");
00076 
00077     query_length = utils_stringCopy(query, PRV_QUERY_BUFFER_LENGTH, QUERY_STARTER QUERY_NAME);
00078     if (query_length < 0)
00079     {
00080         bootstrapServer->status = STATE_BS_FAILING;
00081         return;
00082     }
00083     res = utils_stringCopy(query + query_length, PRV_QUERY_BUFFER_LENGTH - query_length, context->endpointName);
00084     if (res < 0)
00085     {
00086         bootstrapServer->status = STATE_BS_FAILING;
00087         return;
00088     }
00089     query_length += res;
00090 
00091     if (bootstrapServer->sessionH == NULL)
00092     {
00093         bootstrapServer->sessionH = lwm2m_connect_server(bootstrapServer->secObjInstID, context->userData);
00094     }
00095 
00096     if (bootstrapServer->sessionH != NULL)
00097     {
00098         lwm2m_transaction_t * transaction = NULL;
00099 
00100         LOG("Bootstrap server connection opened");
00101 
00102         transaction = transaction_new(bootstrapServer->sessionH, COAP_POST, NULL, NULL, context->nextMID++, 4, NULL);
00103         if (transaction == NULL)
00104         {
00105             bootstrapServer->status = STATE_BS_FAILING;
00106             return;
00107         }
00108 
00109         coap_set_header_uri_path(transaction->message, "/"URI_BOOTSTRAP_SEGMENT);
00110         coap_set_header_uri_query(transaction->message, query);
00111         transaction->callback = prv_handleBootstrapReply;
00112         transaction->userData = (void *)bootstrapServer;
00113         context->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(context->transactionList, transaction);
00114         if (transaction_send(context, transaction) == 0)
00115         {
00116             LOG("CI bootstrap requested to BS server");
00117             bootstrapServer->status = STATE_BS_INITIATED;
00118         }
00119     }
00120     else
00121     {
00122         LOG("Connecting bootstrap server failed");
00123         bootstrapServer->status = STATE_BS_FAILED;
00124     }
00125 }
00126 
00127 void bootstrap_step(lwm2m_context_t * contextP,
00128                     uint32_t currentTime,
00129                     time_t * timeoutP)
00130 {
00131     lwm2m_server_t * targetP;
00132 
00133     LOG("entering");
00134     targetP = contextP->bootstrapServerList;
00135     while (targetP != NULL)
00136     {
00137         LOG_ARG("Initial status: %s", STR_STATUS(targetP->status));
00138         switch (targetP->status)
00139         {
00140         case STATE_DEREGISTERED:
00141             targetP->registration = currentTime + targetP->lifetime;
00142             targetP->status = STATE_BS_HOLD_OFF;
00143             if (*timeoutP > targetP->lifetime)
00144             {
00145                 *timeoutP = targetP->lifetime;
00146             }
00147             break;
00148 
00149         case STATE_BS_HOLD_OFF:
00150             if (targetP->registration <= currentTime)
00151             {
00152                 prv_requestBootstrap(contextP, targetP);
00153             }
00154             else if (*timeoutP > targetP->registration - currentTime)
00155             {
00156                 *timeoutP = targetP->registration - currentTime;
00157             }
00158             break;
00159 
00160         case STATE_BS_INITIATED:
00161             // waiting
00162             break;
00163 
00164         case STATE_BS_PENDING:
00165             // waiting
00166             break;
00167 
00168         case STATE_BS_FINISHING:
00169             if (targetP->sessionH != NULL)
00170             {
00171                 lwm2m_close_connection(targetP->sessionH, contextP->userData);
00172                 targetP->sessionH = NULL;
00173             }
00174             targetP->status = STATE_BS_FINISHED;
00175             *timeoutP = 0;
00176             break;
00177 
00178         case STATE_BS_FAILING:
00179             if (targetP->sessionH != NULL)
00180             {
00181                 lwm2m_close_connection(targetP->sessionH, contextP->userData);
00182                 targetP->sessionH = NULL;
00183             }
00184             targetP->status = STATE_BS_FAILED;
00185             *timeoutP = 0;
00186             break;
00187 
00188         default:
00189             break;
00190         }
00191         LOG_ARG("Finalal status: %s", STR_STATUS(targetP->status));
00192         targetP = targetP->next;
00193     }
00194 }
00195 
00196 coap_status_t bootstrap_handleFinish(lwm2m_context_t * context,
00197                                      void * fromSessionH)
00198 {
00199     lwm2m_server_t * bootstrapServer;
00200 
00201     LOG("Entering");
00202     bootstrapServer = utils_findBootstrapServer(context, fromSessionH);
00203     if (bootstrapServer != NULL
00204      && bootstrapServer->status == STATE_BS_PENDING)
00205     {
00206         LOG("Bootstrap server status changed to STATE_BS_FINISHING");
00207         bootstrapServer->status = STATE_BS_FINISHING;
00208         return COAP_204_CHANGED;
00209     }
00210 
00211     return COAP_IGNORE;
00212 }
00213 
00214 /*
00215  * Reset the bootstrap servers statuses
00216  *
00217  * TODO: handle LWM2M Servers the client is registered to ?
00218  *
00219  */
00220 void bootstrap_start(lwm2m_context_t * contextP)
00221 {
00222     lwm2m_server_t * targetP;
00223 
00224     LOG("Entering");
00225     targetP = contextP->bootstrapServerList;
00226     while (targetP != NULL)
00227     {
00228         targetP->status = STATE_DEREGISTERED;
00229         if (targetP->sessionH == NULL)
00230         {
00231             targetP->sessionH = lwm2m_connect_server(targetP->secObjInstID, contextP->userData);
00232         }
00233         targetP = targetP->next;
00234     }
00235 }
00236 
00237 /*
00238  * Returns STATE_BS_PENDING if at least one bootstrap is still pending
00239  * Returns STATE_BS_FINISHED if at least one bootstrap succeeded and no bootstrap is pending
00240  * Returns STATE_BS_FAILED if all bootstrap failed.
00241  */
00242 lwm2m_status_t bootstrap_getStatus(lwm2m_context_t * contextP)
00243 {
00244     lwm2m_server_t * targetP;
00245     lwm2m_status_t bs_status;
00246 
00247     LOG("Entering");
00248     targetP = contextP->bootstrapServerList;
00249     bs_status = STATE_BS_FAILED;
00250 
00251     while (targetP != NULL)
00252     {
00253         switch (targetP->status)
00254         {
00255             case STATE_BS_FINISHED:
00256                 if (bs_status == STATE_BS_FAILED)
00257                 {
00258                     bs_status = STATE_BS_FINISHED;
00259                 }
00260                 break;
00261 
00262             case STATE_BS_HOLD_OFF:
00263             case STATE_BS_INITIATED:
00264             case STATE_BS_PENDING:
00265             case STATE_BS_FINISHING:
00266                 bs_status = STATE_BS_PENDING;
00267                 break;
00268 
00269             default:
00270                 break;
00271         }
00272         targetP = targetP->next;
00273     }
00274 
00275     LOG_ARG("Returned status: %s", STR_STATUS(bs_status));
00276 
00277     return bs_status;
00278 }
00279 
00280 static coap_status_t prv_checkServerStatus(lwm2m_server_t * serverP)
00281 {
00282     LOG_ARG("Initial status: %s", STR_STATUS(serverP->status));
00283 
00284     switch (serverP->status)
00285     {
00286     case STATE_BS_HOLD_OFF:
00287         serverP->status = STATE_BS_PENDING;
00288         LOG_ARG("Status changed to: %s", STR_STATUS(serverP->status));
00289         break;
00290 
00291     case STATE_BS_INITIATED:
00292         // The ACK was probably lost
00293         serverP->status = STATE_BS_PENDING;
00294         LOG_ARG("Status changed to: %s", STR_STATUS(serverP->status));
00295         break;
00296 
00297     case STATE_DEREGISTERED:
00298         // server initiated bootstrap
00299     case STATE_BS_PENDING:
00300         // do nothing
00301         break;
00302 
00303     case STATE_BS_FINISHED:
00304     case STATE_BS_FINISHING:
00305     case STATE_BS_FAILING:
00306     case STATE_BS_FAILED:
00307     default:
00308         LOG("Returning COAP_IGNORE");
00309         return COAP_IGNORE;
00310     }
00311 
00312     return COAP_NO_ERROR;
00313 }
00314 
00315 static void prv_tagServer(lwm2m_context_t * contextP,
00316                           uint16_t id)
00317 {
00318     lwm2m_server_t * targetP;
00319 
00320     targetP = (lwm2m_server_t *)LWM2M_LIST_FIND(contextP->bootstrapServerList, id);
00321     if (targetP == NULL)
00322     {
00323         targetP = (lwm2m_server_t *)LWM2M_LIST_FIND(contextP->serverList, id);
00324     }
00325     if (targetP != NULL)
00326     {
00327         targetP->dirty = true;
00328     }
00329 }
00330 
00331 static void prv_tagAllServer(lwm2m_context_t * contextP,
00332                              lwm2m_server_t * serverP)
00333 {
00334     lwm2m_server_t * targetP;
00335 
00336     targetP = contextP->bootstrapServerList;
00337     while (targetP != NULL)
00338     {
00339         if (targetP != serverP)
00340         {
00341             targetP->dirty = true;
00342         }
00343         targetP = targetP->next;
00344     }
00345     targetP = contextP->serverList;
00346     while (targetP != NULL)
00347     {
00348         targetP->dirty = true;
00349         targetP = targetP->next;
00350     }
00351 }
00352 
00353 coap_status_t bootstrap_handleCommand(lwm2m_context_t * contextP,
00354                                       lwm2m_uri_t * uriP,
00355                                       lwm2m_server_t * serverP,
00356                                       coap_packet_t * message,
00357                                       coap_packet_t * response)
00358 {
00359     coap_status_t result;
00360     lwm2m_media_type_t format;
00361 
00362     LOG_ARG("Code: %02X", message->code);
00363     LOG_URI(uriP);
00364     format = utils_convertMediaType(message->content_type);
00365 
00366     result = prv_checkServerStatus(serverP);
00367     if (result != COAP_NO_ERROR) return result;
00368 
00369     switch (message->code)
00370     {
00371     case COAP_PUT:
00372         {
00373             if (LWM2M_URI_IS_SET_INSTANCE(uriP))
00374             {
00375                 if (object_isInstanceNew(contextP, uriP->objectId, uriP->instanceId))
00376                 {
00377                     result = object_create(contextP, uriP, format, message->payload, message->payload_len);
00378                     if (COAP_201_CREATED == result)
00379                     {
00380                         result = COAP_204_CHANGED;
00381                     }
00382                 }
00383                 else
00384                 {
00385                     result = object_write(contextP, uriP, format, message->payload, message->payload_len);
00386                     if (uriP->objectId == LWM2M_SECURITY_OBJECT_ID
00387                      && result == COAP_204_CHANGED)
00388                     {
00389                         prv_tagServer(contextP, uriP->instanceId);
00390                     }
00391                 }
00392             }
00393             else
00394             {
00395                 lwm2m_data_t * dataP = NULL;
00396                 int size = 0;
00397                 int i;
00398 
00399                 if (message->payload_len == 0 || message->payload == 0)
00400                 {
00401                     result = COAP_400_BAD_REQUEST;
00402                 }
00403                 else
00404                 {
00405                     size = lwm2m_data_parse(uriP, message->payload, message->payload_len, format, &dataP);
00406                     if (size == 0)
00407                     {
00408                         result = COAP_500_INTERNAL_SERVER_ERROR;
00409                         break;
00410                     }
00411 
00412                     for (i = 0 ; i < size ; i++)
00413                     {
00414                         if(dataP[i].type == LWM2M_TYPE_OBJECT_INSTANCE)
00415                         {
00416                             if (object_isInstanceNew(contextP, uriP->objectId, dataP[i].id))
00417                             {
00418                                 result = object_createInstance(contextP, uriP, &dataP[i]);
00419                                 if (COAP_201_CREATED == result)
00420                                 {
00421                                     result = COAP_204_CHANGED;
00422                                 }
00423                             }
00424                             else
00425                             {
00426                                 result = object_writeInstance(contextP, uriP, &dataP[i]);
00427                                 if (uriP->objectId == LWM2M_SECURITY_OBJECT_ID
00428                                  && result == COAP_204_CHANGED)
00429                                 {
00430                                     prv_tagServer(contextP, dataP[i].id);
00431                                 }
00432                             }
00433                             
00434                             if(result != COAP_204_CHANGED) // Stop object create or write when result is error
00435                             {
00436                                 break;
00437                             }
00438                         }
00439                         else
00440                         {
00441                             result = COAP_400_BAD_REQUEST;
00442                         }
00443                     }
00444                     lwm2m_data_free(size, dataP);
00445                 }
00446             }
00447         }
00448         break;
00449 
00450     case COAP_DELETE:
00451         {
00452             if (LWM2M_URI_IS_SET_RESOURCE(uriP))
00453             {
00454                 result = COAP_400_BAD_REQUEST;
00455             }
00456             else
00457             {
00458                 result = object_delete(contextP, uriP);
00459                 if (uriP->objectId == LWM2M_SECURITY_OBJECT_ID
00460                  && result == COAP_202_DELETED)
00461                 {
00462                     if (LWM2M_URI_IS_SET_INSTANCE(uriP))
00463                     {
00464                         prv_tagServer(contextP, uriP->instanceId);
00465                     }
00466                     else
00467                     {
00468                         prv_tagAllServer(contextP, NULL);
00469                     }
00470                 }
00471             }
00472         }
00473         break;
00474 
00475     case COAP_GET:
00476     case COAP_POST:
00477     default:
00478         result = COAP_400_BAD_REQUEST;
00479         break;
00480     }
00481 
00482     if (result == COAP_202_DELETED
00483      || result == COAP_204_CHANGED)
00484     {
00485         if (serverP->status != STATE_BS_PENDING)
00486         {
00487             serverP->status = STATE_BS_PENDING;
00488             contextP->state = STATE_BOOTSTRAPPING;
00489         }
00490     }
00491     LOG_ARG("Server status: %s", STR_STATUS(serverP->status));
00492 
00493     return result;
00494 }
00495 
00496 coap_status_t bootstrap_handleDeleteAll(lwm2m_context_t * contextP,
00497                                         void * fromSessionH)
00498 {
00499     lwm2m_server_t * serverP;
00500     coap_status_t result;
00501     lwm2m_object_t * objectP;
00502 
00503     LOG("Entering");
00504     serverP = utils_findBootstrapServer(contextP, fromSessionH);
00505     if (serverP == NULL) return COAP_IGNORE;
00506     result = prv_checkServerStatus(serverP);
00507     if (result != COAP_NO_ERROR) return result;
00508 
00509     result = COAP_202_DELETED;
00510     for (objectP = contextP->objectList; objectP != NULL; objectP = objectP->next)
00511     {
00512         lwm2m_uri_t uri;
00513 
00514         memset(&uri, 0, sizeof(lwm2m_uri_t));
00515         uri.flag = LWM2M_URI_FLAG_OBJECT_ID;
00516         uri.objectId = objectP->objID;
00517 
00518         if (objectP->objID == LWM2M_SECURITY_OBJECT_ID)
00519         {
00520             lwm2m_list_t * instanceP;
00521 
00522             instanceP = objectP->instanceList;
00523             while (NULL != instanceP
00524                 && result == COAP_202_DELETED)
00525             {
00526                 if (instanceP->id == serverP->secObjInstID)
00527                 {
00528                     instanceP = instanceP->next;
00529                 }
00530                 else
00531                 {
00532                     uri.flag = LWM2M_URI_FLAG_OBJECT_ID | LWM2M_URI_FLAG_INSTANCE_ID;
00533                     uri.instanceId = instanceP->id;
00534                     result = object_delete(contextP, &uri);
00535                     instanceP = objectP->instanceList;
00536                 }
00537             }
00538             if (result == COAP_202_DELETED)
00539             {
00540                 prv_tagAllServer(contextP, serverP);
00541             }
00542         }
00543         else
00544         {
00545             result = object_delete(contextP, &uri);
00546             if (result == COAP_405_METHOD_NOT_ALLOWED)
00547             {
00548                 // Fake a successful deletion for static objects like the Device object.
00549                 result = COAP_202_DELETED;
00550             }
00551         }
00552     }
00553 
00554     return result;
00555 }
00556 #endif
00557 #endif
00558 
00559 #ifdef LWM2M_BOOTSTRAP_SERVER_MODE
00560 uint8_t bootstrap_handleRequest(lwm2m_context_t * contextP,
00561                                 lwm2m_uri_t * uriP,
00562                                 void * fromSessionH,
00563                                 coap_packet_t * message,
00564                                 coap_packet_t * response)
00565 {
00566     uint8_t result;
00567     char * name;
00568 
00569     LOG_URI(uriP);
00570     if (contextP->bootstrapCallback == NULL) return COAP_500_INTERNAL_SERVER_ERROR;
00571     if (message->code != COAP_POST) return COAP_400_BAD_REQUEST;
00572     if (message->uri_query == NULL) return COAP_400_BAD_REQUEST;
00573     if (message->payload != NULL) return COAP_400_BAD_REQUEST;
00574 
00575     if (lwm2m_strncmp((char *)message->uri_query->data, QUERY_NAME, QUERY_NAME_LEN) != 0)
00576     {
00577         return COAP_400_BAD_REQUEST;
00578     }
00579 
00580     if (message->uri_query->len == QUERY_NAME_LEN) return COAP_400_BAD_REQUEST;
00581     if (message->uri_query->next != NULL) return COAP_400_BAD_REQUEST;
00582 
00583     name = (char *)lwm2m_malloc(message->uri_query->len - QUERY_NAME_LEN + 1);
00584     if (name == NULL) return COAP_500_INTERNAL_SERVER_ERROR;
00585 
00586     memcpy(name, message->uri_query->data + QUERY_NAME_LEN, message->uri_query->len - QUERY_NAME_LEN);
00587     name[message->uri_query->len - QUERY_NAME_LEN] = 0;
00588 
00589     result = contextP->bootstrapCallback(fromSessionH, COAP_NO_ERROR, NULL, name, contextP->bootstrapUserData);
00590 
00591     lwm2m_free(name);
00592 
00593     return result;
00594 }
00595 
00596 void lwm2m_set_bootstrap_callback(lwm2m_context_t * contextP,
00597                                   lwm2m_bootstrap_callback_t callback,
00598                                   void * userData)
00599 {
00600     LOG("Entering");
00601     contextP->bootstrapCallback = callback;
00602     contextP->bootstrapUserData = userData;
00603 }
00604 
00605 static void prv_resultCallback(lwm2m_transaction_t * transacP,
00606                                void * message)
00607 {
00608     bs_data_t * dataP = (bs_data_t *)transacP->userData;
00609     lwm2m_uri_t * uriP;
00610 
00611     if (dataP->isUri == true)
00612     {
00613         uriP = &dataP->uri;
00614     }
00615     else
00616     {
00617         uriP = NULL;
00618     }
00619 
00620     if (message == NULL)
00621     {
00622         dataP->callback(transacP->peerH,
00623                         COAP_503_SERVICE_UNAVAILABLE,
00624                         uriP,
00625                         NULL,
00626                         dataP->userData);
00627     }
00628     else
00629     {
00630         coap_packet_t * packet = (coap_packet_t *)message;
00631 
00632         dataP->callback(transacP->peerH,
00633                         packet->code,
00634                         uriP,
00635                         NULL,
00636                         dataP->userData);
00637     }
00638     lwm2m_free(dataP);
00639 }
00640 
00641 int lwm2m_bootstrap_delete(lwm2m_context_t * contextP,
00642                            void * sessionH,
00643                            lwm2m_uri_t * uriP)
00644 {
00645     lwm2m_transaction_t * transaction;
00646     bs_data_t * dataP;
00647 
00648     LOG_URI(uriP);
00649     transaction = transaction_new(sessionH, COAP_DELETE, NULL, uriP, contextP->nextMID++, 4, NULL);
00650     if (transaction == NULL) return COAP_500_INTERNAL_SERVER_ERROR;
00651 
00652     dataP = (bs_data_t *)lwm2m_malloc(sizeof(bs_data_t));
00653     if (dataP == NULL)
00654     {
00655         transaction_free(transaction);
00656         return COAP_500_INTERNAL_SERVER_ERROR;
00657     }
00658     if (uriP == NULL)
00659     {
00660         dataP->isUri = false;
00661     }
00662     else
00663     {
00664         dataP->isUri = true;
00665         memcpy(&dataP->uri, uriP, sizeof(lwm2m_uri_t));
00666     }
00667     dataP->callback = contextP->bootstrapCallback;
00668     dataP->userData = contextP->bootstrapUserData;
00669 
00670     transaction->callback = prv_resultCallback;
00671     transaction->userData = (void *)dataP;
00672 
00673     contextP->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(contextP->transactionList, transaction);
00674 
00675     return transaction_send(contextP, transaction);
00676 }
00677 
00678 int lwm2m_bootstrap_write(lwm2m_context_t * contextP,
00679                           void * sessionH,
00680                           lwm2m_uri_t * uriP,
00681                           lwm2m_media_type_t format,
00682                           uint8_t * buffer,
00683                           size_t length)
00684 {
00685     lwm2m_transaction_t * transaction;
00686     bs_data_t * dataP;
00687 
00688     LOG_URI(uriP);
00689     if (uriP == NULL
00690     || buffer == NULL
00691     || length == 0)
00692     {
00693         return COAP_400_BAD_REQUEST;
00694     }
00695 
00696     transaction = transaction_new(sessionH, COAP_PUT, NULL, uriP, contextP->nextMID++, 4, NULL);
00697     if (transaction == NULL) return COAP_500_INTERNAL_SERVER_ERROR;
00698 
00699     coap_set_header_content_type(transaction->message, format);
00700     coap_set_payload(transaction->message, buffer, length);
00701 
00702     dataP = (bs_data_t *)lwm2m_malloc(sizeof(bs_data_t));
00703     if (dataP == NULL)
00704     {
00705         transaction_free(transaction);
00706         return COAP_500_INTERNAL_SERVER_ERROR;
00707     }
00708     dataP->isUri = true;
00709     memcpy(&dataP->uri, uriP, sizeof(lwm2m_uri_t));
00710     dataP->callback = contextP->bootstrapCallback;
00711     dataP->userData = contextP->bootstrapUserData;
00712 
00713     transaction->callback = prv_resultCallback;
00714     transaction->userData = (void *)dataP;
00715 
00716     contextP->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(contextP->transactionList, transaction);
00717 
00718     return transaction_send(contextP, transaction);
00719 }
00720 
00721 int lwm2m_bootstrap_finish(lwm2m_context_t * contextP,
00722                            void * sessionH)
00723 {
00724     lwm2m_transaction_t * transaction;
00725     bs_data_t * dataP;
00726 
00727     LOG("Entering");
00728     transaction = transaction_new(sessionH, COAP_POST, NULL, NULL, contextP->nextMID++, 4, NULL);
00729     if (transaction == NULL) return COAP_500_INTERNAL_SERVER_ERROR;
00730 
00731     coap_set_header_uri_path(transaction->message, "/"URI_BOOTSTRAP_SEGMENT);
00732 
00733     dataP = (bs_data_t *)lwm2m_malloc(sizeof(bs_data_t));
00734     if (dataP == NULL)
00735     {
00736         transaction_free(transaction);
00737         return COAP_500_INTERNAL_SERVER_ERROR;
00738     }
00739     dataP->isUri = false;
00740     dataP->callback = contextP->bootstrapCallback;
00741     dataP->userData = contextP->bootstrapUserData;
00742 
00743     transaction->callback = prv_resultCallback;
00744     transaction->userData = (void *)dataP;
00745 
00746     contextP->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(contextP->transactionList, transaction);
00747 
00748     return transaction_send(contextP, transaction);
00749 }
00750 
00751 #endif