pick up wakaama files from https://github.com/eclipse/wakaama

Committer:
terencez
Date:
Wed Apr 19 11:30:02 2017 +0000
Revision:
0:1fa43ab66921
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
terencez 0:1fa43ab66921 1 /*******************************************************************************
terencez 0:1fa43ab66921 2 *
terencez 0:1fa43ab66921 3 * Copyright (c) 2013, 2014 Intel Corporation and others.
terencez 0:1fa43ab66921 4 * All rights reserved. This program and the accompanying materials
terencez 0:1fa43ab66921 5 * are made available under the terms of the Eclipse Public License v1.0
terencez 0:1fa43ab66921 6 * and Eclipse Distribution License v1.0 which accompany this distribution.
terencez 0:1fa43ab66921 7 *
terencez 0:1fa43ab66921 8 * The Eclipse Public License is available at
terencez 0:1fa43ab66921 9 * http://www.eclipse.org/legal/epl-v10.html
terencez 0:1fa43ab66921 10 * The Eclipse Distribution License is available at
terencez 0:1fa43ab66921 11 * http://www.eclipse.org/org/documents/edl-v10.php.
terencez 0:1fa43ab66921 12 *
terencez 0:1fa43ab66921 13 * Contributors:
terencez 0:1fa43ab66921 14 * David Navarro, Intel Corporation - initial API and implementation
terencez 0:1fa43ab66921 15 * domedambrosio - Please refer to git log
terencez 0:1fa43ab66921 16 * Fabien Fleutot - Please refer to git log
terencez 0:1fa43ab66921 17 * Simon Bernard - Please refer to git log
terencez 0:1fa43ab66921 18 * Toby Jaffey - Please refer to git log
terencez 0:1fa43ab66921 19 * Manuel Sangoi - Please refer to git log
terencez 0:1fa43ab66921 20 * Julien Vermillard - Please refer to git log
terencez 0:1fa43ab66921 21 * Bosch Software Innovations GmbH - Please refer to git log
terencez 0:1fa43ab66921 22 * Pascal Rieux - Please refer to git log
terencez 0:1fa43ab66921 23 *
terencez 0:1fa43ab66921 24 *******************************************************************************/
terencez 0:1fa43ab66921 25
terencez 0:1fa43ab66921 26 /*
terencez 0:1fa43ab66921 27 Copyright (c) 2013, 2014 Intel Corporation
terencez 0:1fa43ab66921 28
terencez 0:1fa43ab66921 29 Redistribution and use in source and binary forms, with or without modification,
terencez 0:1fa43ab66921 30 are permitted provided that the following conditions are met:
terencez 0:1fa43ab66921 31
terencez 0:1fa43ab66921 32 * Redistributions of source code must retain the above copyright notice,
terencez 0:1fa43ab66921 33 this list of conditions and the following disclaimer.
terencez 0:1fa43ab66921 34 * Redistributions in binary form must reproduce the above copyright notice,
terencez 0:1fa43ab66921 35 this list of conditions and the following disclaimer in the documentation
terencez 0:1fa43ab66921 36 and/or other materials provided with the distribution.
terencez 0:1fa43ab66921 37 * Neither the name of Intel Corporation nor the names of its contributors
terencez 0:1fa43ab66921 38 may be used to endorse or promote products derived from this software
terencez 0:1fa43ab66921 39 without specific prior written permission.
terencez 0:1fa43ab66921 40
terencez 0:1fa43ab66921 41 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
terencez 0:1fa43ab66921 42 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
terencez 0:1fa43ab66921 43 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
terencez 0:1fa43ab66921 44 IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
terencez 0:1fa43ab66921 45 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
terencez 0:1fa43ab66921 46 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
terencez 0:1fa43ab66921 47 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
terencez 0:1fa43ab66921 48 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
terencez 0:1fa43ab66921 49 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
terencez 0:1fa43ab66921 50 THE POSSIBILITY OF SUCH DAMAGE.
terencez 0:1fa43ab66921 51
terencez 0:1fa43ab66921 52 David Navarro <david.navarro@intel.com>
terencez 0:1fa43ab66921 53
terencez 0:1fa43ab66921 54 */
terencez 0:1fa43ab66921 55
terencez 0:1fa43ab66921 56 #include "internals.h"
terencez 0:1fa43ab66921 57
terencez 0:1fa43ab66921 58 #include <stdlib.h>
terencez 0:1fa43ab66921 59 #include <string.h>
terencez 0:1fa43ab66921 60 #include <stdio.h>
terencez 0:1fa43ab66921 61
terencez 0:1fa43ab66921 62 #define MAX_LOCATION_LENGTH 10 // strlen("/rd/65534") + 1
terencez 0:1fa43ab66921 63
terencez 0:1fa43ab66921 64 #ifdef LWM2M_CLIENT_MODE
terencez 0:1fa43ab66921 65
terencez 0:1fa43ab66921 66 static int prv_getRegistrationQuery(lwm2m_context_t * contextP,
terencez 0:1fa43ab66921 67 lwm2m_server_t * server,
terencez 0:1fa43ab66921 68 char * buffer,
terencez 0:1fa43ab66921 69 size_t length)
terencez 0:1fa43ab66921 70 {
terencez 0:1fa43ab66921 71 int index;
terencez 0:1fa43ab66921 72 int res;
terencez 0:1fa43ab66921 73
terencez 0:1fa43ab66921 74 index = utils_stringCopy(buffer, length, QUERY_STARTER QUERY_VERSION_FULL QUERY_DELIMITER QUERY_NAME);
terencez 0:1fa43ab66921 75 if (index < 0) return 0;
terencez 0:1fa43ab66921 76 res = utils_stringCopy(buffer + index, length - index, contextP->endpointName);
terencez 0:1fa43ab66921 77 if (res < 0) return 0;
terencez 0:1fa43ab66921 78 index += res;
terencez 0:1fa43ab66921 79
terencez 0:1fa43ab66921 80 if (NULL != contextP->msisdn)
terencez 0:1fa43ab66921 81 {
terencez 0:1fa43ab66921 82 res = utils_stringCopy(buffer + index, length - index, QUERY_DELIMITER QUERY_SMS);
terencez 0:1fa43ab66921 83 if (res < 0) return 0;
terencez 0:1fa43ab66921 84 index += res;
terencez 0:1fa43ab66921 85 res = utils_stringCopy(buffer + index, length - index, contextP->msisdn);
terencez 0:1fa43ab66921 86 if (res < 0) return 0;
terencez 0:1fa43ab66921 87 index += res;
terencez 0:1fa43ab66921 88 }
terencez 0:1fa43ab66921 89
terencez 0:1fa43ab66921 90 switch (server->binding)
terencez 0:1fa43ab66921 91 {
terencez 0:1fa43ab66921 92 case BINDING_U:
terencez 0:1fa43ab66921 93 res = utils_stringCopy(buffer + index, length - index, "&b=U");
terencez 0:1fa43ab66921 94 break;
terencez 0:1fa43ab66921 95 case BINDING_UQ:
terencez 0:1fa43ab66921 96 res = utils_stringCopy(buffer + index, length - index, "&b=UQ");
terencez 0:1fa43ab66921 97 break;
terencez 0:1fa43ab66921 98 case BINDING_S:
terencez 0:1fa43ab66921 99 res = utils_stringCopy(buffer + index, length - index, "&b=S");
terencez 0:1fa43ab66921 100 break;
terencez 0:1fa43ab66921 101 case BINDING_SQ:
terencez 0:1fa43ab66921 102 res = utils_stringCopy(buffer + index, length - index, "&b=SQ");
terencez 0:1fa43ab66921 103 break;
terencez 0:1fa43ab66921 104 case BINDING_US:
terencez 0:1fa43ab66921 105 res = utils_stringCopy(buffer + index, length - index, "&b=US");
terencez 0:1fa43ab66921 106 break;
terencez 0:1fa43ab66921 107 case BINDING_UQS:
terencez 0:1fa43ab66921 108 res = utils_stringCopy(buffer + index, length - index, "&b=UQS");
terencez 0:1fa43ab66921 109 break;
terencez 0:1fa43ab66921 110 default:
terencez 0:1fa43ab66921 111 res = -1;
terencez 0:1fa43ab66921 112 }
terencez 0:1fa43ab66921 113 if (res < 0) return 0;
terencez 0:1fa43ab66921 114
terencez 0:1fa43ab66921 115 return index + res;
terencez 0:1fa43ab66921 116 }
terencez 0:1fa43ab66921 117
terencez 0:1fa43ab66921 118 static void prv_handleRegistrationReply(lwm2m_transaction_t * transacP,
terencez 0:1fa43ab66921 119 void * message)
terencez 0:1fa43ab66921 120 {
terencez 0:1fa43ab66921 121 coap_packet_t * packet = (coap_packet_t *)message;
terencez 0:1fa43ab66921 122 lwm2m_server_t * targetP = (lwm2m_server_t *)(transacP->userData);
terencez 0:1fa43ab66921 123
terencez 0:1fa43ab66921 124 if (targetP->status == STATE_REG_PENDING)
terencez 0:1fa43ab66921 125 {
terencez 0:1fa43ab66921 126 time_t tv_sec = lwm2m_gettime();
terencez 0:1fa43ab66921 127 if (tv_sec >= 0)
terencez 0:1fa43ab66921 128 {
terencez 0:1fa43ab66921 129 targetP->registration = tv_sec;
terencez 0:1fa43ab66921 130 }
terencez 0:1fa43ab66921 131 if (packet != NULL && packet->code == COAP_201_CREATED)
terencez 0:1fa43ab66921 132 {
terencez 0:1fa43ab66921 133 targetP->status = STATE_REGISTERED;
terencez 0:1fa43ab66921 134 if (NULL != targetP->location)
terencez 0:1fa43ab66921 135 {
terencez 0:1fa43ab66921 136 lwm2m_free(targetP->location);
terencez 0:1fa43ab66921 137 }
terencez 0:1fa43ab66921 138 targetP->location = coap_get_multi_option_as_string(packet->location_path);
terencez 0:1fa43ab66921 139
terencez 0:1fa43ab66921 140 LOG("Registration successful");
terencez 0:1fa43ab66921 141 }
terencez 0:1fa43ab66921 142 else
terencez 0:1fa43ab66921 143 {
terencez 0:1fa43ab66921 144 targetP->status = STATE_REG_FAILED;
terencez 0:1fa43ab66921 145 LOG("Registration failed");
terencez 0:1fa43ab66921 146 }
terencez 0:1fa43ab66921 147 }
terencez 0:1fa43ab66921 148 }
terencez 0:1fa43ab66921 149
terencez 0:1fa43ab66921 150 #define PRV_QUERY_BUFFER_LENGTH 200
terencez 0:1fa43ab66921 151
terencez 0:1fa43ab66921 152 // send the registration for a single server
terencez 0:1fa43ab66921 153 static uint8_t prv_register(lwm2m_context_t * contextP,
terencez 0:1fa43ab66921 154 lwm2m_server_t * server)
terencez 0:1fa43ab66921 155 {
terencez 0:1fa43ab66921 156 char query[200];
terencez 0:1fa43ab66921 157 int query_length;
terencez 0:1fa43ab66921 158 uint8_t payload[512];
terencez 0:1fa43ab66921 159 int payload_length;
terencez 0:1fa43ab66921 160 lwm2m_transaction_t * transaction;
terencez 0:1fa43ab66921 161
terencez 0:1fa43ab66921 162 payload_length = object_getRegisterPayload(contextP, payload, sizeof(payload));
terencez 0:1fa43ab66921 163 if (payload_length == 0) return COAP_500_INTERNAL_SERVER_ERROR;
terencez 0:1fa43ab66921 164
terencez 0:1fa43ab66921 165 query_length = prv_getRegistrationQuery(contextP, server, query, sizeof(query));
terencez 0:1fa43ab66921 166
terencez 0:1fa43ab66921 167 if (query_length == 0) return COAP_500_INTERNAL_SERVER_ERROR;
terencez 0:1fa43ab66921 168
terencez 0:1fa43ab66921 169 if (0 != server->lifetime)
terencez 0:1fa43ab66921 170 {
terencez 0:1fa43ab66921 171 int res;
terencez 0:1fa43ab66921 172
terencez 0:1fa43ab66921 173 res = utils_stringCopy(query + query_length, PRV_QUERY_BUFFER_LENGTH - query_length, QUERY_DELIMITER QUERY_LIFETIME);
terencez 0:1fa43ab66921 174 if (res < 0) return COAP_500_INTERNAL_SERVER_ERROR;
terencez 0:1fa43ab66921 175 query_length += res;
terencez 0:1fa43ab66921 176 res = utils_intCopy(query + query_length, PRV_QUERY_BUFFER_LENGTH - query_length, server->lifetime);
terencez 0:1fa43ab66921 177 if (res < 0) return COAP_500_INTERNAL_SERVER_ERROR;
terencez 0:1fa43ab66921 178 query_length += res;
terencez 0:1fa43ab66921 179 }
terencez 0:1fa43ab66921 180
terencez 0:1fa43ab66921 181 if (server->sessionH == NULL)
terencez 0:1fa43ab66921 182 {
terencez 0:1fa43ab66921 183 server->sessionH = lwm2m_connect_server(server->secObjInstID, contextP->userData);
terencez 0:1fa43ab66921 184 }
terencez 0:1fa43ab66921 185
terencez 0:1fa43ab66921 186 if (NULL == server->sessionH) return COAP_503_SERVICE_UNAVAILABLE;
terencez 0:1fa43ab66921 187
terencez 0:1fa43ab66921 188 transaction = transaction_new(server->sessionH, COAP_POST, NULL, NULL, contextP->nextMID++, 4, NULL);
terencez 0:1fa43ab66921 189 if (transaction == NULL) return COAP_500_INTERNAL_SERVER_ERROR;
terencez 0:1fa43ab66921 190
terencez 0:1fa43ab66921 191 coap_set_header_uri_path(transaction->message, "/"URI_REGISTRATION_SEGMENT);
terencez 0:1fa43ab66921 192 coap_set_header_uri_query(transaction->message, query);
terencez 0:1fa43ab66921 193 coap_set_header_content_type(transaction->message, LWM2M_CONTENT_LINK);
terencez 0:1fa43ab66921 194 coap_set_payload(transaction->message, payload, payload_length);
terencez 0:1fa43ab66921 195
terencez 0:1fa43ab66921 196 transaction->callback = prv_handleRegistrationReply;
terencez 0:1fa43ab66921 197 transaction->userData = (void *) server;
terencez 0:1fa43ab66921 198
terencez 0:1fa43ab66921 199 contextP->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(contextP->transactionList, transaction);
terencez 0:1fa43ab66921 200 if (transaction_send(contextP, transaction) != 0) return COAP_500_INTERNAL_SERVER_ERROR;
terencez 0:1fa43ab66921 201
terencez 0:1fa43ab66921 202 server->status = STATE_REG_PENDING;
terencez 0:1fa43ab66921 203
terencez 0:1fa43ab66921 204 return COAP_NO_ERROR;
terencez 0:1fa43ab66921 205 }
terencez 0:1fa43ab66921 206
terencez 0:1fa43ab66921 207 static void prv_handleRegistrationUpdateReply(lwm2m_transaction_t * transacP,
terencez 0:1fa43ab66921 208 void * message)
terencez 0:1fa43ab66921 209 {
terencez 0:1fa43ab66921 210 coap_packet_t * packet = (coap_packet_t *)message;
terencez 0:1fa43ab66921 211 lwm2m_server_t * targetP = (lwm2m_server_t *)(transacP->userData);
terencez 0:1fa43ab66921 212
terencez 0:1fa43ab66921 213 if (targetP->status == STATE_REG_UPDATE_PENDING)
terencez 0:1fa43ab66921 214 {
terencez 0:1fa43ab66921 215 time_t tv_sec = lwm2m_gettime();
terencez 0:1fa43ab66921 216 if (tv_sec >= 0)
terencez 0:1fa43ab66921 217 {
terencez 0:1fa43ab66921 218 targetP->registration = tv_sec;
terencez 0:1fa43ab66921 219 }
terencez 0:1fa43ab66921 220 if (packet != NULL && packet->code == COAP_204_CHANGED)
terencez 0:1fa43ab66921 221 {
terencez 0:1fa43ab66921 222 targetP->status = STATE_REGISTERED;
terencez 0:1fa43ab66921 223 LOG("Registration update successful");
terencez 0:1fa43ab66921 224 }
terencez 0:1fa43ab66921 225 else
terencez 0:1fa43ab66921 226 {
terencez 0:1fa43ab66921 227 targetP->status = STATE_REG_FAILED;
terencez 0:1fa43ab66921 228 LOG("Registration update failed");
terencez 0:1fa43ab66921 229 }
terencez 0:1fa43ab66921 230 }
terencez 0:1fa43ab66921 231 }
terencez 0:1fa43ab66921 232
terencez 0:1fa43ab66921 233 static int prv_updateRegistration(lwm2m_context_t * contextP,
terencez 0:1fa43ab66921 234 lwm2m_server_t * server,
terencez 0:1fa43ab66921 235 bool withObjects)
terencez 0:1fa43ab66921 236 {
terencez 0:1fa43ab66921 237 lwm2m_transaction_t * transaction;
terencez 0:1fa43ab66921 238 uint8_t payload[512];
terencez 0:1fa43ab66921 239 int payload_length;
terencez 0:1fa43ab66921 240
terencez 0:1fa43ab66921 241 transaction = transaction_new(server->sessionH, COAP_POST, NULL, NULL, contextP->nextMID++, 4, NULL);
terencez 0:1fa43ab66921 242 if (transaction == NULL) return COAP_500_INTERNAL_SERVER_ERROR;
terencez 0:1fa43ab66921 243
terencez 0:1fa43ab66921 244 coap_set_header_uri_path(transaction->message, server->location);
terencez 0:1fa43ab66921 245
terencez 0:1fa43ab66921 246 if (withObjects == true)
terencez 0:1fa43ab66921 247 {
terencez 0:1fa43ab66921 248 payload_length = object_getRegisterPayload(contextP, payload, sizeof(payload));
terencez 0:1fa43ab66921 249 if (payload_length == 0)
terencez 0:1fa43ab66921 250 {
terencez 0:1fa43ab66921 251 transaction_free(transaction);
terencez 0:1fa43ab66921 252 return COAP_500_INTERNAL_SERVER_ERROR;
terencez 0:1fa43ab66921 253 }
terencez 0:1fa43ab66921 254 coap_set_payload(transaction->message, payload, payload_length);
terencez 0:1fa43ab66921 255 }
terencez 0:1fa43ab66921 256
terencez 0:1fa43ab66921 257 transaction->callback = prv_handleRegistrationUpdateReply;
terencez 0:1fa43ab66921 258 transaction->userData = (void *) server;
terencez 0:1fa43ab66921 259
terencez 0:1fa43ab66921 260 contextP->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(contextP->transactionList, transaction);
terencez 0:1fa43ab66921 261
terencez 0:1fa43ab66921 262 if (transaction_send(contextP, transaction) == 0)
terencez 0:1fa43ab66921 263 {
terencez 0:1fa43ab66921 264 server->status = STATE_REG_UPDATE_PENDING;
terencez 0:1fa43ab66921 265 }
terencez 0:1fa43ab66921 266
terencez 0:1fa43ab66921 267 return COAP_NO_ERROR;
terencez 0:1fa43ab66921 268 }
terencez 0:1fa43ab66921 269
terencez 0:1fa43ab66921 270 // update the registration of a given server
terencez 0:1fa43ab66921 271 int lwm2m_update_registration(lwm2m_context_t * contextP,
terencez 0:1fa43ab66921 272 uint16_t shortServerID,
terencez 0:1fa43ab66921 273 bool withObjects)
terencez 0:1fa43ab66921 274 {
terencez 0:1fa43ab66921 275 lwm2m_server_t * targetP;
terencez 0:1fa43ab66921 276 uint8_t result;
terencez 0:1fa43ab66921 277
terencez 0:1fa43ab66921 278 LOG_ARG("State: %s, shortServerID: %d", STR_STATE(contextP->state), shortServerID);
terencez 0:1fa43ab66921 279
terencez 0:1fa43ab66921 280 result = COAP_NO_ERROR;
terencez 0:1fa43ab66921 281
terencez 0:1fa43ab66921 282 targetP = contextP->serverList;
terencez 0:1fa43ab66921 283 if (targetP == NULL)
terencez 0:1fa43ab66921 284 {
terencez 0:1fa43ab66921 285 if (object_getServers(contextP) == -1)
terencez 0:1fa43ab66921 286 {
terencez 0:1fa43ab66921 287 LOG("No server found");
terencez 0:1fa43ab66921 288 return COAP_404_NOT_FOUND;
terencez 0:1fa43ab66921 289 }
terencez 0:1fa43ab66921 290 }
terencez 0:1fa43ab66921 291 while (targetP != NULL && result == COAP_NO_ERROR)
terencez 0:1fa43ab66921 292 {
terencez 0:1fa43ab66921 293 if (shortServerID != 0)
terencez 0:1fa43ab66921 294 {
terencez 0:1fa43ab66921 295 if (targetP->shortID == shortServerID)
terencez 0:1fa43ab66921 296 {
terencez 0:1fa43ab66921 297 // found the server, trigger the update transaction
terencez 0:1fa43ab66921 298 if (targetP->status == STATE_REGISTERED
terencez 0:1fa43ab66921 299 || targetP->status == STATE_REG_UPDATE_PENDING)
terencez 0:1fa43ab66921 300 {
terencez 0:1fa43ab66921 301 if (withObjects == true)
terencez 0:1fa43ab66921 302 {
terencez 0:1fa43ab66921 303 targetP->status = STATE_REG_FULL_UPDATE_NEEDED;
terencez 0:1fa43ab66921 304 }
terencez 0:1fa43ab66921 305 else
terencez 0:1fa43ab66921 306 {
terencez 0:1fa43ab66921 307 targetP->status = STATE_REG_UPDATE_NEEDED;
terencez 0:1fa43ab66921 308 }
terencez 0:1fa43ab66921 309 return COAP_NO_ERROR;
terencez 0:1fa43ab66921 310 }
terencez 0:1fa43ab66921 311 else if ((targetP->status == STATE_REG_FULL_UPDATE_NEEDED)
terencez 0:1fa43ab66921 312 || (targetP->status == STATE_REG_UPDATE_NEEDED))
terencez 0:1fa43ab66921 313 {
terencez 0:1fa43ab66921 314 // if REG (FULL) UPDATE is already set, returns COAP_NO_ERROR
terencez 0:1fa43ab66921 315 if (withObjects == true)
terencez 0:1fa43ab66921 316 {
terencez 0:1fa43ab66921 317 targetP->status = STATE_REG_FULL_UPDATE_NEEDED;
terencez 0:1fa43ab66921 318 }
terencez 0:1fa43ab66921 319 return COAP_NO_ERROR;
terencez 0:1fa43ab66921 320 }
terencez 0:1fa43ab66921 321 else
terencez 0:1fa43ab66921 322 {
terencez 0:1fa43ab66921 323 return COAP_400_BAD_REQUEST;
terencez 0:1fa43ab66921 324 }
terencez 0:1fa43ab66921 325 }
terencez 0:1fa43ab66921 326 }
terencez 0:1fa43ab66921 327 else
terencez 0:1fa43ab66921 328 {
terencez 0:1fa43ab66921 329 if (targetP->status == STATE_REGISTERED
terencez 0:1fa43ab66921 330 || targetP->status == STATE_REG_UPDATE_PENDING)
terencez 0:1fa43ab66921 331 {
terencez 0:1fa43ab66921 332 if (withObjects == true)
terencez 0:1fa43ab66921 333 {
terencez 0:1fa43ab66921 334 targetP->status = STATE_REG_FULL_UPDATE_NEEDED;
terencez 0:1fa43ab66921 335 }
terencez 0:1fa43ab66921 336 else
terencez 0:1fa43ab66921 337 {
terencez 0:1fa43ab66921 338 targetP->status = STATE_REG_UPDATE_NEEDED;
terencez 0:1fa43ab66921 339 }
terencez 0:1fa43ab66921 340 }
terencez 0:1fa43ab66921 341 }
terencez 0:1fa43ab66921 342 targetP = targetP->next;
terencez 0:1fa43ab66921 343 }
terencez 0:1fa43ab66921 344
terencez 0:1fa43ab66921 345 if (shortServerID != 0
terencez 0:1fa43ab66921 346 && targetP == NULL)
terencez 0:1fa43ab66921 347 {
terencez 0:1fa43ab66921 348 // no server found
terencez 0:1fa43ab66921 349 result = COAP_404_NOT_FOUND;
terencez 0:1fa43ab66921 350 }
terencez 0:1fa43ab66921 351
terencez 0:1fa43ab66921 352 return result;
terencez 0:1fa43ab66921 353 }
terencez 0:1fa43ab66921 354
terencez 0:1fa43ab66921 355 uint8_t registration_start(lwm2m_context_t * contextP)
terencez 0:1fa43ab66921 356 {
terencez 0:1fa43ab66921 357 lwm2m_server_t * targetP;
terencez 0:1fa43ab66921 358 uint8_t result;
terencez 0:1fa43ab66921 359
terencez 0:1fa43ab66921 360 LOG_ARG("State: %s", STR_STATE(contextP->state));
terencez 0:1fa43ab66921 361
terencez 0:1fa43ab66921 362 result = COAP_NO_ERROR;
terencez 0:1fa43ab66921 363
terencez 0:1fa43ab66921 364 targetP = contextP->serverList;
terencez 0:1fa43ab66921 365 while (targetP != NULL && result == COAP_NO_ERROR)
terencez 0:1fa43ab66921 366 {
terencez 0:1fa43ab66921 367 if (targetP->status == STATE_DEREGISTERED
terencez 0:1fa43ab66921 368 || targetP->status == STATE_REG_FAILED)
terencez 0:1fa43ab66921 369 {
terencez 0:1fa43ab66921 370 result = prv_register(contextP, targetP);
terencez 0:1fa43ab66921 371 }
terencez 0:1fa43ab66921 372 targetP = targetP->next;
terencez 0:1fa43ab66921 373 }
terencez 0:1fa43ab66921 374
terencez 0:1fa43ab66921 375 return result;
terencez 0:1fa43ab66921 376 }
terencez 0:1fa43ab66921 377
terencez 0:1fa43ab66921 378
terencez 0:1fa43ab66921 379 /*
terencez 0:1fa43ab66921 380 * Returns STATE_REG_PENDING if at least one registration is still pending
terencez 0:1fa43ab66921 381 * Returns STATE_REGISTERED if no registration is pending and there is at least one server the client is registered to
terencez 0:1fa43ab66921 382 * Returns STATE_REG_FAILED if all registration failed.
terencez 0:1fa43ab66921 383 */
terencez 0:1fa43ab66921 384 lwm2m_status_t registration_getStatus(lwm2m_context_t * contextP)
terencez 0:1fa43ab66921 385 {
terencez 0:1fa43ab66921 386 lwm2m_server_t * targetP;
terencez 0:1fa43ab66921 387 lwm2m_status_t reg_status;
terencez 0:1fa43ab66921 388
terencez 0:1fa43ab66921 389 LOG_ARG("State: %s", STR_STATE(contextP->state));
terencez 0:1fa43ab66921 390
terencez 0:1fa43ab66921 391 targetP = contextP->serverList;
terencez 0:1fa43ab66921 392 reg_status = STATE_REG_FAILED;
terencez 0:1fa43ab66921 393
terencez 0:1fa43ab66921 394 while (targetP != NULL)
terencez 0:1fa43ab66921 395 {
terencez 0:1fa43ab66921 396 LOG_ARG("targetP->status: %s", STR_STATUS(targetP->status));
terencez 0:1fa43ab66921 397 switch (targetP->status)
terencez 0:1fa43ab66921 398 {
terencez 0:1fa43ab66921 399 case STATE_REGISTERED:
terencez 0:1fa43ab66921 400 case STATE_REG_UPDATE_NEEDED:
terencez 0:1fa43ab66921 401 case STATE_REG_FULL_UPDATE_NEEDED:
terencez 0:1fa43ab66921 402 case STATE_REG_UPDATE_PENDING:
terencez 0:1fa43ab66921 403 if (reg_status == STATE_REG_FAILED)
terencez 0:1fa43ab66921 404 {
terencez 0:1fa43ab66921 405 reg_status = STATE_REGISTERED;
terencez 0:1fa43ab66921 406 }
terencez 0:1fa43ab66921 407 break;
terencez 0:1fa43ab66921 408
terencez 0:1fa43ab66921 409 case STATE_REG_PENDING:
terencez 0:1fa43ab66921 410 reg_status = STATE_REG_PENDING;
terencez 0:1fa43ab66921 411 break;
terencez 0:1fa43ab66921 412
terencez 0:1fa43ab66921 413 case STATE_REG_FAILED:
terencez 0:1fa43ab66921 414 case STATE_DEREG_PENDING:
terencez 0:1fa43ab66921 415 case STATE_DEREGISTERED:
terencez 0:1fa43ab66921 416 default:
terencez 0:1fa43ab66921 417 break;
terencez 0:1fa43ab66921 418 }
terencez 0:1fa43ab66921 419 LOG_ARG("reg_status: %s", STR_STATUS(reg_status));
terencez 0:1fa43ab66921 420
terencez 0:1fa43ab66921 421 targetP = targetP->next;
terencez 0:1fa43ab66921 422 }
terencez 0:1fa43ab66921 423
terencez 0:1fa43ab66921 424 return reg_status;
terencez 0:1fa43ab66921 425 }
terencez 0:1fa43ab66921 426
terencez 0:1fa43ab66921 427 static void prv_handleDeregistrationReply(lwm2m_transaction_t * transacP,
terencez 0:1fa43ab66921 428 void * message)
terencez 0:1fa43ab66921 429 {
terencez 0:1fa43ab66921 430 lwm2m_server_t * targetP;
terencez 0:1fa43ab66921 431
terencez 0:1fa43ab66921 432 targetP = (lwm2m_server_t *)(transacP->userData);
terencez 0:1fa43ab66921 433 if (NULL != targetP)
terencez 0:1fa43ab66921 434 {
terencez 0:1fa43ab66921 435 if (targetP->status == STATE_DEREG_PENDING)
terencez 0:1fa43ab66921 436 {
terencez 0:1fa43ab66921 437 targetP->status = STATE_DEREGISTERED;
terencez 0:1fa43ab66921 438 }
terencez 0:1fa43ab66921 439 }
terencez 0:1fa43ab66921 440 }
terencez 0:1fa43ab66921 441
terencez 0:1fa43ab66921 442 void registration_deregister(lwm2m_context_t * contextP,
terencez 0:1fa43ab66921 443 lwm2m_server_t * serverP)
terencez 0:1fa43ab66921 444 {
terencez 0:1fa43ab66921 445 lwm2m_transaction_t * transaction;
terencez 0:1fa43ab66921 446
terencez 0:1fa43ab66921 447 LOG_ARG("State: %s, serverP->status: %s", STR_STATE(contextP->state), STR_STATUS(serverP->status));
terencez 0:1fa43ab66921 448
terencez 0:1fa43ab66921 449 if (serverP->status == STATE_DEREGISTERED
terencez 0:1fa43ab66921 450 || serverP->status == STATE_REG_PENDING
terencez 0:1fa43ab66921 451 || serverP->status == STATE_DEREG_PENDING
terencez 0:1fa43ab66921 452 || serverP->status == STATE_REG_FAILED
terencez 0:1fa43ab66921 453 || serverP->location == NULL)
terencez 0:1fa43ab66921 454 {
terencez 0:1fa43ab66921 455 return;
terencez 0:1fa43ab66921 456 }
terencez 0:1fa43ab66921 457
terencez 0:1fa43ab66921 458 transaction = transaction_new(serverP->sessionH, COAP_DELETE, NULL, NULL, contextP->nextMID++, 4, NULL);
terencez 0:1fa43ab66921 459 if (transaction == NULL) return;
terencez 0:1fa43ab66921 460
terencez 0:1fa43ab66921 461 coap_set_header_uri_path(transaction->message, serverP->location);
terencez 0:1fa43ab66921 462
terencez 0:1fa43ab66921 463 transaction->callback = prv_handleDeregistrationReply;
terencez 0:1fa43ab66921 464 transaction->userData = (void *) contextP;
terencez 0:1fa43ab66921 465
terencez 0:1fa43ab66921 466 contextP->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(contextP->transactionList, transaction);
terencez 0:1fa43ab66921 467 if (transaction_send(contextP, transaction) == 0)
terencez 0:1fa43ab66921 468 {
terencez 0:1fa43ab66921 469 serverP->status = STATE_DEREG_PENDING;
terencez 0:1fa43ab66921 470 }
terencez 0:1fa43ab66921 471 }
terencez 0:1fa43ab66921 472 #endif
terencez 0:1fa43ab66921 473
terencez 0:1fa43ab66921 474 #ifdef LWM2M_SERVER_MODE
terencez 0:1fa43ab66921 475 static void prv_freeClientObjectList(lwm2m_client_object_t * objects)
terencez 0:1fa43ab66921 476 {
terencez 0:1fa43ab66921 477 while (objects != NULL)
terencez 0:1fa43ab66921 478 {
terencez 0:1fa43ab66921 479 lwm2m_client_object_t * objP;
terencez 0:1fa43ab66921 480
terencez 0:1fa43ab66921 481 while (objects->instanceList != NULL)
terencez 0:1fa43ab66921 482 {
terencez 0:1fa43ab66921 483 lwm2m_list_t * target;
terencez 0:1fa43ab66921 484
terencez 0:1fa43ab66921 485 target = objects->instanceList;
terencez 0:1fa43ab66921 486 objects->instanceList = objects->instanceList->next;
terencez 0:1fa43ab66921 487 lwm2m_free(target);
terencez 0:1fa43ab66921 488 }
terencez 0:1fa43ab66921 489
terencez 0:1fa43ab66921 490 objP = objects;
terencez 0:1fa43ab66921 491 objects = objects->next;
terencez 0:1fa43ab66921 492 lwm2m_free(objP);
terencez 0:1fa43ab66921 493 }
terencez 0:1fa43ab66921 494 }
terencez 0:1fa43ab66921 495
terencez 0:1fa43ab66921 496 static int prv_getParameters(multi_option_t * query,
terencez 0:1fa43ab66921 497 char ** nameP,
terencez 0:1fa43ab66921 498 uint32_t * lifetimeP,
terencez 0:1fa43ab66921 499 char ** msisdnP,
terencez 0:1fa43ab66921 500 lwm2m_binding_t * bindingP,
terencez 0:1fa43ab66921 501 char ** versionP)
terencez 0:1fa43ab66921 502 {
terencez 0:1fa43ab66921 503 *nameP = NULL;
terencez 0:1fa43ab66921 504 *lifetimeP = 0;
terencez 0:1fa43ab66921 505 *msisdnP = NULL;
terencez 0:1fa43ab66921 506 *bindingP = BINDING_UNKNOWN;
terencez 0:1fa43ab66921 507 *versionP = NULL;
terencez 0:1fa43ab66921 508
terencez 0:1fa43ab66921 509 while (query != NULL)
terencez 0:1fa43ab66921 510 {
terencez 0:1fa43ab66921 511 if (lwm2m_strncmp((char *)query->data, QUERY_NAME, QUERY_NAME_LEN) == 0)
terencez 0:1fa43ab66921 512 {
terencez 0:1fa43ab66921 513 if (*nameP != NULL) goto error;
terencez 0:1fa43ab66921 514 if (query->len == QUERY_NAME_LEN) goto error;
terencez 0:1fa43ab66921 515
terencez 0:1fa43ab66921 516 *nameP = (char *)lwm2m_malloc(query->len - QUERY_NAME_LEN + 1);
terencez 0:1fa43ab66921 517 if (*nameP != NULL)
terencez 0:1fa43ab66921 518 {
terencez 0:1fa43ab66921 519 memcpy(*nameP, query->data + QUERY_NAME_LEN, query->len - QUERY_NAME_LEN);
terencez 0:1fa43ab66921 520 (*nameP)[query->len - QUERY_NAME_LEN] = 0;
terencez 0:1fa43ab66921 521 }
terencez 0:1fa43ab66921 522 }
terencez 0:1fa43ab66921 523 else if (lwm2m_strncmp((char *)query->data, QUERY_SMS, QUERY_SMS_LEN) == 0)
terencez 0:1fa43ab66921 524 {
terencez 0:1fa43ab66921 525 if (*msisdnP != NULL) goto error;
terencez 0:1fa43ab66921 526 if (query->len == QUERY_SMS_LEN) goto error;
terencez 0:1fa43ab66921 527
terencez 0:1fa43ab66921 528 *msisdnP = (char *)lwm2m_malloc(query->len - QUERY_SMS_LEN + 1);
terencez 0:1fa43ab66921 529 if (*msisdnP != NULL)
terencez 0:1fa43ab66921 530 {
terencez 0:1fa43ab66921 531 memcpy(*msisdnP, query->data + QUERY_SMS_LEN, query->len - QUERY_SMS_LEN);
terencez 0:1fa43ab66921 532 (*msisdnP)[query->len - QUERY_SMS_LEN] = 0;
terencez 0:1fa43ab66921 533 }
terencez 0:1fa43ab66921 534 }
terencez 0:1fa43ab66921 535 else if (lwm2m_strncmp((char *)query->data, QUERY_LIFETIME, QUERY_LIFETIME_LEN) == 0)
terencez 0:1fa43ab66921 536 {
terencez 0:1fa43ab66921 537 int i;
terencez 0:1fa43ab66921 538
terencez 0:1fa43ab66921 539 if (*lifetimeP != 0) goto error;
terencez 0:1fa43ab66921 540 if (query->len == QUERY_LIFETIME_LEN) goto error;
terencez 0:1fa43ab66921 541
terencez 0:1fa43ab66921 542 for (i = QUERY_LIFETIME_LEN ; i < query->len ; i++)
terencez 0:1fa43ab66921 543 {
terencez 0:1fa43ab66921 544 if (query->data[i] < '0' || query->data[i] > '9') goto error;
terencez 0:1fa43ab66921 545 *lifetimeP = (*lifetimeP * 10) + (query->data[i] - '0');
terencez 0:1fa43ab66921 546 }
terencez 0:1fa43ab66921 547 }
terencez 0:1fa43ab66921 548 else if (lwm2m_strncmp((char *)query->data, QUERY_VERSION, QUERY_VERSION_LEN) == 0)
terencez 0:1fa43ab66921 549 {
terencez 0:1fa43ab66921 550 if (*versionP != NULL) goto error;
terencez 0:1fa43ab66921 551 if (query->len == QUERY_VERSION_LEN) goto error;
terencez 0:1fa43ab66921 552
terencez 0:1fa43ab66921 553 *versionP = (char *)lwm2m_malloc(query->len - QUERY_VERSION_LEN + 1);
terencez 0:1fa43ab66921 554 if (*versionP != NULL)
terencez 0:1fa43ab66921 555 {
terencez 0:1fa43ab66921 556 memcpy(*versionP, query->data + QUERY_VERSION_LEN, query->len - QUERY_VERSION_LEN);
terencez 0:1fa43ab66921 557 (*versionP)[query->len - QUERY_VERSION_LEN] = 0;
terencez 0:1fa43ab66921 558 }
terencez 0:1fa43ab66921 559 }
terencez 0:1fa43ab66921 560 else if (lwm2m_strncmp((char *)query->data, QUERY_BINDING, QUERY_BINDING_LEN) == 0)
terencez 0:1fa43ab66921 561 {
terencez 0:1fa43ab66921 562 if (*bindingP != BINDING_UNKNOWN) goto error;
terencez 0:1fa43ab66921 563 if (query->len == QUERY_BINDING_LEN) goto error;
terencez 0:1fa43ab66921 564
terencez 0:1fa43ab66921 565 *bindingP = utils_stringToBinding(query->data + QUERY_BINDING_LEN, query->len - QUERY_BINDING_LEN);
terencez 0:1fa43ab66921 566 }
terencez 0:1fa43ab66921 567 query = query->next;
terencez 0:1fa43ab66921 568 }
terencez 0:1fa43ab66921 569
terencez 0:1fa43ab66921 570 return 0;
terencez 0:1fa43ab66921 571
terencez 0:1fa43ab66921 572 error:
terencez 0:1fa43ab66921 573 if (*nameP != NULL) lwm2m_free(*nameP);
terencez 0:1fa43ab66921 574 if (*msisdnP != NULL) lwm2m_free(*msisdnP);
terencez 0:1fa43ab66921 575 if (*versionP != NULL) lwm2m_free(*versionP);
terencez 0:1fa43ab66921 576
terencez 0:1fa43ab66921 577 return -1;
terencez 0:1fa43ab66921 578 }
terencez 0:1fa43ab66921 579
terencez 0:1fa43ab66921 580 static uint16_t prv_splitLinkAttribute(uint8_t * data,
terencez 0:1fa43ab66921 581 uint16_t length,
terencez 0:1fa43ab66921 582 uint16_t * keyStart,
terencez 0:1fa43ab66921 583 uint16_t * keyLength,
terencez 0:1fa43ab66921 584 uint16_t * valueStart,
terencez 0:1fa43ab66921 585 uint16_t * valueLength)
terencez 0:1fa43ab66921 586 {
terencez 0:1fa43ab66921 587 uint16_t index;
terencez 0:1fa43ab66921 588 uint16_t end;
terencez 0:1fa43ab66921 589
terencez 0:1fa43ab66921 590 index = 0;
terencez 0:1fa43ab66921 591 while (index < length && data[index] == ' ') index++;
terencez 0:1fa43ab66921 592 if (index == length) return 0;
terencez 0:1fa43ab66921 593
terencez 0:1fa43ab66921 594 if (data[index] == REG_ATTR_SEPARATOR)
terencez 0:1fa43ab66921 595 {
terencez 0:1fa43ab66921 596 index++;
terencez 0:1fa43ab66921 597 }
terencez 0:1fa43ab66921 598 if (index == length) return 0;
terencez 0:1fa43ab66921 599
terencez 0:1fa43ab66921 600 *keyStart = index;
terencez 0:1fa43ab66921 601
terencez 0:1fa43ab66921 602 while (index < length && data[index] != REG_ATTR_EQUALS) index++;
terencez 0:1fa43ab66921 603 if (index == *keyStart || index == length) return 0;
terencez 0:1fa43ab66921 604
terencez 0:1fa43ab66921 605 *keyLength = index - *keyStart;
terencez 0:1fa43ab66921 606
terencez 0:1fa43ab66921 607 index++;
terencez 0:1fa43ab66921 608 while (index < length && data[index] == ' ') index++;
terencez 0:1fa43ab66921 609 if (index == length) return 0;
terencez 0:1fa43ab66921 610
terencez 0:1fa43ab66921 611 *valueStart = index;
terencez 0:1fa43ab66921 612
terencez 0:1fa43ab66921 613 while (index < length && data[index] != REG_ATTR_SEPARATOR) index++;
terencez 0:1fa43ab66921 614 end = index;
terencez 0:1fa43ab66921 615
terencez 0:1fa43ab66921 616 index--;
terencez 0:1fa43ab66921 617 while (index > *valueStart && data[index] == ' ') index--;
terencez 0:1fa43ab66921 618 if (index == *valueStart) return 0;
terencez 0:1fa43ab66921 619
terencez 0:1fa43ab66921 620 *valueLength = index - *valueStart + 1;
terencez 0:1fa43ab66921 621
terencez 0:1fa43ab66921 622 return end;
terencez 0:1fa43ab66921 623 }
terencez 0:1fa43ab66921 624
terencez 0:1fa43ab66921 625 static int prv_parseLinkAttributes(uint8_t * data,
terencez 0:1fa43ab66921 626 uint16_t length,
terencez 0:1fa43ab66921 627 bool * supportJSON,
terencez 0:1fa43ab66921 628 char ** altPath)
terencez 0:1fa43ab66921 629 {
terencez 0:1fa43ab66921 630 uint16_t index;
terencez 0:1fa43ab66921 631 uint16_t pathStart;
terencez 0:1fa43ab66921 632 uint16_t pathLength;
terencez 0:1fa43ab66921 633 bool isValid;
terencez 0:1fa43ab66921 634
terencez 0:1fa43ab66921 635 isValid = false;
terencez 0:1fa43ab66921 636
terencez 0:1fa43ab66921 637 // Expecting application/link-format (RFC6690)
terencez 0:1fa43ab66921 638 // leading space were removed before. Remove trailing spaces.
terencez 0:1fa43ab66921 639 while (length > 0 && data[length-1] == ' ') length--;
terencez 0:1fa43ab66921 640
terencez 0:1fa43ab66921 641 // strip open tag
terencez 0:1fa43ab66921 642 if (length >= 2 && data[0] == REG_URI_START)
terencez 0:1fa43ab66921 643 {
terencez 0:1fa43ab66921 644 data += 1;
terencez 0:1fa43ab66921 645 length -= 1;
terencez 0:1fa43ab66921 646 }
terencez 0:1fa43ab66921 647 else
terencez 0:1fa43ab66921 648 {
terencez 0:1fa43ab66921 649 return 0;
terencez 0:1fa43ab66921 650 }
terencez 0:1fa43ab66921 651
terencez 0:1fa43ab66921 652 pathStart = 0;
terencez 0:1fa43ab66921 653 index = length - 1;
terencez 0:1fa43ab66921 654 while (index > 0 && data[index] != REG_URI_END) index--;
terencez 0:1fa43ab66921 655 // link attributes are required
terencez 0:1fa43ab66921 656 if (index == 0 || index == length - 1) return 0;
terencez 0:1fa43ab66921 657
terencez 0:1fa43ab66921 658 // If there is a preceding /, remove it
terencez 0:1fa43ab66921 659 if (data[pathStart] == '/')
terencez 0:1fa43ab66921 660 {
terencez 0:1fa43ab66921 661 pathStart += 1;
terencez 0:1fa43ab66921 662 }
terencez 0:1fa43ab66921 663 pathLength = index - pathStart;
terencez 0:1fa43ab66921 664
terencez 0:1fa43ab66921 665 index++;
terencez 0:1fa43ab66921 666 if (index >= length || data[index] != REG_ATTR_SEPARATOR) return 0;
terencez 0:1fa43ab66921 667 index++;
terencez 0:1fa43ab66921 668
terencez 0:1fa43ab66921 669 while (index < length)
terencez 0:1fa43ab66921 670 {
terencez 0:1fa43ab66921 671 uint16_t result;
terencez 0:1fa43ab66921 672 uint16_t keyStart;
terencez 0:1fa43ab66921 673 uint16_t keyLength;
terencez 0:1fa43ab66921 674 uint16_t valueStart;
terencez 0:1fa43ab66921 675 uint16_t valueLength;
terencez 0:1fa43ab66921 676
terencez 0:1fa43ab66921 677 result = prv_splitLinkAttribute(data + index, length - index, &keyStart, &keyLength, &valueStart, &valueLength);
terencez 0:1fa43ab66921 678 if (result == 0) return 0;
terencez 0:1fa43ab66921 679
terencez 0:1fa43ab66921 680 if (keyLength == REG_ATTR_TYPE_KEY_LEN
terencez 0:1fa43ab66921 681 && 0 == lwm2m_strncmp(REG_ATTR_TYPE_KEY, data + index + keyStart, keyLength))
terencez 0:1fa43ab66921 682 {
terencez 0:1fa43ab66921 683 if (isValid == true) return 0; // declared twice
terencez 0:1fa43ab66921 684 if (valueLength != REG_ATTR_TYPE_VALUE_LEN
terencez 0:1fa43ab66921 685 || 0 != lwm2m_strncmp(REG_ATTR_TYPE_VALUE, data + index + valueStart, valueLength))
terencez 0:1fa43ab66921 686 {
terencez 0:1fa43ab66921 687 return 0;
terencez 0:1fa43ab66921 688 }
terencez 0:1fa43ab66921 689 isValid = true;
terencez 0:1fa43ab66921 690 }
terencez 0:1fa43ab66921 691 else if (keyLength == REG_ATTR_CONTENT_KEY_LEN
terencez 0:1fa43ab66921 692 && 0 == lwm2m_strncmp(REG_ATTR_CONTENT_KEY, data + index + keyStart, keyLength))
terencez 0:1fa43ab66921 693 {
terencez 0:1fa43ab66921 694 if (*supportJSON == true) return 0; // declared twice
terencez 0:1fa43ab66921 695 if (valueLength == REG_ATTR_CONTENT_JSON_LEN
terencez 0:1fa43ab66921 696 && 0 == lwm2m_strncmp(REG_ATTR_CONTENT_JSON, data + index + valueStart, valueLength))
terencez 0:1fa43ab66921 697 {
terencez 0:1fa43ab66921 698 *supportJSON = true;
terencez 0:1fa43ab66921 699 }
terencez 0:1fa43ab66921 700 else
terencez 0:1fa43ab66921 701 {
terencez 0:1fa43ab66921 702 return 0;
terencez 0:1fa43ab66921 703 }
terencez 0:1fa43ab66921 704 }
terencez 0:1fa43ab66921 705 // else ignore this one
terencez 0:1fa43ab66921 706
terencez 0:1fa43ab66921 707 index += result;
terencez 0:1fa43ab66921 708 }
terencez 0:1fa43ab66921 709
terencez 0:1fa43ab66921 710 if (isValid == false) return 0;
terencez 0:1fa43ab66921 711
terencez 0:1fa43ab66921 712 if (pathLength != 0)
terencez 0:1fa43ab66921 713 {
terencez 0:1fa43ab66921 714 *altPath = (char *)lwm2m_malloc(pathLength + 1);
terencez 0:1fa43ab66921 715 if (*altPath == NULL) return 0;
terencez 0:1fa43ab66921 716 memcpy(*altPath, data + pathStart, pathLength);
terencez 0:1fa43ab66921 717 (*altPath)[pathLength] = 0;
terencez 0:1fa43ab66921 718 }
terencez 0:1fa43ab66921 719
terencez 0:1fa43ab66921 720 return 1;
terencez 0:1fa43ab66921 721 }
terencez 0:1fa43ab66921 722
terencez 0:1fa43ab66921 723 static int prv_getId(uint8_t * data,
terencez 0:1fa43ab66921 724 uint16_t length,
terencez 0:1fa43ab66921 725 uint16_t * objId,
terencez 0:1fa43ab66921 726 uint16_t * instanceId)
terencez 0:1fa43ab66921 727 {
terencez 0:1fa43ab66921 728 int value;
terencez 0:1fa43ab66921 729 uint16_t limit;
terencez 0:1fa43ab66921 730
terencez 0:1fa43ab66921 731 // Expecting application/link-format (RFC6690)
terencez 0:1fa43ab66921 732 // leading space were removed before. Remove trailing spaces.
terencez 0:1fa43ab66921 733 while (length > 0 && data[length-1] == ' ') length--;
terencez 0:1fa43ab66921 734
terencez 0:1fa43ab66921 735 // strip open and close tags
terencez 0:1fa43ab66921 736 if (length >= 1 && data[0] == REG_URI_START && data[length-1] == REG_URI_END)
terencez 0:1fa43ab66921 737 {
terencez 0:1fa43ab66921 738 data += 1;
terencez 0:1fa43ab66921 739 length -= 2;
terencez 0:1fa43ab66921 740 }
terencez 0:1fa43ab66921 741 else
terencez 0:1fa43ab66921 742 {
terencez 0:1fa43ab66921 743 return 0;
terencez 0:1fa43ab66921 744 }
terencez 0:1fa43ab66921 745
terencez 0:1fa43ab66921 746 // If there is a preceding /, remove it
terencez 0:1fa43ab66921 747 if (length >= 1 && data[0] == '/')
terencez 0:1fa43ab66921 748 {
terencez 0:1fa43ab66921 749 data += 1;
terencez 0:1fa43ab66921 750 length -= 1;
terencez 0:1fa43ab66921 751 }
terencez 0:1fa43ab66921 752
terencez 0:1fa43ab66921 753 limit = 0;
terencez 0:1fa43ab66921 754 while (limit < length && data[limit] != '/') limit++;
terencez 0:1fa43ab66921 755 value = uri_getNumber(data, limit);
terencez 0:1fa43ab66921 756 if (value < 0 || value >= LWM2M_MAX_ID) return 0;
terencez 0:1fa43ab66921 757 *objId = value;
terencez 0:1fa43ab66921 758
terencez 0:1fa43ab66921 759 if (limit < length)
terencez 0:1fa43ab66921 760 {
terencez 0:1fa43ab66921 761 limit += 1;
terencez 0:1fa43ab66921 762 data += limit;
terencez 0:1fa43ab66921 763 length -= limit;
terencez 0:1fa43ab66921 764
terencez 0:1fa43ab66921 765 if (length > 0)
terencez 0:1fa43ab66921 766 {
terencez 0:1fa43ab66921 767 value = uri_getNumber(data, length);
terencez 0:1fa43ab66921 768 if (value >= 0 && value < LWM2M_MAX_ID)
terencez 0:1fa43ab66921 769 {
terencez 0:1fa43ab66921 770 *instanceId = value;
terencez 0:1fa43ab66921 771 return 2;
terencez 0:1fa43ab66921 772 }
terencez 0:1fa43ab66921 773 else
terencez 0:1fa43ab66921 774 {
terencez 0:1fa43ab66921 775 return 0;
terencez 0:1fa43ab66921 776 }
terencez 0:1fa43ab66921 777 }
terencez 0:1fa43ab66921 778 }
terencez 0:1fa43ab66921 779
terencez 0:1fa43ab66921 780 return 1;
terencez 0:1fa43ab66921 781 }
terencez 0:1fa43ab66921 782
terencez 0:1fa43ab66921 783 static lwm2m_client_object_t * prv_decodeRegisterPayload(uint8_t * payload,
terencez 0:1fa43ab66921 784 uint16_t payloadLength,
terencez 0:1fa43ab66921 785 bool * supportJSON,
terencez 0:1fa43ab66921 786 char ** altPath)
terencez 0:1fa43ab66921 787 {
terencez 0:1fa43ab66921 788 uint16_t index;
terencez 0:1fa43ab66921 789 lwm2m_client_object_t * objList;
terencez 0:1fa43ab66921 790 bool linkAttrFound;
terencez 0:1fa43ab66921 791
terencez 0:1fa43ab66921 792 *altPath = NULL;
terencez 0:1fa43ab66921 793 *supportJSON = false;
terencez 0:1fa43ab66921 794 objList = NULL;
terencez 0:1fa43ab66921 795 linkAttrFound = false;
terencez 0:1fa43ab66921 796 index = 0;
terencez 0:1fa43ab66921 797
terencez 0:1fa43ab66921 798 while (index <= payloadLength)
terencez 0:1fa43ab66921 799 {
terencez 0:1fa43ab66921 800 uint16_t start;
terencez 0:1fa43ab66921 801 uint16_t length;
terencez 0:1fa43ab66921 802 int result;
terencez 0:1fa43ab66921 803 uint16_t id;
terencez 0:1fa43ab66921 804 uint16_t instance;
terencez 0:1fa43ab66921 805
terencez 0:1fa43ab66921 806 while (index < payloadLength && payload[index] == ' ') index++;
terencez 0:1fa43ab66921 807 if (index == payloadLength) break;
terencez 0:1fa43ab66921 808
terencez 0:1fa43ab66921 809 start = index;
terencez 0:1fa43ab66921 810 while (index < payloadLength && payload[index] != REG_DELIMITER) index++;
terencez 0:1fa43ab66921 811 length = index - start;
terencez 0:1fa43ab66921 812
terencez 0:1fa43ab66921 813 result = prv_getId(payload + start, length, &id, &instance);
terencez 0:1fa43ab66921 814 if (result != 0)
terencez 0:1fa43ab66921 815 {
terencez 0:1fa43ab66921 816 lwm2m_client_object_t * objectP;
terencez 0:1fa43ab66921 817
terencez 0:1fa43ab66921 818 objectP = (lwm2m_client_object_t *)lwm2m_list_find((lwm2m_list_t *)objList, id);
terencez 0:1fa43ab66921 819 if (objectP == NULL)
terencez 0:1fa43ab66921 820 {
terencez 0:1fa43ab66921 821 objectP = (lwm2m_client_object_t *)lwm2m_malloc(sizeof(lwm2m_client_object_t));
terencez 0:1fa43ab66921 822 memset(objectP, 0, sizeof(lwm2m_client_object_t));
terencez 0:1fa43ab66921 823 if (objectP == NULL) goto error;
terencez 0:1fa43ab66921 824 objectP->id = id;
terencez 0:1fa43ab66921 825 objList = (lwm2m_client_object_t *)LWM2M_LIST_ADD(objList, objectP);
terencez 0:1fa43ab66921 826 }
terencez 0:1fa43ab66921 827 if (result == 2)
terencez 0:1fa43ab66921 828 {
terencez 0:1fa43ab66921 829 lwm2m_list_t * instanceP;
terencez 0:1fa43ab66921 830
terencez 0:1fa43ab66921 831 instanceP = lwm2m_list_find(objectP->instanceList, instance);
terencez 0:1fa43ab66921 832 if (instanceP == NULL)
terencez 0:1fa43ab66921 833 {
terencez 0:1fa43ab66921 834 instanceP = (lwm2m_list_t *)lwm2m_malloc(sizeof(lwm2m_list_t));
terencez 0:1fa43ab66921 835 memset(instanceP, 0, sizeof(lwm2m_list_t));
terencez 0:1fa43ab66921 836 instanceP->id = instance;
terencez 0:1fa43ab66921 837 objectP->instanceList = LWM2M_LIST_ADD(objectP->instanceList, instanceP);
terencez 0:1fa43ab66921 838 }
terencez 0:1fa43ab66921 839 }
terencez 0:1fa43ab66921 840 }
terencez 0:1fa43ab66921 841 else if (linkAttrFound == false)
terencez 0:1fa43ab66921 842 {
terencez 0:1fa43ab66921 843 result = prv_parseLinkAttributes(payload + start, length, supportJSON, altPath);
terencez 0:1fa43ab66921 844 if (result == 0) goto error;
terencez 0:1fa43ab66921 845
terencez 0:1fa43ab66921 846 linkAttrFound = true;
terencez 0:1fa43ab66921 847 }
terencez 0:1fa43ab66921 848 else goto error;
terencez 0:1fa43ab66921 849
terencez 0:1fa43ab66921 850 index++;
terencez 0:1fa43ab66921 851 }
terencez 0:1fa43ab66921 852
terencez 0:1fa43ab66921 853 return objList;
terencez 0:1fa43ab66921 854
terencez 0:1fa43ab66921 855 error:
terencez 0:1fa43ab66921 856 if (*altPath != NULL)
terencez 0:1fa43ab66921 857 {
terencez 0:1fa43ab66921 858 lwm2m_free(*altPath);
terencez 0:1fa43ab66921 859 *altPath = NULL;
terencez 0:1fa43ab66921 860 }
terencez 0:1fa43ab66921 861 prv_freeClientObjectList(objList);
terencez 0:1fa43ab66921 862
terencez 0:1fa43ab66921 863 return NULL;
terencez 0:1fa43ab66921 864 }
terencez 0:1fa43ab66921 865
terencez 0:1fa43ab66921 866 static lwm2m_client_t * prv_getClientByName(lwm2m_context_t * contextP,
terencez 0:1fa43ab66921 867 char * name)
terencez 0:1fa43ab66921 868 {
terencez 0:1fa43ab66921 869 lwm2m_client_t * targetP;
terencez 0:1fa43ab66921 870
terencez 0:1fa43ab66921 871 targetP = contextP->clientList;
terencez 0:1fa43ab66921 872 while (targetP != NULL && strcmp(name, targetP->name) != 0)
terencez 0:1fa43ab66921 873 {
terencez 0:1fa43ab66921 874 targetP = targetP->next;
terencez 0:1fa43ab66921 875 }
terencez 0:1fa43ab66921 876
terencez 0:1fa43ab66921 877 return targetP;
terencez 0:1fa43ab66921 878 }
terencez 0:1fa43ab66921 879
terencez 0:1fa43ab66921 880 void registration_freeClient(lwm2m_client_t * clientP)
terencez 0:1fa43ab66921 881 {
terencez 0:1fa43ab66921 882 LOG("Entering");
terencez 0:1fa43ab66921 883 if (clientP->name != NULL) lwm2m_free(clientP->name);
terencez 0:1fa43ab66921 884 if (clientP->msisdn != NULL) lwm2m_free(clientP->msisdn);
terencez 0:1fa43ab66921 885 if (clientP->altPath != NULL) lwm2m_free(clientP->altPath);
terencez 0:1fa43ab66921 886 prv_freeClientObjectList(clientP->objectList);
terencez 0:1fa43ab66921 887 while(clientP->observationList != NULL)
terencez 0:1fa43ab66921 888 {
terencez 0:1fa43ab66921 889 lwm2m_observation_t * targetP;
terencez 0:1fa43ab66921 890
terencez 0:1fa43ab66921 891 targetP = clientP->observationList;
terencez 0:1fa43ab66921 892 clientP->observationList = clientP->observationList->next;
terencez 0:1fa43ab66921 893 lwm2m_free(targetP);
terencez 0:1fa43ab66921 894 }
terencez 0:1fa43ab66921 895 lwm2m_free(clientP);
terencez 0:1fa43ab66921 896 }
terencez 0:1fa43ab66921 897
terencez 0:1fa43ab66921 898 static int prv_getLocationString(uint16_t id,
terencez 0:1fa43ab66921 899 char location[MAX_LOCATION_LENGTH])
terencez 0:1fa43ab66921 900 {
terencez 0:1fa43ab66921 901 int index;
terencez 0:1fa43ab66921 902 int result;
terencez 0:1fa43ab66921 903
terencez 0:1fa43ab66921 904 memset(location, 0, MAX_LOCATION_LENGTH);
terencez 0:1fa43ab66921 905
terencez 0:1fa43ab66921 906 result = utils_stringCopy(location, MAX_LOCATION_LENGTH, "/"URI_REGISTRATION_SEGMENT"/");
terencez 0:1fa43ab66921 907 if (result < 0) return 0;
terencez 0:1fa43ab66921 908 index = result;
terencez 0:1fa43ab66921 909
terencez 0:1fa43ab66921 910 result = utils_intCopy(location + index, MAX_LOCATION_LENGTH - index, id);
terencez 0:1fa43ab66921 911 if (result < 0) return 0;
terencez 0:1fa43ab66921 912
terencez 0:1fa43ab66921 913 return index + result;
terencez 0:1fa43ab66921 914 }
terencez 0:1fa43ab66921 915
terencez 0:1fa43ab66921 916 coap_status_t registration_handleRequest(lwm2m_context_t * contextP,
terencez 0:1fa43ab66921 917 lwm2m_uri_t * uriP,
terencez 0:1fa43ab66921 918 void * fromSessionH,
terencez 0:1fa43ab66921 919 coap_packet_t * message,
terencez 0:1fa43ab66921 920 coap_packet_t * response)
terencez 0:1fa43ab66921 921 {
terencez 0:1fa43ab66921 922 coap_status_t result;
terencez 0:1fa43ab66921 923 time_t tv_sec;
terencez 0:1fa43ab66921 924
terencez 0:1fa43ab66921 925 LOG_URI(uriP);
terencez 0:1fa43ab66921 926 tv_sec = lwm2m_gettime();
terencez 0:1fa43ab66921 927 if (tv_sec < 0) return COAP_500_INTERNAL_SERVER_ERROR;
terencez 0:1fa43ab66921 928
terencez 0:1fa43ab66921 929 switch(message->code)
terencez 0:1fa43ab66921 930 {
terencez 0:1fa43ab66921 931 case COAP_POST:
terencez 0:1fa43ab66921 932 {
terencez 0:1fa43ab66921 933 char * name = NULL;
terencez 0:1fa43ab66921 934 uint32_t lifetime;
terencez 0:1fa43ab66921 935 char * msisdn;
terencez 0:1fa43ab66921 936 char * altPath;
terencez 0:1fa43ab66921 937 char * version;
terencez 0:1fa43ab66921 938 lwm2m_binding_t binding;
terencez 0:1fa43ab66921 939 lwm2m_client_object_t * objects;
terencez 0:1fa43ab66921 940 bool supportJSON;
terencez 0:1fa43ab66921 941 lwm2m_client_t * clientP;
terencez 0:1fa43ab66921 942 char location[MAX_LOCATION_LENGTH];
terencez 0:1fa43ab66921 943
terencez 0:1fa43ab66921 944 if (0 != prv_getParameters(message->uri_query, &name, &lifetime, &msisdn, &binding, &version))
terencez 0:1fa43ab66921 945 {
terencez 0:1fa43ab66921 946 return COAP_400_BAD_REQUEST;
terencez 0:1fa43ab66921 947 }
terencez 0:1fa43ab66921 948 if (message->content_type != LWM2M_CONTENT_LINK
terencez 0:1fa43ab66921 949 && message->content_type != LWM2M_CONTENT_TEXT)
terencez 0:1fa43ab66921 950 {
terencez 0:1fa43ab66921 951 return COAP_400_BAD_REQUEST;
terencez 0:1fa43ab66921 952 }
terencez 0:1fa43ab66921 953
terencez 0:1fa43ab66921 954 objects = prv_decodeRegisterPayload(message->payload, message->payload_len, &supportJSON, &altPath);
terencez 0:1fa43ab66921 955
terencez 0:1fa43ab66921 956 switch (uriP->flag & LWM2M_URI_MASK_ID)
terencez 0:1fa43ab66921 957 {
terencez 0:1fa43ab66921 958 case 0:
terencez 0:1fa43ab66921 959 // Register operation
terencez 0:1fa43ab66921 960 // Version is mandatory
terencez 0:1fa43ab66921 961 if (version == NULL)
terencez 0:1fa43ab66921 962 {
terencez 0:1fa43ab66921 963 if (name != NULL) lwm2m_free(name);
terencez 0:1fa43ab66921 964 if (msisdn != NULL) lwm2m_free(msisdn);
terencez 0:1fa43ab66921 965 return COAP_400_BAD_REQUEST;
terencez 0:1fa43ab66921 966 }
terencez 0:1fa43ab66921 967 // Endpoint client name is mandatory
terencez 0:1fa43ab66921 968 if (name == NULL)
terencez 0:1fa43ab66921 969 {
terencez 0:1fa43ab66921 970 lwm2m_free(version);
terencez 0:1fa43ab66921 971 if (msisdn != NULL) lwm2m_free(msisdn);
terencez 0:1fa43ab66921 972 return COAP_400_BAD_REQUEST;
terencez 0:1fa43ab66921 973 }
terencez 0:1fa43ab66921 974 // Object list is mandatory
terencez 0:1fa43ab66921 975 if (objects == NULL)
terencez 0:1fa43ab66921 976 {
terencez 0:1fa43ab66921 977 lwm2m_free(version);
terencez 0:1fa43ab66921 978 lwm2m_free(name);
terencez 0:1fa43ab66921 979 if (msisdn != NULL) lwm2m_free(msisdn);
terencez 0:1fa43ab66921 980 return COAP_400_BAD_REQUEST;
terencez 0:1fa43ab66921 981 }
terencez 0:1fa43ab66921 982 // version must be 1.0
terencez 0:1fa43ab66921 983 if (strlen(version) != LWM2M_VERSION_LEN
terencez 0:1fa43ab66921 984 || lwm2m_strncmp(version, LWM2M_VERSION, LWM2M_VERSION_LEN))
terencez 0:1fa43ab66921 985 {
terencez 0:1fa43ab66921 986 lwm2m_free(version);
terencez 0:1fa43ab66921 987 lwm2m_free(name);
terencez 0:1fa43ab66921 988 if (msisdn != NULL) lwm2m_free(msisdn);
terencez 0:1fa43ab66921 989 return COAP_412_PRECONDITION_FAILED;
terencez 0:1fa43ab66921 990 }
terencez 0:1fa43ab66921 991
terencez 0:1fa43ab66921 992 if (lifetime == 0)
terencez 0:1fa43ab66921 993 {
terencez 0:1fa43ab66921 994 lifetime = LWM2M_DEFAULT_LIFETIME;
terencez 0:1fa43ab66921 995 }
terencez 0:1fa43ab66921 996
terencez 0:1fa43ab66921 997 clientP = prv_getClientByName(contextP, name);
terencez 0:1fa43ab66921 998 if (clientP != NULL)
terencez 0:1fa43ab66921 999 {
terencez 0:1fa43ab66921 1000 // we reset this registration
terencez 0:1fa43ab66921 1001 lwm2m_free(clientP->name);
terencez 0:1fa43ab66921 1002 if (clientP->msisdn != NULL) lwm2m_free(clientP->msisdn);
terencez 0:1fa43ab66921 1003 if (clientP->altPath != NULL) lwm2m_free(clientP->altPath);
terencez 0:1fa43ab66921 1004 prv_freeClientObjectList(clientP->objectList);
terencez 0:1fa43ab66921 1005 clientP->objectList = NULL;
terencez 0:1fa43ab66921 1006 }
terencez 0:1fa43ab66921 1007 else
terencez 0:1fa43ab66921 1008 {
terencez 0:1fa43ab66921 1009 clientP = (lwm2m_client_t *)lwm2m_malloc(sizeof(lwm2m_client_t));
terencez 0:1fa43ab66921 1010 if (clientP == NULL)
terencez 0:1fa43ab66921 1011 {
terencez 0:1fa43ab66921 1012 lwm2m_free(name);
terencez 0:1fa43ab66921 1013 lwm2m_free(altPath);
terencez 0:1fa43ab66921 1014 if (msisdn != NULL) lwm2m_free(msisdn);
terencez 0:1fa43ab66921 1015 prv_freeClientObjectList(objects);
terencez 0:1fa43ab66921 1016 return COAP_500_INTERNAL_SERVER_ERROR;
terencez 0:1fa43ab66921 1017 }
terencez 0:1fa43ab66921 1018 memset(clientP, 0, sizeof(lwm2m_client_t));
terencez 0:1fa43ab66921 1019 clientP->internalID = lwm2m_list_newId((lwm2m_list_t *)contextP->clientList);
terencez 0:1fa43ab66921 1020 contextP->clientList = (lwm2m_client_t *)LWM2M_LIST_ADD(contextP->clientList, clientP);
terencez 0:1fa43ab66921 1021 }
terencez 0:1fa43ab66921 1022 clientP->name = name;
terencez 0:1fa43ab66921 1023 clientP->binding = binding;
terencez 0:1fa43ab66921 1024 clientP->msisdn = msisdn;
terencez 0:1fa43ab66921 1025 clientP->altPath = altPath;
terencez 0:1fa43ab66921 1026 clientP->supportJSON = supportJSON;
terencez 0:1fa43ab66921 1027 clientP->lifetime = lifetime;
terencez 0:1fa43ab66921 1028 clientP->endOfLife = tv_sec + lifetime;
terencez 0:1fa43ab66921 1029 clientP->objectList = objects;
terencez 0:1fa43ab66921 1030 clientP->sessionH = fromSessionH;
terencez 0:1fa43ab66921 1031
terencez 0:1fa43ab66921 1032 if (prv_getLocationString(clientP->internalID, location) == 0)
terencez 0:1fa43ab66921 1033 {
terencez 0:1fa43ab66921 1034 registration_freeClient(clientP);
terencez 0:1fa43ab66921 1035 return COAP_500_INTERNAL_SERVER_ERROR;
terencez 0:1fa43ab66921 1036 }
terencez 0:1fa43ab66921 1037 if (coap_set_header_location_path(response, location) == 0)
terencez 0:1fa43ab66921 1038 {
terencez 0:1fa43ab66921 1039 registration_freeClient(clientP);
terencez 0:1fa43ab66921 1040 return COAP_500_INTERNAL_SERVER_ERROR;
terencez 0:1fa43ab66921 1041 }
terencez 0:1fa43ab66921 1042
terencez 0:1fa43ab66921 1043 if (contextP->monitorCallback != NULL)
terencez 0:1fa43ab66921 1044 {
terencez 0:1fa43ab66921 1045 contextP->monitorCallback(clientP->internalID, NULL, COAP_201_CREATED, LWM2M_CONTENT_TEXT, NULL, 0, contextP->monitorUserData);
terencez 0:1fa43ab66921 1046 }
terencez 0:1fa43ab66921 1047 result = COAP_201_CREATED;
terencez 0:1fa43ab66921 1048 break;
terencez 0:1fa43ab66921 1049
terencez 0:1fa43ab66921 1050 case LWM2M_URI_FLAG_OBJECT_ID:
terencez 0:1fa43ab66921 1051 clientP = (lwm2m_client_t *)lwm2m_list_find((lwm2m_list_t *)contextP->clientList, uriP->objectId);
terencez 0:1fa43ab66921 1052 if (clientP == NULL) return COAP_404_NOT_FOUND;
terencez 0:1fa43ab66921 1053
terencez 0:1fa43ab66921 1054 // Endpoint client name MUST NOT be present
terencez 0:1fa43ab66921 1055 if (name != NULL)
terencez 0:1fa43ab66921 1056 {
terencez 0:1fa43ab66921 1057 lwm2m_free(name);
terencez 0:1fa43ab66921 1058 if (msisdn != NULL) lwm2m_free(msisdn);
terencez 0:1fa43ab66921 1059 return COAP_400_BAD_REQUEST;
terencez 0:1fa43ab66921 1060 }
terencez 0:1fa43ab66921 1061
terencez 0:1fa43ab66921 1062 if (binding != BINDING_UNKNOWN)
terencez 0:1fa43ab66921 1063 {
terencez 0:1fa43ab66921 1064 clientP->binding = binding;
terencez 0:1fa43ab66921 1065 }
terencez 0:1fa43ab66921 1066 if (msisdn != NULL)
terencez 0:1fa43ab66921 1067 {
terencez 0:1fa43ab66921 1068 if (clientP->msisdn != NULL) lwm2m_free(clientP->msisdn);
terencez 0:1fa43ab66921 1069 clientP->msisdn = msisdn;
terencez 0:1fa43ab66921 1070 }
terencez 0:1fa43ab66921 1071 if (lifetime != 0)
terencez 0:1fa43ab66921 1072 {
terencez 0:1fa43ab66921 1073 clientP->lifetime = lifetime;
terencez 0:1fa43ab66921 1074 }
terencez 0:1fa43ab66921 1075 // client IP address, port or MSISDN may have changed
terencez 0:1fa43ab66921 1076 clientP->sessionH = fromSessionH;
terencez 0:1fa43ab66921 1077
terencez 0:1fa43ab66921 1078 if (objects != NULL)
terencez 0:1fa43ab66921 1079 {
terencez 0:1fa43ab66921 1080 lwm2m_observation_t * observationP;
terencez 0:1fa43ab66921 1081
terencez 0:1fa43ab66921 1082 // remove observations on object/instance no longer existing
terencez 0:1fa43ab66921 1083 observationP = clientP->observationList;
terencez 0:1fa43ab66921 1084 while (observationP != NULL)
terencez 0:1fa43ab66921 1085 {
terencez 0:1fa43ab66921 1086 lwm2m_client_object_t * objP;
terencez 0:1fa43ab66921 1087 lwm2m_observation_t * nextP;
terencez 0:1fa43ab66921 1088
terencez 0:1fa43ab66921 1089 nextP = observationP->next;
terencez 0:1fa43ab66921 1090
terencez 0:1fa43ab66921 1091 objP = (lwm2m_client_object_t *)lwm2m_list_find((lwm2m_list_t *)objects, observationP->uri.objectId);
terencez 0:1fa43ab66921 1092 if (objP == NULL)
terencez 0:1fa43ab66921 1093 {
terencez 0:1fa43ab66921 1094 observationP->callback(clientP->internalID,
terencez 0:1fa43ab66921 1095 &observationP->uri,
terencez 0:1fa43ab66921 1096 COAP_202_DELETED,
terencez 0:1fa43ab66921 1097 LWM2M_CONTENT_TEXT, NULL, 0,
terencez 0:1fa43ab66921 1098 observationP->userData);
terencez 0:1fa43ab66921 1099 observe_remove(observationP);
terencez 0:1fa43ab66921 1100 }
terencez 0:1fa43ab66921 1101 else
terencez 0:1fa43ab66921 1102 {
terencez 0:1fa43ab66921 1103 if ((observationP->uri.flag & LWM2M_URI_FLAG_INSTANCE_ID) != 0)
terencez 0:1fa43ab66921 1104 {
terencez 0:1fa43ab66921 1105 if (lwm2m_list_find((lwm2m_list_t *)objP->instanceList, observationP->uri.instanceId) == NULL)
terencez 0:1fa43ab66921 1106 {
terencez 0:1fa43ab66921 1107 observationP->callback(clientP->internalID,
terencez 0:1fa43ab66921 1108 &observationP->uri,
terencez 0:1fa43ab66921 1109 COAP_202_DELETED,
terencez 0:1fa43ab66921 1110 LWM2M_CONTENT_TEXT, NULL, 0,
terencez 0:1fa43ab66921 1111 observationP->userData);
terencez 0:1fa43ab66921 1112 observe_remove(observationP);
terencez 0:1fa43ab66921 1113 }
terencez 0:1fa43ab66921 1114 }
terencez 0:1fa43ab66921 1115 }
terencez 0:1fa43ab66921 1116
terencez 0:1fa43ab66921 1117 observationP = nextP;
terencez 0:1fa43ab66921 1118 }
terencez 0:1fa43ab66921 1119
terencez 0:1fa43ab66921 1120 prv_freeClientObjectList(clientP->objectList);
terencez 0:1fa43ab66921 1121 clientP->objectList = objects;
terencez 0:1fa43ab66921 1122 }
terencez 0:1fa43ab66921 1123
terencez 0:1fa43ab66921 1124 clientP->endOfLife = tv_sec + clientP->lifetime;
terencez 0:1fa43ab66921 1125
terencez 0:1fa43ab66921 1126 if (contextP->monitorCallback != NULL)
terencez 0:1fa43ab66921 1127 {
terencez 0:1fa43ab66921 1128 contextP->monitorCallback(clientP->internalID, NULL, COAP_204_CHANGED, LWM2M_CONTENT_TEXT, NULL, 0, contextP->monitorUserData);
terencez 0:1fa43ab66921 1129 }
terencez 0:1fa43ab66921 1130 result = COAP_204_CHANGED;
terencez 0:1fa43ab66921 1131 break;
terencez 0:1fa43ab66921 1132
terencez 0:1fa43ab66921 1133 default:
terencez 0:1fa43ab66921 1134 return COAP_400_BAD_REQUEST;
terencez 0:1fa43ab66921 1135 }
terencez 0:1fa43ab66921 1136 }
terencez 0:1fa43ab66921 1137 break;
terencez 0:1fa43ab66921 1138
terencez 0:1fa43ab66921 1139 case COAP_DELETE:
terencez 0:1fa43ab66921 1140 {
terencez 0:1fa43ab66921 1141 lwm2m_client_t * clientP;
terencez 0:1fa43ab66921 1142
terencez 0:1fa43ab66921 1143 if ((uriP->flag & LWM2M_URI_MASK_ID) != LWM2M_URI_FLAG_OBJECT_ID) return COAP_400_BAD_REQUEST;
terencez 0:1fa43ab66921 1144
terencez 0:1fa43ab66921 1145 contextP->clientList = (lwm2m_client_t *)LWM2M_LIST_RM(contextP->clientList, uriP->objectId, &clientP);
terencez 0:1fa43ab66921 1146 if (clientP == NULL) return COAP_400_BAD_REQUEST;
terencez 0:1fa43ab66921 1147 if (contextP->monitorCallback != NULL)
terencez 0:1fa43ab66921 1148 {
terencez 0:1fa43ab66921 1149 contextP->monitorCallback(clientP->internalID, NULL, COAP_202_DELETED, LWM2M_CONTENT_TEXT, NULL, 0, contextP->monitorUserData);
terencez 0:1fa43ab66921 1150 }
terencez 0:1fa43ab66921 1151 registration_freeClient(clientP);
terencez 0:1fa43ab66921 1152 result = COAP_202_DELETED;
terencez 0:1fa43ab66921 1153 }
terencez 0:1fa43ab66921 1154 break;
terencez 0:1fa43ab66921 1155
terencez 0:1fa43ab66921 1156 default:
terencez 0:1fa43ab66921 1157 return COAP_400_BAD_REQUEST;
terencez 0:1fa43ab66921 1158 }
terencez 0:1fa43ab66921 1159
terencez 0:1fa43ab66921 1160 return result;
terencez 0:1fa43ab66921 1161 }
terencez 0:1fa43ab66921 1162
terencez 0:1fa43ab66921 1163 void lwm2m_set_monitoring_callback(lwm2m_context_t * contextP,
terencez 0:1fa43ab66921 1164 lwm2m_result_callback_t callback,
terencez 0:1fa43ab66921 1165 void * userData)
terencez 0:1fa43ab66921 1166 {
terencez 0:1fa43ab66921 1167 LOG("Entering");
terencez 0:1fa43ab66921 1168 contextP->monitorCallback = callback;
terencez 0:1fa43ab66921 1169 contextP->monitorUserData = userData;
terencez 0:1fa43ab66921 1170 }
terencez 0:1fa43ab66921 1171 #endif
terencez 0:1fa43ab66921 1172
terencez 0:1fa43ab66921 1173 // for each server update the registration if needed
terencez 0:1fa43ab66921 1174 // for each client check if the registration expired
terencez 0:1fa43ab66921 1175 void registration_step(lwm2m_context_t * contextP,
terencez 0:1fa43ab66921 1176 time_t currentTime,
terencez 0:1fa43ab66921 1177 time_t * timeoutP)
terencez 0:1fa43ab66921 1178 {
terencez 0:1fa43ab66921 1179 #ifdef LWM2M_CLIENT_MODE
terencez 0:1fa43ab66921 1180 lwm2m_server_t * targetP = contextP->serverList;
terencez 0:1fa43ab66921 1181
terencez 0:1fa43ab66921 1182 LOG_ARG("State: %s", STR_STATE(contextP->state));
terencez 0:1fa43ab66921 1183
terencez 0:1fa43ab66921 1184 targetP = contextP->serverList;
terencez 0:1fa43ab66921 1185 while (targetP != NULL)
terencez 0:1fa43ab66921 1186 {
terencez 0:1fa43ab66921 1187 switch (targetP->status)
terencez 0:1fa43ab66921 1188 {
terencez 0:1fa43ab66921 1189 case STATE_REGISTERED:
terencez 0:1fa43ab66921 1190 {
terencez 0:1fa43ab66921 1191 time_t nextUpdate;
terencez 0:1fa43ab66921 1192 time_t interval;
terencez 0:1fa43ab66921 1193
terencez 0:1fa43ab66921 1194 nextUpdate = targetP->lifetime;
terencez 0:1fa43ab66921 1195 if (COAP_MAX_TRANSMIT_WAIT < nextUpdate)
terencez 0:1fa43ab66921 1196 {
terencez 0:1fa43ab66921 1197 nextUpdate -= COAP_MAX_TRANSMIT_WAIT;
terencez 0:1fa43ab66921 1198 }
terencez 0:1fa43ab66921 1199 else
terencez 0:1fa43ab66921 1200 {
terencez 0:1fa43ab66921 1201 nextUpdate = nextUpdate >> 1;
terencez 0:1fa43ab66921 1202 }
terencez 0:1fa43ab66921 1203
terencez 0:1fa43ab66921 1204 interval = targetP->registration + nextUpdate - currentTime;
terencez 0:1fa43ab66921 1205 if (0 >= interval)
terencez 0:1fa43ab66921 1206 {
terencez 0:1fa43ab66921 1207 LOG("Updating registration");
terencez 0:1fa43ab66921 1208 prv_updateRegistration(contextP, targetP, false);
terencez 0:1fa43ab66921 1209 }
terencez 0:1fa43ab66921 1210 else if (interval < *timeoutP)
terencez 0:1fa43ab66921 1211 {
terencez 0:1fa43ab66921 1212 *timeoutP = interval;
terencez 0:1fa43ab66921 1213 }
terencez 0:1fa43ab66921 1214 }
terencez 0:1fa43ab66921 1215 break;
terencez 0:1fa43ab66921 1216
terencez 0:1fa43ab66921 1217 case STATE_REG_UPDATE_NEEDED:
terencez 0:1fa43ab66921 1218 prv_updateRegistration(contextP, targetP, false);
terencez 0:1fa43ab66921 1219 break;
terencez 0:1fa43ab66921 1220
terencez 0:1fa43ab66921 1221 case STATE_REG_FULL_UPDATE_NEEDED:
terencez 0:1fa43ab66921 1222 prv_updateRegistration(contextP, targetP, true);
terencez 0:1fa43ab66921 1223 break;
terencez 0:1fa43ab66921 1224
terencez 0:1fa43ab66921 1225 case STATE_REG_FAILED:
terencez 0:1fa43ab66921 1226 if (targetP->sessionH != NULL)
terencez 0:1fa43ab66921 1227 {
terencez 0:1fa43ab66921 1228 lwm2m_close_connection(targetP->sessionH, contextP->userData);
terencez 0:1fa43ab66921 1229 targetP->sessionH = NULL;
terencez 0:1fa43ab66921 1230 }
terencez 0:1fa43ab66921 1231 break;
terencez 0:1fa43ab66921 1232
terencez 0:1fa43ab66921 1233 default:
terencez 0:1fa43ab66921 1234 break;
terencez 0:1fa43ab66921 1235 }
terencez 0:1fa43ab66921 1236 targetP = targetP->next;
terencez 0:1fa43ab66921 1237 }
terencez 0:1fa43ab66921 1238
terencez 0:1fa43ab66921 1239 #endif
terencez 0:1fa43ab66921 1240 #ifdef LWM2M_SERVER_MODE
terencez 0:1fa43ab66921 1241 lwm2m_client_t * clientP;
terencez 0:1fa43ab66921 1242
terencez 0:1fa43ab66921 1243 LOG("Entering");
terencez 0:1fa43ab66921 1244 // monitor clients lifetime
terencez 0:1fa43ab66921 1245 clientP = contextP->clientList;
terencez 0:1fa43ab66921 1246 while (clientP != NULL)
terencez 0:1fa43ab66921 1247 {
terencez 0:1fa43ab66921 1248 lwm2m_client_t * nextP = clientP->next;
terencez 0:1fa43ab66921 1249
terencez 0:1fa43ab66921 1250 if (clientP->endOfLife <= currentTime)
terencez 0:1fa43ab66921 1251 {
terencez 0:1fa43ab66921 1252 contextP->clientList = (lwm2m_client_t *)LWM2M_LIST_RM(contextP->clientList, clientP->internalID, NULL);
terencez 0:1fa43ab66921 1253 if (contextP->monitorCallback != NULL)
terencez 0:1fa43ab66921 1254 {
terencez 0:1fa43ab66921 1255 contextP->monitorCallback(clientP->internalID, NULL, COAP_202_DELETED, LWM2M_CONTENT_TEXT, NULL, 0, contextP->monitorUserData);
terencez 0:1fa43ab66921 1256 }
terencez 0:1fa43ab66921 1257 registration_freeClient(clientP);
terencez 0:1fa43ab66921 1258 }
terencez 0:1fa43ab66921 1259 else
terencez 0:1fa43ab66921 1260 {
terencez 0:1fa43ab66921 1261 time_t interval;
terencez 0:1fa43ab66921 1262
terencez 0:1fa43ab66921 1263 interval = clientP->endOfLife - currentTime;
terencez 0:1fa43ab66921 1264
terencez 0:1fa43ab66921 1265 if (*timeoutP > interval)
terencez 0:1fa43ab66921 1266 {
terencez 0:1fa43ab66921 1267 *timeoutP = interval;
terencez 0:1fa43ab66921 1268 }
terencez 0:1fa43ab66921 1269 }
terencez 0:1fa43ab66921 1270 clientP = nextP;
terencez 0:1fa43ab66921 1271 }
terencez 0:1fa43ab66921 1272 #endif
terencez 0:1fa43ab66921 1273
terencez 0:1fa43ab66921 1274 }
terencez 0:1fa43ab66921 1275