pick up wakaama files from https://github.com/eclipse/wakaama
core/transaction.c@0:1fa43ab66921, 2017-04-19 (annotated)
- Committer:
- terencez
- Date:
- Wed Apr 19 11:30:02 2017 +0000
- Revision:
- 0:1fa43ab66921
Initial commit
Who changed what in which revision?
User | Revision | Line number | New 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 | } |