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 * Simon Bernard - Please refer to git log
terencez 0:1fa43ab66921 16 * Toby Jaffey - Please refer to git log
terencez 0:1fa43ab66921 17 * Pascal Rieux - Please refer to git log
terencez 0:1fa43ab66921 18 * Bosch Software Innovations GmbH - Please refer to git log
terencez 0:1fa43ab66921 19 *
terencez 0:1fa43ab66921 20 *******************************************************************************/
terencez 0:1fa43ab66921 21
terencez 0:1fa43ab66921 22 /*
terencez 0:1fa43ab66921 23 Copyright (c) 2013, 2014 Intel Corporation
terencez 0:1fa43ab66921 24
terencez 0:1fa43ab66921 25 Redistribution and use in source and binary forms, with or without modification,
terencez 0:1fa43ab66921 26 are permitted provided that the following conditions are met:
terencez 0:1fa43ab66921 27
terencez 0:1fa43ab66921 28 * Redistributions of source code must retain the above copyright notice,
terencez 0:1fa43ab66921 29 this list of conditions and the following disclaimer.
terencez 0:1fa43ab66921 30 * Redistributions in binary form must reproduce the above copyright notice,
terencez 0:1fa43ab66921 31 this list of conditions and the following disclaimer in the documentation
terencez 0:1fa43ab66921 32 and/or other materials provided with the distribution.
terencez 0:1fa43ab66921 33 * Neither the name of Intel Corporation nor the names of its contributors
terencez 0:1fa43ab66921 34 may be used to endorse or promote products derived from this software
terencez 0:1fa43ab66921 35 without specific prior written permission.
terencez 0:1fa43ab66921 36
terencez 0:1fa43ab66921 37 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
terencez 0:1fa43ab66921 38 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
terencez 0:1fa43ab66921 39 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
terencez 0:1fa43ab66921 40 IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
terencez 0:1fa43ab66921 41 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
terencez 0:1fa43ab66921 42 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
terencez 0:1fa43ab66921 43 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
terencez 0:1fa43ab66921 44 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
terencez 0:1fa43ab66921 45 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
terencez 0:1fa43ab66921 46 THE POSSIBILITY OF SUCH DAMAGE.
terencez 0:1fa43ab66921 47
terencez 0:1fa43ab66921 48 David Navarro <david.navarro@intel.com>
terencez 0:1fa43ab66921 49
terencez 0:1fa43ab66921 50 */
terencez 0:1fa43ab66921 51
terencez 0:1fa43ab66921 52 /*
terencez 0:1fa43ab66921 53 Contains code snippets which are:
terencez 0:1fa43ab66921 54
terencez 0:1fa43ab66921 55 * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich
terencez 0:1fa43ab66921 56 * All rights reserved.
terencez 0:1fa43ab66921 57 *
terencez 0:1fa43ab66921 58 * Redistribution and use in source and binary forms, with or without
terencez 0:1fa43ab66921 59 * modification, are permitted provided that the following conditions
terencez 0:1fa43ab66921 60 * are met:
terencez 0:1fa43ab66921 61 * 1. Redistributions of source code must retain the above copyright
terencez 0:1fa43ab66921 62 * notice, this list of conditions and the following disclaimer.
terencez 0:1fa43ab66921 63 * 2. Redistributions in binary form must reproduce the above copyright
terencez 0:1fa43ab66921 64 * notice, this list of conditions and the following disclaimer in the
terencez 0:1fa43ab66921 65 * documentation and/or other materials provided with the distribution.
terencez 0:1fa43ab66921 66 * 3. Neither the name of the Institute nor the names of its contributors
terencez 0:1fa43ab66921 67 * may be used to endorse or promote products derived from this software
terencez 0:1fa43ab66921 68 * without specific prior written permission.
terencez 0:1fa43ab66921 69 *
terencez 0:1fa43ab66921 70 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
terencez 0:1fa43ab66921 71 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
terencez 0:1fa43ab66921 72 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
terencez 0:1fa43ab66921 73 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
terencez 0:1fa43ab66921 74 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
terencez 0:1fa43ab66921 75 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
terencez 0:1fa43ab66921 76 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
terencez 0:1fa43ab66921 77 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
terencez 0:1fa43ab66921 78 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
terencez 0:1fa43ab66921 79 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
terencez 0:1fa43ab66921 80 * SUCH DAMAGE.
terencez 0:1fa43ab66921 81
terencez 0:1fa43ab66921 82 */
terencez 0:1fa43ab66921 83
terencez 0:1fa43ab66921 84 /************************************************************************
terencez 0:1fa43ab66921 85 * Function for communications transactions.
terencez 0:1fa43ab66921 86 *
terencez 0:1fa43ab66921 87 * Basic specification: rfc7252
terencez 0:1fa43ab66921 88 *
terencez 0:1fa43ab66921 89 * Transaction implements processing of piggybacked and separate response communication
terencez 0:1fa43ab66921 90 * dialogs specified in section 2.2 of the above specification.
terencez 0:1fa43ab66921 91 * The caller registers a callback function, which is called, when either the result is
terencez 0:1fa43ab66921 92 * received or a timeout occurs.
terencez 0:1fa43ab66921 93 *
terencez 0:1fa43ab66921 94 * Supported dialogs:
terencez 0:1fa43ab66921 95 * Requests (GET - DELETE):
terencez 0:1fa43ab66921 96 * - CON with mid, without token => regular finished with corresponding ACK.MID
terencez 0:1fa43ab66921 97 * - CON with mid, with token => regular finished with corresponding ACK.MID and response containing
terencez 0:1fa43ab66921 98 * the token. Supports both versions, with piggybacked ACK and separate ACK/response.
terencez 0:1fa43ab66921 99 * Though the ACK.MID may be lost in the separate version, a matching response may
terencez 0:1fa43ab66921 100 * finish the transaction even without the ACK.MID.
terencez 0:1fa43ab66921 101 * - NON without token => no transaction, no result expected!
terencez 0:1fa43ab66921 102 * - NON with token => regular finished with response containing the token.
terencez 0:1fa43ab66921 103 * Responses (COAP_201_CREATED - ?):
terencez 0:1fa43ab66921 104 * - CON with mid => regular finished with corresponding ACK.MID
terencez 0:1fa43ab66921 105 */
terencez 0:1fa43ab66921 106
terencez 0:1fa43ab66921 107 #include "internals.h"
terencez 0:1fa43ab66921 108
terencez 0:1fa43ab66921 109
terencez 0:1fa43ab66921 110 /*
terencez 0:1fa43ab66921 111 * Modulo mask (+1 and +0.5 for rounding) for a random number to get the tick number for the random
terencez 0:1fa43ab66921 112 * retransmission time between COAP_RESPONSE_TIMEOUT and COAP_RESPONSE_TIMEOUT*COAP_RESPONSE_RANDOM_FACTOR.
terencez 0:1fa43ab66921 113 */
terencez 0:1fa43ab66921 114 #define COAP_RESPONSE_TIMEOUT_TICKS (CLOCK_SECOND * COAP_RESPONSE_TIMEOUT)
terencez 0:1fa43ab66921 115 #define COAP_RESPONSE_TIMEOUT_BACKOFF_MASK ((CLOCK_SECOND * COAP_RESPONSE_TIMEOUT * (COAP_RESPONSE_RANDOM_FACTOR - 1)) + 1.5)
terencez 0:1fa43ab66921 116
terencez 0:1fa43ab66921 117 static int prv_checkFinished(lwm2m_transaction_t * transacP,
terencez 0:1fa43ab66921 118 coap_packet_t * receivedMessage)
terencez 0:1fa43ab66921 119 {
terencez 0:1fa43ab66921 120 int len;
terencez 0:1fa43ab66921 121 const uint8_t* token;
terencez 0:1fa43ab66921 122 coap_packet_t * transactionMessage = transacP->message;
terencez 0:1fa43ab66921 123
terencez 0:1fa43ab66921 124 if (COAP_DELETE < transactionMessage->code)
terencez 0:1fa43ab66921 125 {
terencez 0:1fa43ab66921 126 // response
terencez 0:1fa43ab66921 127 return transacP->ack_received ? 1 : 0;
terencez 0:1fa43ab66921 128 }
terencez 0:1fa43ab66921 129 if (!IS_OPTION(transactionMessage, COAP_OPTION_TOKEN))
terencez 0:1fa43ab66921 130 {
terencez 0:1fa43ab66921 131 // request without token
terencez 0:1fa43ab66921 132 return transacP->ack_received ? 1 : 0;
terencez 0:1fa43ab66921 133 }
terencez 0:1fa43ab66921 134
terencez 0:1fa43ab66921 135 len = coap_get_header_token(receivedMessage, &token);
terencez 0:1fa43ab66921 136 if (transactionMessage->token_len == len)
terencez 0:1fa43ab66921 137 {
terencez 0:1fa43ab66921 138 if (memcmp(transactionMessage->token, token, len)==0) return 1;
terencez 0:1fa43ab66921 139 }
terencez 0:1fa43ab66921 140
terencez 0:1fa43ab66921 141 return 0;
terencez 0:1fa43ab66921 142 }
terencez 0:1fa43ab66921 143
terencez 0:1fa43ab66921 144 lwm2m_transaction_t * transaction_new(void * sessionH,
terencez 0:1fa43ab66921 145 coap_method_t method,
terencez 0:1fa43ab66921 146 char * altPath,
terencez 0:1fa43ab66921 147 lwm2m_uri_t * uriP,
terencez 0:1fa43ab66921 148 uint16_t mID,
terencez 0:1fa43ab66921 149 uint8_t token_len,
terencez 0:1fa43ab66921 150 uint8_t* token)
terencez 0:1fa43ab66921 151 {
terencez 0:1fa43ab66921 152 lwm2m_transaction_t * transacP;
terencez 0:1fa43ab66921 153 int result;
terencez 0:1fa43ab66921 154
terencez 0:1fa43ab66921 155 LOG_ARG("method: %d, altPath: \"%s\", mID: %d, token_len: %d",
terencez 0:1fa43ab66921 156 method, altPath, mID, token_len);
terencez 0:1fa43ab66921 157 LOG_URI(uriP);
terencez 0:1fa43ab66921 158
terencez 0:1fa43ab66921 159 // no transactions without peer
terencez 0:1fa43ab66921 160 if (NULL == sessionH) return NULL;
terencez 0:1fa43ab66921 161
terencez 0:1fa43ab66921 162 transacP = (lwm2m_transaction_t *)lwm2m_malloc(sizeof(lwm2m_transaction_t));
terencez 0:1fa43ab66921 163
terencez 0:1fa43ab66921 164 if (NULL == transacP) return NULL;
terencez 0:1fa43ab66921 165 memset(transacP, 0, sizeof(lwm2m_transaction_t));
terencez 0:1fa43ab66921 166
terencez 0:1fa43ab66921 167 transacP->message = lwm2m_malloc(sizeof(coap_packet_t));
terencez 0:1fa43ab66921 168 if (NULL == transacP->message) goto error;
terencez 0:1fa43ab66921 169
terencez 0:1fa43ab66921 170 coap_init_message(transacP->message, COAP_TYPE_CON, method, mID);
terencez 0:1fa43ab66921 171
terencez 0:1fa43ab66921 172 transacP->peerH = sessionH;
terencez 0:1fa43ab66921 173
terencez 0:1fa43ab66921 174 transacP->mID = mID;
terencez 0:1fa43ab66921 175
terencez 0:1fa43ab66921 176 if (altPath != NULL)
terencez 0:1fa43ab66921 177 {
terencez 0:1fa43ab66921 178 // TODO: Support multi-segment alternative path
terencez 0:1fa43ab66921 179 coap_set_header_uri_path_segment(transacP->message, altPath + 1);
terencez 0:1fa43ab66921 180 }
terencez 0:1fa43ab66921 181 if (NULL != uriP)
terencez 0:1fa43ab66921 182 {
terencez 0:1fa43ab66921 183 result = utils_intCopy(transacP->objStringID, LWM2M_STRING_ID_MAX_LEN, uriP->objectId);
terencez 0:1fa43ab66921 184 if (result < 0) goto error;
terencez 0:1fa43ab66921 185
terencez 0:1fa43ab66921 186 coap_set_header_uri_path_segment(transacP->message, transacP->objStringID);
terencez 0:1fa43ab66921 187
terencez 0:1fa43ab66921 188 if (LWM2M_URI_IS_SET_INSTANCE(uriP))
terencez 0:1fa43ab66921 189 {
terencez 0:1fa43ab66921 190 result = utils_intCopy(transacP->instanceStringID, LWM2M_STRING_ID_MAX_LEN, uriP->instanceId);
terencez 0:1fa43ab66921 191 if (result < 0) goto error;
terencez 0:1fa43ab66921 192 coap_set_header_uri_path_segment(transacP->message, transacP->instanceStringID);
terencez 0:1fa43ab66921 193 }
terencez 0:1fa43ab66921 194 else
terencez 0:1fa43ab66921 195 {
terencez 0:1fa43ab66921 196 if (LWM2M_URI_IS_SET_RESOURCE(uriP))
terencez 0:1fa43ab66921 197 {
terencez 0:1fa43ab66921 198 coap_set_header_uri_path_segment(transacP->message, NULL);
terencez 0:1fa43ab66921 199 }
terencez 0:1fa43ab66921 200 }
terencez 0:1fa43ab66921 201 if (LWM2M_URI_IS_SET_RESOURCE(uriP))
terencez 0:1fa43ab66921 202 {
terencez 0:1fa43ab66921 203 result = utils_intCopy(transacP->resourceStringID, LWM2M_STRING_ID_MAX_LEN, uriP->resourceId);
terencez 0:1fa43ab66921 204 if (result < 0) goto error;
terencez 0:1fa43ab66921 205 coap_set_header_uri_path_segment(transacP->message, transacP->resourceStringID);
terencez 0:1fa43ab66921 206 }
terencez 0:1fa43ab66921 207 }
terencez 0:1fa43ab66921 208 if (0 < token_len)
terencez 0:1fa43ab66921 209 {
terencez 0:1fa43ab66921 210 if (NULL != token)
terencez 0:1fa43ab66921 211 {
terencez 0:1fa43ab66921 212 coap_set_header_token(transacP->message, token, token_len);
terencez 0:1fa43ab66921 213 }
terencez 0:1fa43ab66921 214 else {
terencez 0:1fa43ab66921 215 // generate a token
terencez 0:1fa43ab66921 216 uint8_t temp_token[COAP_TOKEN_LEN];
terencez 0:1fa43ab66921 217 time_t tv_sec = lwm2m_gettime();
terencez 0:1fa43ab66921 218
terencez 0:1fa43ab66921 219 // initialize first 6 bytes, leave the last 2 random
terencez 0:1fa43ab66921 220 temp_token[0] = mID;
terencez 0:1fa43ab66921 221 temp_token[1] = mID >> 8;
terencez 0:1fa43ab66921 222 temp_token[2] = tv_sec;
terencez 0:1fa43ab66921 223 temp_token[3] = tv_sec >> 8;
terencez 0:1fa43ab66921 224 temp_token[4] = tv_sec >> 16;
terencez 0:1fa43ab66921 225 temp_token[5] = tv_sec >> 24;
terencez 0:1fa43ab66921 226 // use just the provided amount of bytes
terencez 0:1fa43ab66921 227 coap_set_header_token(transacP->message, temp_token, token_len);
terencez 0:1fa43ab66921 228 }
terencez 0:1fa43ab66921 229 }
terencez 0:1fa43ab66921 230
terencez 0:1fa43ab66921 231 LOG("Exiting on success");
terencez 0:1fa43ab66921 232 return transacP;
terencez 0:1fa43ab66921 233
terencez 0:1fa43ab66921 234 error:
terencez 0:1fa43ab66921 235 LOG("Exiting on failure");
terencez 0:1fa43ab66921 236 lwm2m_free(transacP);
terencez 0:1fa43ab66921 237 return NULL;
terencez 0:1fa43ab66921 238 }
terencez 0:1fa43ab66921 239
terencez 0:1fa43ab66921 240 void transaction_free(lwm2m_transaction_t * transacP)
terencez 0:1fa43ab66921 241 {
terencez 0:1fa43ab66921 242 LOG("Entering");
terencez 0:1fa43ab66921 243 if (transacP->message) lwm2m_free(transacP->message);
terencez 0:1fa43ab66921 244 if (transacP->buffer) lwm2m_free(transacP->buffer);
terencez 0:1fa43ab66921 245 lwm2m_free(transacP);
terencez 0:1fa43ab66921 246 }
terencez 0:1fa43ab66921 247
terencez 0:1fa43ab66921 248 void transaction_remove(lwm2m_context_t * contextP,
terencez 0:1fa43ab66921 249 lwm2m_transaction_t * transacP)
terencez 0:1fa43ab66921 250 {
terencez 0:1fa43ab66921 251 LOG("Entering");
terencez 0:1fa43ab66921 252 contextP->transactionList = (lwm2m_transaction_t *) LWM2M_LIST_RM(contextP->transactionList, transacP->mID, NULL);
terencez 0:1fa43ab66921 253 transaction_free(transacP);
terencez 0:1fa43ab66921 254 }
terencez 0:1fa43ab66921 255
terencez 0:1fa43ab66921 256 bool transaction_handleResponse(lwm2m_context_t * contextP,
terencez 0:1fa43ab66921 257 void * fromSessionH,
terencez 0:1fa43ab66921 258 coap_packet_t * message,
terencez 0:1fa43ab66921 259 coap_packet_t * response)
terencez 0:1fa43ab66921 260 {
terencez 0:1fa43ab66921 261 bool found = false;
terencez 0:1fa43ab66921 262 bool reset = false;
terencez 0:1fa43ab66921 263 lwm2m_transaction_t * transacP;
terencez 0:1fa43ab66921 264
terencez 0:1fa43ab66921 265 LOG("Entering");
terencez 0:1fa43ab66921 266 transacP = contextP->transactionList;
terencez 0:1fa43ab66921 267
terencez 0:1fa43ab66921 268 while (NULL != transacP)
terencez 0:1fa43ab66921 269 {
terencez 0:1fa43ab66921 270 if (lwm2m_session_is_equal(fromSessionH, transacP->peerH, contextP->userData) == true)
terencez 0:1fa43ab66921 271 {
terencez 0:1fa43ab66921 272 if (!transacP->ack_received)
terencez 0:1fa43ab66921 273 {
terencez 0:1fa43ab66921 274 if ((COAP_TYPE_ACK == message->type) || (COAP_TYPE_RST == message->type))
terencez 0:1fa43ab66921 275 {
terencez 0:1fa43ab66921 276 if (transacP->mID == message->mid)
terencez 0:1fa43ab66921 277 {
terencez 0:1fa43ab66921 278 found = true;
terencez 0:1fa43ab66921 279 transacP->ack_received = true;
terencez 0:1fa43ab66921 280 reset = COAP_TYPE_RST == message->type;
terencez 0:1fa43ab66921 281 }
terencez 0:1fa43ab66921 282 }
terencez 0:1fa43ab66921 283 }
terencez 0:1fa43ab66921 284
terencez 0:1fa43ab66921 285 if (reset || prv_checkFinished(transacP, message))
terencez 0:1fa43ab66921 286 {
terencez 0:1fa43ab66921 287 // HACK: If a message is sent from the monitor callback,
terencez 0:1fa43ab66921 288 // it will arrive before the registration ACK.
terencez 0:1fa43ab66921 289 // So we resend transaction that were denied for authentication reason.
terencez 0:1fa43ab66921 290 if (!reset)
terencez 0:1fa43ab66921 291 {
terencez 0:1fa43ab66921 292 if (COAP_TYPE_CON == message->type && NULL != response)
terencez 0:1fa43ab66921 293 {
terencez 0:1fa43ab66921 294 coap_init_message(response, COAP_TYPE_ACK, 0, message->mid);
terencez 0:1fa43ab66921 295 message_send(contextP, response, fromSessionH);
terencez 0:1fa43ab66921 296 }
terencez 0:1fa43ab66921 297
terencez 0:1fa43ab66921 298 if ((COAP_401_UNAUTHORIZED == message->code) && (COAP_MAX_RETRANSMIT > transacP->retrans_counter))
terencez 0:1fa43ab66921 299 {
terencez 0:1fa43ab66921 300 transacP->ack_received = false;
terencez 0:1fa43ab66921 301 transacP->retrans_time += COAP_RESPONSE_TIMEOUT;
terencez 0:1fa43ab66921 302 return true;
terencez 0:1fa43ab66921 303 }
terencez 0:1fa43ab66921 304 }
terencez 0:1fa43ab66921 305 if (transacP->callback != NULL)
terencez 0:1fa43ab66921 306 {
terencez 0:1fa43ab66921 307 transacP->callback(transacP, message);
terencez 0:1fa43ab66921 308 }
terencez 0:1fa43ab66921 309 transaction_remove(contextP, transacP);
terencez 0:1fa43ab66921 310 return true;
terencez 0:1fa43ab66921 311 }
terencez 0:1fa43ab66921 312 // if we found our guy, exit
terencez 0:1fa43ab66921 313 if (found)
terencez 0:1fa43ab66921 314 {
terencez 0:1fa43ab66921 315 time_t tv_sec = lwm2m_gettime();
terencez 0:1fa43ab66921 316 if (0 <= tv_sec)
terencez 0:1fa43ab66921 317 {
terencez 0:1fa43ab66921 318 transacP->retrans_time = tv_sec;
terencez 0:1fa43ab66921 319 }
terencez 0:1fa43ab66921 320 if (transacP->response_timeout)
terencez 0:1fa43ab66921 321 {
terencez 0:1fa43ab66921 322 transacP->retrans_time += transacP->response_timeout;
terencez 0:1fa43ab66921 323 }
terencez 0:1fa43ab66921 324 else
terencez 0:1fa43ab66921 325 {
terencez 0:1fa43ab66921 326 transacP->retrans_time += COAP_RESPONSE_TIMEOUT * transacP->retrans_counter;
terencez 0:1fa43ab66921 327 }
terencez 0:1fa43ab66921 328 return true;
terencez 0:1fa43ab66921 329 }
terencez 0:1fa43ab66921 330 }
terencez 0:1fa43ab66921 331
terencez 0:1fa43ab66921 332 transacP = transacP->next;
terencez 0:1fa43ab66921 333 }
terencez 0:1fa43ab66921 334 return false;
terencez 0:1fa43ab66921 335 }
terencez 0:1fa43ab66921 336
terencez 0:1fa43ab66921 337 int transaction_send(lwm2m_context_t * contextP,
terencez 0:1fa43ab66921 338 lwm2m_transaction_t * transacP)
terencez 0:1fa43ab66921 339 {
terencez 0:1fa43ab66921 340 bool maxRetriesReached = false;
terencez 0:1fa43ab66921 341
terencez 0:1fa43ab66921 342 LOG("Entering");
terencez 0:1fa43ab66921 343 if (transacP->buffer == NULL)
terencez 0:1fa43ab66921 344 {
terencez 0:1fa43ab66921 345 transacP->buffer_len = coap_serialize_get_size(transacP->message);
terencez 0:1fa43ab66921 346 if (transacP->buffer_len == 0) return COAP_500_INTERNAL_SERVER_ERROR;
terencez 0:1fa43ab66921 347
terencez 0:1fa43ab66921 348 transacP->buffer = (uint8_t*)lwm2m_malloc(transacP->buffer_len);
terencez 0:1fa43ab66921 349 if (transacP->buffer == NULL) return COAP_500_INTERNAL_SERVER_ERROR;
terencez 0:1fa43ab66921 350
terencez 0:1fa43ab66921 351 transacP->buffer_len = coap_serialize_message(transacP->message, transacP->buffer);
terencez 0:1fa43ab66921 352 if (transacP->buffer_len == 0)
terencez 0:1fa43ab66921 353 {
terencez 0:1fa43ab66921 354 lwm2m_free(transacP->buffer);
terencez 0:1fa43ab66921 355 transacP->buffer = NULL;
terencez 0:1fa43ab66921 356 transaction_remove(contextP, transacP);
terencez 0:1fa43ab66921 357 return COAP_500_INTERNAL_SERVER_ERROR;
terencez 0:1fa43ab66921 358 }
terencez 0:1fa43ab66921 359 }
terencez 0:1fa43ab66921 360
terencez 0:1fa43ab66921 361 if (!transacP->ack_received)
terencez 0:1fa43ab66921 362 {
terencez 0:1fa43ab66921 363 long unsigned timeout;
terencez 0:1fa43ab66921 364
terencez 0:1fa43ab66921 365 if (0 == transacP->retrans_counter)
terencez 0:1fa43ab66921 366 {
terencez 0:1fa43ab66921 367 time_t tv_sec = lwm2m_gettime();
terencez 0:1fa43ab66921 368 if (0 <= tv_sec)
terencez 0:1fa43ab66921 369 {
terencez 0:1fa43ab66921 370 transacP->retrans_time = tv_sec + COAP_RESPONSE_TIMEOUT;
terencez 0:1fa43ab66921 371 transacP->retrans_counter = 1;
terencez 0:1fa43ab66921 372 timeout = 0;
terencez 0:1fa43ab66921 373 }
terencez 0:1fa43ab66921 374 else
terencez 0:1fa43ab66921 375 {
terencez 0:1fa43ab66921 376 maxRetriesReached = true;
terencez 0:1fa43ab66921 377 }
terencez 0:1fa43ab66921 378 }
terencez 0:1fa43ab66921 379 else
terencez 0:1fa43ab66921 380 {
terencez 0:1fa43ab66921 381 timeout = COAP_RESPONSE_TIMEOUT << (transacP->retrans_counter - 1);
terencez 0:1fa43ab66921 382 }
terencez 0:1fa43ab66921 383
terencez 0:1fa43ab66921 384 if (COAP_MAX_RETRANSMIT + 1 >= transacP->retrans_counter)
terencez 0:1fa43ab66921 385 {
terencez 0:1fa43ab66921 386 (void)lwm2m_buffer_send(transacP->peerH, transacP->buffer, transacP->buffer_len, contextP->userData);
terencez 0:1fa43ab66921 387
terencez 0:1fa43ab66921 388 transacP->retrans_time += timeout;
terencez 0:1fa43ab66921 389 transacP->retrans_counter += 1;
terencez 0:1fa43ab66921 390 }
terencez 0:1fa43ab66921 391 else
terencez 0:1fa43ab66921 392 {
terencez 0:1fa43ab66921 393 maxRetriesReached = true;
terencez 0:1fa43ab66921 394 }
terencez 0:1fa43ab66921 395 }
terencez 0:1fa43ab66921 396
terencez 0:1fa43ab66921 397 if (transacP->ack_received || maxRetriesReached)
terencez 0:1fa43ab66921 398 {
terencez 0:1fa43ab66921 399 if (transacP->callback)
terencez 0:1fa43ab66921 400 {
terencez 0:1fa43ab66921 401 transacP->callback(transacP, NULL);
terencez 0:1fa43ab66921 402 }
terencez 0:1fa43ab66921 403 transaction_remove(contextP, transacP);
terencez 0:1fa43ab66921 404 return -1;
terencez 0:1fa43ab66921 405 }
terencez 0:1fa43ab66921 406
terencez 0:1fa43ab66921 407 return 0;
terencez 0:1fa43ab66921 408 }
terencez 0:1fa43ab66921 409
terencez 0:1fa43ab66921 410 void transaction_step(lwm2m_context_t * contextP,
terencez 0:1fa43ab66921 411 time_t currentTime,
terencez 0:1fa43ab66921 412 time_t * timeoutP)
terencez 0:1fa43ab66921 413 {
terencez 0:1fa43ab66921 414 lwm2m_transaction_t * transacP;
terencez 0:1fa43ab66921 415
terencez 0:1fa43ab66921 416 LOG("Entering");
terencez 0:1fa43ab66921 417 transacP = contextP->transactionList;
terencez 0:1fa43ab66921 418 while (transacP != NULL)
terencez 0:1fa43ab66921 419 {
terencez 0:1fa43ab66921 420 // transaction_send() may remove transaction from the linked list
terencez 0:1fa43ab66921 421 lwm2m_transaction_t * nextP = transacP->next;
terencez 0:1fa43ab66921 422 int removed = 0;
terencez 0:1fa43ab66921 423
terencez 0:1fa43ab66921 424 if (transacP->retrans_time <= currentTime)
terencez 0:1fa43ab66921 425 {
terencez 0:1fa43ab66921 426 removed = transaction_send(contextP, transacP);
terencez 0:1fa43ab66921 427 }
terencez 0:1fa43ab66921 428
terencez 0:1fa43ab66921 429 if (0 == removed)
terencez 0:1fa43ab66921 430 {
terencez 0:1fa43ab66921 431 time_t interval;
terencez 0:1fa43ab66921 432
terencez 0:1fa43ab66921 433 if (transacP->retrans_time > currentTime)
terencez 0:1fa43ab66921 434 {
terencez 0:1fa43ab66921 435 interval = transacP->retrans_time - currentTime;
terencez 0:1fa43ab66921 436 }
terencez 0:1fa43ab66921 437 else
terencez 0:1fa43ab66921 438 {
terencez 0:1fa43ab66921 439 interval = 1;
terencez 0:1fa43ab66921 440 }
terencez 0:1fa43ab66921 441
terencez 0:1fa43ab66921 442 if (*timeoutP > interval)
terencez 0:1fa43ab66921 443 {
terencez 0:1fa43ab66921 444 *timeoutP = interval;
terencez 0:1fa43ab66921 445 }
terencez 0:1fa43ab66921 446 }
terencez 0:1fa43ab66921 447 else
terencez 0:1fa43ab66921 448 {
terencez 0:1fa43ab66921 449 *timeoutP = 1;
terencez 0:1fa43ab66921 450 }
terencez 0:1fa43ab66921 451
terencez 0:1fa43ab66921 452 transacP = nextP;
terencez 0:1fa43ab66921 453 }
terencez 0:1fa43ab66921 454 }