terence zhang / wakaama-core
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers management.c Source File

management.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  *    domedambrosio - Please refer to git log
00016  *    Toby Jaffey - Please refer to git log
00017  *    Bosch Software Innovations GmbH - Please refer to git log
00018  *    Pascal Rieux - Please refer to git log
00019  *    
00020  *******************************************************************************/
00021 /*
00022  Copyright (c) 2013, 2014 Intel Corporation
00023 
00024  Redistribution and use in source and binary forms, with or without modification,
00025  are permitted provided that the following conditions are met:
00026 
00027      * Redistributions of source code must retain the above copyright notice,
00028        this list of conditions and the following disclaimer.
00029      * Redistributions in binary form must reproduce the above copyright notice,
00030        this list of conditions and the following disclaimer in the documentation
00031        and/or other materials provided with the distribution.
00032      * Neither the name of Intel Corporation nor the names of its contributors
00033        may be used to endorse or promote products derived from this software
00034        without specific prior written permission.
00035 
00036  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00037  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00038  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00039  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
00040  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00041  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00042  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00043  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00044  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
00045  THE POSSIBILITY OF SUCH DAMAGE.
00046 
00047  David Navarro <david.navarro@intel.com>
00048 
00049 */
00050 
00051 #include "internals.h"
00052 #include <stdio.h>
00053 
00054 
00055 #ifdef LWM2M_CLIENT_MODE
00056 static int prv_readAttributes(multi_option_t * query,
00057                               lwm2m_attributes_t * attrP)
00058 {
00059     int64_t intValue;
00060     double floatValue;
00061 
00062     memset(attrP, 0, sizeof(lwm2m_attributes_t));
00063 
00064     while (query != NULL)
00065     {
00066         if (lwm2m_strncmp((char *)query->data, ATTR_MIN_PERIOD_STR, ATTR_MIN_PERIOD_LEN) == 0)
00067         {
00068             if (0 != ((attrP->toSet | attrP->toClear) & LWM2M_ATTR_FLAG_MIN_PERIOD)) return -1;
00069             if (query->len == ATTR_MIN_PERIOD_LEN) return -1;
00070 
00071             if (1 != utils_plainTextToInt64(query->data + ATTR_MIN_PERIOD_LEN, query->len - ATTR_MIN_PERIOD_LEN, &intValue)) return -1;
00072             if (intValue < 0) return -1;
00073 
00074             attrP->toSet |= LWM2M_ATTR_FLAG_MIN_PERIOD;
00075             attrP->minPeriod = intValue;
00076         }
00077         else if (lwm2m_strncmp((char *)query->data, ATTR_MIN_PERIOD_STR, ATTR_MIN_PERIOD_LEN - 1) == 0)
00078         {
00079             if (0 != ((attrP->toSet | attrP->toClear) & LWM2M_ATTR_FLAG_MIN_PERIOD)) return -1;
00080             if (query->len != ATTR_MIN_PERIOD_LEN - 1) return -1;
00081 
00082             attrP->toClear |= LWM2M_ATTR_FLAG_MIN_PERIOD;
00083         }
00084         else if (lwm2m_strncmp((char *)query->data, ATTR_MAX_PERIOD_STR, ATTR_MAX_PERIOD_LEN) == 0)
00085         {
00086             if (0 != ((attrP->toSet | attrP->toClear) & LWM2M_ATTR_FLAG_MAX_PERIOD)) return -1;
00087             if (query->len == ATTR_MAX_PERIOD_LEN) return -1;
00088 
00089             if (1 != utils_plainTextToInt64(query->data + ATTR_MAX_PERIOD_LEN, query->len - ATTR_MAX_PERIOD_LEN, &intValue)) return -1;
00090             if (intValue < 0) return -1;
00091 
00092             attrP->toSet |= LWM2M_ATTR_FLAG_MAX_PERIOD;
00093             attrP->maxPeriod = intValue;
00094         }
00095         else if (lwm2m_strncmp((char *)query->data, ATTR_MAX_PERIOD_STR, ATTR_MAX_PERIOD_LEN - 1) == 0)
00096         {
00097             if (0 != ((attrP->toSet | attrP->toClear) & LWM2M_ATTR_FLAG_MAX_PERIOD)) return -1;
00098             if (query->len != ATTR_MAX_PERIOD_LEN - 1) return -1;
00099 
00100             attrP->toClear |= LWM2M_ATTR_FLAG_MAX_PERIOD;
00101         }
00102         else if (lwm2m_strncmp((char *)query->data, ATTR_GREATER_THAN_STR, ATTR_GREATER_THAN_LEN) == 0)
00103         {
00104             if (0 != ((attrP->toSet | attrP->toClear) & LWM2M_ATTR_FLAG_GREATER_THAN)) return -1;
00105             if (query->len == ATTR_GREATER_THAN_LEN) return -1;
00106 
00107             if (1 != utils_plainTextToFloat64(query->data + ATTR_GREATER_THAN_LEN, query->len - ATTR_GREATER_THAN_LEN, &floatValue)) return -1;
00108 
00109             attrP->toSet |= LWM2M_ATTR_FLAG_GREATER_THAN;
00110             attrP->greaterThan = floatValue;
00111         }
00112         else if (lwm2m_strncmp((char *)query->data, ATTR_GREATER_THAN_STR, ATTR_GREATER_THAN_LEN - 1) == 0)
00113         {
00114             if (0 != ((attrP->toSet | attrP->toClear) & LWM2M_ATTR_FLAG_GREATER_THAN)) return -1;
00115             if (query->len != ATTR_GREATER_THAN_LEN - 1) return -1;
00116 
00117             attrP->toClear |= LWM2M_ATTR_FLAG_GREATER_THAN;
00118         }
00119         else if (lwm2m_strncmp((char *)query->data, ATTR_LESS_THAN_STR, ATTR_LESS_THAN_LEN) == 0)
00120         {
00121             if (0 != ((attrP->toSet | attrP->toClear) & LWM2M_ATTR_FLAG_LESS_THAN)) return -1;
00122             if (query->len == ATTR_LESS_THAN_LEN) return -1;
00123 
00124             if (1 != utils_plainTextToFloat64(query->data + ATTR_LESS_THAN_LEN, query->len - ATTR_LESS_THAN_LEN, &floatValue)) return -1;
00125 
00126             attrP->toSet |= LWM2M_ATTR_FLAG_LESS_THAN;
00127             attrP->lessThan = floatValue;
00128         }
00129         else if (lwm2m_strncmp((char *)query->data, ATTR_LESS_THAN_STR, ATTR_LESS_THAN_LEN - 1) == 0)
00130         {
00131             if (0 != ((attrP->toSet | attrP->toClear) & LWM2M_ATTR_FLAG_LESS_THAN)) return -1;
00132             if (query->len != ATTR_LESS_THAN_LEN - 1) return -1;
00133 
00134             attrP->toClear |= LWM2M_ATTR_FLAG_LESS_THAN;
00135         }
00136         else if (lwm2m_strncmp((char *)query->data, ATTR_STEP_STR, ATTR_STEP_LEN) == 0)
00137         {
00138             if (0 != ((attrP->toSet | attrP->toClear) & LWM2M_ATTR_FLAG_STEP)) return -1;
00139             if (query->len == ATTR_STEP_LEN) return -1;
00140 
00141             if (1 != utils_plainTextToFloat64(query->data + ATTR_STEP_LEN, query->len - ATTR_STEP_LEN, &floatValue)) return -1;
00142             if (floatValue < 0) return -1;
00143 
00144             attrP->toSet |= LWM2M_ATTR_FLAG_STEP;
00145             attrP->step = floatValue;
00146         }
00147         else if (lwm2m_strncmp((char *)query->data, ATTR_STEP_STR, ATTR_STEP_LEN - 1) == 0)
00148         {
00149             if (0 != ((attrP->toSet | attrP->toClear) & LWM2M_ATTR_FLAG_STEP)) return -1;
00150             if (query->len != ATTR_STEP_LEN - 1) return -1;
00151 
00152             attrP->toClear |= LWM2M_ATTR_FLAG_STEP;
00153         }
00154         else return -1;
00155 
00156         query = query->next;
00157     }
00158 
00159     return 0;
00160 }
00161 
00162 coap_status_t dm_handleRequest(lwm2m_context_t * contextP,
00163                                 lwm2m_uri_t * uriP,
00164                                 lwm2m_server_t * serverP,
00165                                 coap_packet_t * message,
00166                                 coap_packet_t * response)
00167 {
00168     coap_status_t result;
00169     lwm2m_media_type_t format;
00170 
00171     LOG_ARG("Code: %02X, server status: %s", message->code, STR_STATUS(serverP->status));
00172     LOG_URI(uriP);
00173 
00174     if (IS_OPTION(message, COAP_OPTION_CONTENT_TYPE))
00175     {
00176         format = utils_convertMediaType(message->content_type);
00177     }
00178     else
00179     {
00180         format = LWM2M_CONTENT_TLV;
00181     }
00182 
00183     if (uriP->objectId == LWM2M_SECURITY_OBJECT_ID)
00184     {
00185         return COAP_404_NOT_FOUND;
00186     }
00187 
00188     if (serverP->status != STATE_REGISTERED
00189         && serverP->status != STATE_REG_UPDATE_NEEDED
00190         && serverP->status != STATE_REG_FULL_UPDATE_NEEDED
00191         && serverP->status != STATE_REG_UPDATE_PENDING)
00192     {
00193         return COAP_IGNORE;
00194     }
00195 
00196     // TODO: check ACL
00197 
00198     switch (message->code)
00199     {
00200     case COAP_GET:
00201         {
00202             uint8_t * buffer = NULL;
00203             size_t length = 0;
00204             int res;
00205 
00206             if (IS_OPTION(message, COAP_OPTION_OBSERVE))
00207             {
00208                 lwm2m_data_t * dataP = NULL;
00209                 int size = 0;
00210 
00211                 result = object_readData(contextP, uriP, &size, &dataP);
00212                 if (COAP_205_CONTENT == result)
00213                 {
00214                     result = observe_handleRequest(contextP, uriP, serverP, size, dataP, message, response);
00215                     if (COAP_205_CONTENT == result)
00216                     {
00217                         res = lwm2m_data_serialize(uriP, size, dataP, &format, &buffer);
00218                         if (res < 0)
00219                         {
00220                             result = COAP_500_INTERNAL_SERVER_ERROR;
00221                         }
00222                         else
00223                         {
00224                             length = (size_t)res;
00225                             LOG_ARG("Observe Request[/%d/%d/%d]: %.*s\n", uriP->objectId, uriP->instanceId, uriP->resourceId, length, buffer);
00226                         }
00227                     }
00228                     lwm2m_data_free(size, dataP);
00229                 }
00230             }
00231             else if (IS_OPTION(message, COAP_OPTION_ACCEPT)
00232                   && message->accept_num == 1
00233                   && message->accept[0] == APPLICATION_LINK_FORMAT)
00234             {
00235                 format = LWM2M_CONTENT_LINK;
00236                 result = object_discover(contextP, uriP, serverP, &buffer, &length);
00237             }
00238             else
00239             {
00240                 if (IS_OPTION(message, COAP_OPTION_ACCEPT))
00241                 {
00242                     format = utils_convertMediaType(message->accept[0]);
00243                 }
00244 
00245                 result = object_read(contextP, uriP, &format, &buffer, &length);
00246             }
00247             if (COAP_205_CONTENT == result)
00248             {
00249                 coap_set_header_content_type(response, format);
00250                 coap_set_payload(response, buffer, length);
00251                 // lwm2m_handle_packet will free buffer
00252             }
00253             else
00254             {
00255                 lwm2m_free(buffer);
00256             }
00257         }
00258         break;
00259 
00260     case COAP_POST:
00261         {
00262             if (!LWM2M_URI_IS_SET_INSTANCE(uriP))
00263             {
00264                 result = object_create(contextP, uriP, format, message->payload, message->payload_len);
00265                 if (result == COAP_201_CREATED)
00266                 {
00267                     //longest uri is /65535/65535 = 12 + 1 (null) chars
00268                     char location_path[13] = "";
00269                     //instanceId expected
00270                     if ((uriP->flag & LWM2M_URI_FLAG_INSTANCE_ID) == 0)
00271                     {
00272                         result = COAP_500_INTERNAL_SERVER_ERROR;
00273                         break;
00274                     }
00275 
00276                     if (sprintf(location_path, "/%d/%d", uriP->objectId, uriP->instanceId) < 0)
00277                     {
00278                         result = COAP_500_INTERNAL_SERVER_ERROR;
00279                         break;
00280                     }
00281                     coap_set_header_location_path(response, location_path);
00282 
00283                     lwm2m_update_registration(contextP, 0, true);
00284                 }
00285             }
00286             else if (!LWM2M_URI_IS_SET_RESOURCE(uriP))
00287             {
00288                 result = object_write(contextP, uriP, format, message->payload, message->payload_len);
00289             }
00290             else
00291             {
00292                 result = object_execute(contextP, uriP, message->payload, message->payload_len);
00293             }
00294         }
00295         break;
00296 
00297     case COAP_PUT:
00298         {
00299             if (IS_OPTION(message, COAP_OPTION_URI_QUERY))
00300             {
00301                 lwm2m_attributes_t attr;
00302 
00303                 if (0 != prv_readAttributes(message->uri_query, &attr))
00304                 {
00305                     result = COAP_400_BAD_REQUEST;
00306                 }
00307                 else
00308                 {
00309                     result = observe_setParameters(contextP, uriP, serverP, &attr);
00310                 }
00311             }
00312             else if (LWM2M_URI_IS_SET_INSTANCE(uriP))
00313             {
00314                 result = object_write(contextP, uriP, format, message->payload, message->payload_len);
00315             }
00316             else
00317             {
00318                 result = COAP_400_BAD_REQUEST;
00319             }
00320         }
00321         break;
00322 
00323     case COAP_DELETE:
00324         {
00325             if (!LWM2M_URI_IS_SET_INSTANCE(uriP) || LWM2M_URI_IS_SET_RESOURCE(uriP))
00326             {
00327                 result = COAP_400_BAD_REQUEST;
00328             }
00329             else
00330             {
00331                 result = object_delete(contextP, uriP);
00332                 if (result == COAP_202_DELETED)
00333                 {
00334                     lwm2m_update_registration(contextP, 0, true);
00335                 }
00336             }
00337         }
00338         break;
00339 
00340     default:
00341         result = COAP_400_BAD_REQUEST;
00342         break;
00343     }
00344 
00345     return result;
00346 }
00347 
00348 #endif
00349 
00350 #ifdef LWM2M_SERVER_MODE
00351 
00352 #define ID_AS_STRING_MAX_LEN 8
00353 
00354 static void prv_resultCallback(lwm2m_transaction_t * transacP,
00355                                void * message)
00356 {
00357     dm_data_t * dataP = (dm_data_t *)transacP->userData;
00358 
00359     if (message == NULL)
00360     {
00361         dataP->callback(dataP->clientID,
00362                         &dataP->uri,
00363                         COAP_503_SERVICE_UNAVAILABLE,
00364                         LWM2M_CONTENT_TEXT, NULL, 0,
00365                         dataP->userData);
00366     }
00367     else
00368     {
00369         coap_packet_t * packet = (coap_packet_t *)message;
00370 
00371         //if packet is a CREATE response and the instanceId was assigned by the client
00372         if (packet->code == COAP_201_CREATED
00373          && packet->location_path != NULL)
00374         {
00375             char * locationString = NULL;
00376             int result = 0;
00377             lwm2m_uri_t locationUri;
00378 
00379             locationString = coap_get_multi_option_as_string(packet->location_path);
00380             if (locationString == NULL)
00381             {
00382                 LOG("Error: coap_get_multi_option_as_string() failed for Location_path option in prv_resultCallback()");
00383                 return;
00384             }
00385 
00386             result = lwm2m_stringToUri(locationString, strlen(locationString), &locationUri);
00387             if (result == 0)
00388             {
00389                 LOG("Error: lwm2m_stringToUri() failed for Location_path option in prv_resultCallback()");
00390                 lwm2m_free(locationString);
00391                 return;
00392             }
00393 
00394             ((dm_data_t*)transacP->userData)->uri.instanceId = locationUri.instanceId;
00395             ((dm_data_t*)transacP->userData)->uri.flag = locationUri.flag;
00396 
00397             lwm2m_free(locationString);
00398         }
00399 
00400         dataP->callback(dataP->clientID,
00401                         &dataP->uri,
00402                         packet->code,
00403                         utils_convertMediaType(packet->content_type),
00404                         packet->payload,
00405                         packet->payload_len,
00406                         dataP->userData);
00407     }
00408     lwm2m_free(dataP);
00409 }
00410 
00411 static int prv_makeOperation(lwm2m_context_t * contextP,
00412                              uint16_t clientID,
00413                              lwm2m_uri_t * uriP,
00414                              coap_method_t method,
00415                              lwm2m_media_type_t format,
00416                              uint8_t * buffer,
00417                              int length,
00418                              lwm2m_result_callback_t callback,
00419                              void * userData)
00420 {
00421     lwm2m_client_t * clientP;
00422     lwm2m_transaction_t * transaction;
00423     dm_data_t * dataP;
00424 
00425     clientP = (lwm2m_client_t *)lwm2m_list_find((lwm2m_list_t *)contextP->clientList, clientID);
00426     if (clientP == NULL) return COAP_404_NOT_FOUND;
00427 
00428     transaction = transaction_new(clientP->sessionH, method, clientP->altPath, uriP, contextP->nextMID++, 4, NULL);
00429     if (transaction == NULL) return COAP_500_INTERNAL_SERVER_ERROR;
00430 
00431     if (method == COAP_GET)
00432     {
00433         coap_set_header_accept(transaction->message, format);
00434     }
00435     else if (buffer != NULL)
00436     {
00437         coap_set_header_content_type(transaction->message, format);
00438         // TODO: Take care of fragmentation
00439         coap_set_payload(transaction->message, buffer, length);
00440     }
00441 
00442     if (callback != NULL)
00443     {
00444         dataP = (dm_data_t *)lwm2m_malloc(sizeof(dm_data_t));
00445         if (dataP == NULL)
00446         {
00447             transaction_free(transaction);
00448             return COAP_500_INTERNAL_SERVER_ERROR;
00449         }
00450         memcpy(&dataP->uri, uriP, sizeof(lwm2m_uri_t));
00451         dataP->clientID = clientP->internalID;
00452         dataP->callback = callback;
00453         dataP->userData = userData;
00454 
00455         transaction->callback = prv_resultCallback;
00456         transaction->userData = (void *)dataP;
00457     }
00458 
00459     contextP->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(contextP->transactionList, transaction);
00460 
00461     return transaction_send(contextP, transaction);
00462 }
00463 
00464 int lwm2m_dm_read(lwm2m_context_t * contextP,
00465                   uint16_t clientID,
00466                   lwm2m_uri_t * uriP,
00467                   lwm2m_result_callback_t callback,
00468                   void * userData)
00469 {
00470     lwm2m_client_t * clientP;
00471     lwm2m_media_type_t format;
00472 
00473     LOG_ARG("clientID: %d", clientID);
00474     LOG_URI(uriP);
00475 
00476     clientP = (lwm2m_client_t *)lwm2m_list_find((lwm2m_list_t *)contextP->clientList, clientID);
00477     if (clientP == NULL) return COAP_404_NOT_FOUND;
00478 
00479     if (clientP->supportJSON == true)
00480     {
00481         format = LWM2M_CONTENT_JSON;
00482     }
00483     else
00484     {
00485         format = LWM2M_CONTENT_TLV;
00486     }
00487 
00488     return prv_makeOperation(contextP, clientID, uriP,
00489                              COAP_GET,
00490                              format,
00491                              NULL, 0,
00492                              callback, userData);
00493 }
00494 
00495 int lwm2m_dm_write(lwm2m_context_t * contextP,
00496                    uint16_t clientID,
00497                    lwm2m_uri_t * uriP,
00498                    lwm2m_media_type_t format,
00499                    uint8_t * buffer,
00500                    int length,
00501                    lwm2m_result_callback_t callback,
00502                    void * userData)
00503 {
00504     LOG_ARG("clientID: %d, format: %s, length: %d", clientID, STR_MEDIA_TYPE(format), length);
00505     LOG_URI(uriP);
00506     if (!LWM2M_URI_IS_SET_INSTANCE(uriP)
00507      || length == 0)
00508     {
00509         return COAP_400_BAD_REQUEST;
00510     }
00511 
00512     if (LWM2M_URI_IS_SET_RESOURCE(uriP))
00513     {
00514         return prv_makeOperation(contextP, clientID, uriP,
00515                                   COAP_PUT,
00516                                   format, buffer, length,
00517                                   callback, userData);
00518     }
00519     else
00520     {
00521         return prv_makeOperation(contextP, clientID, uriP,
00522                                   COAP_POST,
00523                                   format, buffer, length,
00524                                   callback, userData);
00525     }
00526 }
00527 
00528 int lwm2m_dm_execute(lwm2m_context_t * contextP,
00529                      uint16_t clientID,
00530                      lwm2m_uri_t * uriP,
00531                      lwm2m_media_type_t format,
00532                      uint8_t * buffer,
00533                      int length,
00534                      lwm2m_result_callback_t callback,
00535                      void * userData)
00536 {
00537     LOG_ARG("clientID: %d, format: %s, length: %d", clientID, STR_MEDIA_TYPE(format), length);
00538     LOG_URI(uriP);
00539     if (!LWM2M_URI_IS_SET_RESOURCE(uriP))
00540     {
00541         return COAP_400_BAD_REQUEST;
00542     }
00543 
00544     return prv_makeOperation(contextP, clientID, uriP,
00545                               COAP_POST,
00546                               format, buffer, length,
00547                               callback, userData);
00548 }
00549 
00550 int lwm2m_dm_create(lwm2m_context_t * contextP,
00551                     uint16_t clientID,
00552                     lwm2m_uri_t * uriP,
00553                     lwm2m_media_type_t format,
00554                     uint8_t * buffer,
00555                     int length,
00556                     lwm2m_result_callback_t callback,
00557                     void * userData)
00558 {
00559     LOG_ARG("clientID: %d, format: %s, length: %d", clientID, STR_MEDIA_TYPE(format), length);
00560     LOG_URI(uriP);
00561 
00562     if (LWM2M_URI_IS_SET_INSTANCE(uriP)
00563      || length == 0)
00564     {
00565         return COAP_400_BAD_REQUEST;
00566     }
00567 
00568     return prv_makeOperation(contextP, clientID, uriP,
00569                               COAP_POST,
00570                               format, buffer, length,
00571                               callback, userData);
00572 }
00573 
00574 int lwm2m_dm_delete(lwm2m_context_t * contextP,
00575                     uint16_t clientID,
00576                     lwm2m_uri_t * uriP,
00577                     lwm2m_result_callback_t callback,
00578                     void * userData)
00579 {
00580     LOG_ARG("clientID: %d", clientID);
00581     LOG_URI(uriP);
00582     if (!LWM2M_URI_IS_SET_INSTANCE(uriP)
00583      || LWM2M_URI_IS_SET_RESOURCE(uriP))
00584     {
00585         return COAP_400_BAD_REQUEST;
00586     }
00587 
00588     return prv_makeOperation(contextP, clientID, uriP,
00589                               COAP_DELETE,
00590                               LWM2M_CONTENT_TEXT, NULL, 0,
00591                               callback, userData);
00592 }
00593 
00594 int lwm2m_dm_write_attributes(lwm2m_context_t * contextP,
00595                               uint16_t clientID,
00596                               lwm2m_uri_t * uriP,
00597                               lwm2m_attributes_t * attrP,
00598                               lwm2m_result_callback_t callback,
00599                               void * userData)
00600 {
00601 #define _PRV_BUFFER_SIZE 32
00602     lwm2m_client_t * clientP;
00603     lwm2m_transaction_t * transaction;
00604     coap_packet_t * coap_pkt;
00605     uint8_t buffer[_PRV_BUFFER_SIZE];
00606     size_t length;
00607 
00608     LOG_ARG("clientID: %d", clientID);
00609     LOG_URI(uriP);
00610     if (attrP == NULL) return COAP_400_BAD_REQUEST;
00611 
00612     if (0 != (attrP->toSet & attrP->toClear)) return COAP_400_BAD_REQUEST;
00613     if (0 != (attrP->toSet & ATTR_FLAG_NUMERIC) && !LWM2M_URI_IS_SET_RESOURCE(uriP)) return COAP_400_BAD_REQUEST;
00614     if (ATTR_FLAG_NUMERIC == (attrP->toSet & ATTR_FLAG_NUMERIC)
00615      && (attrP->lessThan + 2 * attrP->step >= attrP->greaterThan)) return COAP_400_BAD_REQUEST;
00616 
00617     clientP = (lwm2m_client_t *)lwm2m_list_find((lwm2m_list_t *)contextP->clientList, clientID);
00618     if (clientP == NULL) return COAP_404_NOT_FOUND;
00619 
00620     transaction = transaction_new(clientP->sessionH, COAP_PUT, clientP->altPath, uriP, contextP->nextMID++, 4, NULL);
00621     if (transaction == NULL) return COAP_500_INTERNAL_SERVER_ERROR;
00622 
00623     if (callback != NULL)
00624     {
00625         dm_data_t * dataP;
00626 
00627         dataP = (dm_data_t *)lwm2m_malloc(sizeof(dm_data_t));
00628         if (dataP == NULL)
00629         {
00630             transaction_free(transaction);
00631             return COAP_500_INTERNAL_SERVER_ERROR;
00632         }
00633         memcpy(&dataP->uri, uriP, sizeof(lwm2m_uri_t));
00634         dataP->clientID = clientP->internalID;
00635         dataP->callback = callback;
00636         dataP->userData = userData;
00637 
00638         transaction->callback = prv_resultCallback;
00639         transaction->userData = (void *)dataP;
00640     }
00641 
00642     coap_pkt = (coap_packet_t *)transaction->message;
00643     free_multi_option(coap_pkt->uri_query);
00644     if (attrP->toSet & LWM2M_ATTR_FLAG_MIN_PERIOD)
00645     {
00646         memcpy(buffer, ATTR_MIN_PERIOD_STR, ATTR_MIN_PERIOD_LEN);
00647         length = utils_intToText(attrP->minPeriod, buffer + ATTR_MIN_PERIOD_LEN, _PRV_BUFFER_SIZE - ATTR_MIN_PERIOD_LEN);
00648         if (length == 0)
00649         {
00650             transaction_free(transaction);
00651             return COAP_500_INTERNAL_SERVER_ERROR;
00652         }
00653         coap_add_multi_option(&(coap_pkt->uri_query), buffer, ATTR_MIN_PERIOD_LEN + length, 0);
00654         SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY);
00655     }
00656     if (attrP->toSet & LWM2M_ATTR_FLAG_MAX_PERIOD)
00657     {
00658         memcpy(buffer, ATTR_MAX_PERIOD_STR, ATTR_MAX_PERIOD_LEN);
00659         length = utils_intToText(attrP->maxPeriod, buffer + ATTR_MAX_PERIOD_LEN, _PRV_BUFFER_SIZE - ATTR_MAX_PERIOD_LEN);
00660         if (length == 0)
00661         {
00662             transaction_free(transaction);
00663             return COAP_500_INTERNAL_SERVER_ERROR;
00664         }
00665         coap_add_multi_option(&(coap_pkt->uri_query), buffer, ATTR_MAX_PERIOD_LEN + length, 0);
00666         SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY);
00667     }
00668     if (attrP->toSet & LWM2M_ATTR_FLAG_GREATER_THAN)
00669     {
00670         memcpy(buffer, ATTR_GREATER_THAN_STR, ATTR_GREATER_THAN_LEN);
00671         length = utils_floatToText(attrP->greaterThan, buffer + ATTR_GREATER_THAN_LEN, _PRV_BUFFER_SIZE - ATTR_GREATER_THAN_LEN);
00672         if (length == 0)
00673         {
00674             transaction_free(transaction);
00675             return COAP_500_INTERNAL_SERVER_ERROR;
00676         }
00677         coap_add_multi_option(&(coap_pkt->uri_query), buffer, ATTR_GREATER_THAN_LEN + length, 0);
00678         SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY);
00679     }
00680     if (attrP->toSet & LWM2M_ATTR_FLAG_LESS_THAN)
00681     {
00682         memcpy(buffer, ATTR_LESS_THAN_STR, ATTR_LESS_THAN_LEN);
00683         length = utils_floatToText(attrP->lessThan, buffer + ATTR_LESS_THAN_LEN, _PRV_BUFFER_SIZE - ATTR_LESS_THAN_LEN);
00684         if (length == 0)
00685         {
00686             transaction_free(transaction);
00687             return COAP_500_INTERNAL_SERVER_ERROR;
00688         }
00689         coap_add_multi_option(&(coap_pkt->uri_query), buffer, ATTR_LESS_THAN_LEN + length, 0);
00690         SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY);
00691     }
00692     if (attrP->toSet & LWM2M_ATTR_FLAG_STEP)
00693     {
00694         memcpy(buffer, ATTR_STEP_STR, ATTR_STEP_LEN);
00695         length = utils_floatToText(attrP->step, buffer + ATTR_STEP_LEN, _PRV_BUFFER_SIZE - ATTR_STEP_LEN);
00696         if (length == 0)
00697         {
00698             transaction_free(transaction);
00699             return COAP_500_INTERNAL_SERVER_ERROR;
00700         }
00701         coap_add_multi_option(&(coap_pkt->uri_query), buffer, ATTR_STEP_LEN + length, 0);
00702         SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY);
00703     }
00704     if (attrP->toClear & LWM2M_ATTR_FLAG_MIN_PERIOD)
00705     {
00706         coap_add_multi_option(&(coap_pkt->uri_query), ATTR_MIN_PERIOD_STR, ATTR_MIN_PERIOD_LEN -1, 0);
00707         SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY);
00708     }
00709     if (attrP->toClear & LWM2M_ATTR_FLAG_MAX_PERIOD)
00710     {
00711         coap_add_multi_option(&(coap_pkt->uri_query), ATTR_MAX_PERIOD_STR, ATTR_MAX_PERIOD_LEN - 1, 0);
00712         SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY);
00713     }
00714     if (attrP->toClear & LWM2M_ATTR_FLAG_GREATER_THAN)
00715     {
00716         coap_add_multi_option(&(coap_pkt->uri_query), ATTR_GREATER_THAN_STR, ATTR_GREATER_THAN_LEN - 1, 0);
00717         SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY);
00718     }
00719     if (attrP->toClear & LWM2M_ATTR_FLAG_LESS_THAN)
00720     {
00721         coap_add_multi_option(&(coap_pkt->uri_query), ATTR_LESS_THAN_STR, ATTR_LESS_THAN_LEN - 1, 0);
00722         SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY);
00723     }
00724     if (attrP->toClear & LWM2M_ATTR_FLAG_STEP)
00725     {
00726         coap_add_multi_option(&(coap_pkt->uri_query), ATTR_STEP_STR, ATTR_STEP_LEN - 1, 0);
00727         SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY);
00728     }
00729 
00730     contextP->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(contextP->transactionList, transaction);
00731 
00732     return transaction_send(contextP, transaction);
00733 }
00734 
00735 int lwm2m_dm_discover(lwm2m_context_t * contextP,
00736                       uint16_t clientID,
00737                       lwm2m_uri_t * uriP,
00738                       lwm2m_result_callback_t callback,
00739                       void * userData)
00740 {
00741     lwm2m_client_t * clientP;
00742     lwm2m_transaction_t * transaction;
00743     dm_data_t * dataP;
00744 
00745     LOG_ARG("clientID: %d", clientID);
00746     LOG_URI(uriP);
00747     clientP = (lwm2m_client_t *)lwm2m_list_find((lwm2m_list_t *)contextP->clientList, clientID);
00748     if (clientP == NULL) return COAP_404_NOT_FOUND;
00749 
00750     transaction = transaction_new(clientP->sessionH, COAP_GET, clientP->altPath, uriP, contextP->nextMID++, 4, NULL);
00751     if (transaction == NULL) return COAP_500_INTERNAL_SERVER_ERROR;
00752 
00753     coap_set_header_accept(transaction->message, LWM2M_CONTENT_LINK);
00754 
00755     if (callback != NULL)
00756     {
00757         dataP = (dm_data_t *)lwm2m_malloc(sizeof(dm_data_t));
00758         if (dataP == NULL)
00759         {
00760             transaction_free(transaction);
00761             return COAP_500_INTERNAL_SERVER_ERROR;
00762         }
00763         memcpy(&dataP->uri, uriP, sizeof(lwm2m_uri_t));
00764         dataP->clientID = clientP->internalID;
00765         dataP->callback = callback;
00766         dataP->userData = userData;
00767 
00768         transaction->callback = prv_resultCallback;
00769         transaction->userData = (void *)dataP;
00770     }
00771 
00772     contextP->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(contextP->transactionList, transaction);
00773 
00774     return transaction_send(contextP, transaction);
00775 }
00776 
00777 #endif