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