Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
packet.c
00001 /******************************************************************************* 00002 * 00003 * Copyright (c) 2013, 2014 Intel Corporation and others. 00004 * All rights reserved. This program and the accompanying materials 00005 * are made available under the terms of the Eclipse Public License v1.0 00006 * and Eclipse Distribution License v1.0 which accompany this distribution. 00007 * 00008 * The Eclipse Public License is available at 00009 * http://www.eclipse.org/legal/epl-v10.html 00010 * The Eclipse Distribution License is available at 00011 * http://www.eclipse.org/org/documents/edl-v10.php. 00012 * 00013 * Contributors: 00014 * David Navarro, Intel Corporation - initial API and implementation 00015 * domedambrosio - Please refer to git log 00016 * Fabien Fleutot - Please refer to git log 00017 * Fabien Fleutot - Please refer to git log 00018 * Simon Bernard - Please refer to git log 00019 * Toby Jaffey - Please refer to git log 00020 * Pascal Rieux - Please refer to git log 00021 * Bosch Software Innovations GmbH - Please refer to git log 00022 * 00023 *******************************************************************************/ 00024 00025 /* 00026 Copyright (c) 2013, 2014 Intel Corporation 00027 00028 Redistribution and use in source and binary forms, with or without modification, 00029 are permitted provided that the following conditions are met: 00030 00031 * Redistributions of source code must retain the above copyright notice, 00032 this list of conditions and the following disclaimer. 00033 * Redistributions in binary form must reproduce the above copyright notice, 00034 this list of conditions and the following disclaimer in the documentation 00035 and/or other materials provided with the distribution. 00036 * Neither the name of Intel Corporation nor the names of its contributors 00037 may be used to endorse or promote products derived from this software 00038 without specific prior written permission. 00039 00040 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00041 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00042 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00043 IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 00044 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00045 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00046 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00047 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 00048 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 00049 THE POSSIBILITY OF SUCH DAMAGE. 00050 00051 David Navarro <david.navarro@intel.com> 00052 00053 */ 00054 00055 /* 00056 Contains code snippets which are: 00057 00058 * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich 00059 * All rights reserved. 00060 * 00061 * Redistribution and use in source and binary forms, with or without 00062 * modification, are permitted provided that the following conditions 00063 * are met: 00064 * 1. Redistributions of source code must retain the above copyright 00065 * notice, this list of conditions and the following disclaimer. 00066 * 2. Redistributions in binary form must reproduce the above copyright 00067 * notice, this list of conditions and the following disclaimer in the 00068 * documentation and/or other materials provided with the distribution. 00069 * 3. Neither the name of the Institute nor the names of its contributors 00070 * may be used to endorse or promote products derived from this software 00071 * without specific prior written permission. 00072 * 00073 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00074 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00075 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00076 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00077 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00078 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00079 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00080 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00081 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00082 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00083 * SUCH DAMAGE. 00084 00085 */ 00086 00087 00088 #include "internals.h" 00089 00090 #include <stdlib.h> 00091 #include <string.h> 00092 00093 #include <stdio.h> 00094 00095 00096 static void handle_reset(lwm2m_context_t * contextP, 00097 void * fromSessionH, 00098 coap_packet_t * message) 00099 { 00100 #ifdef LWM2M_CLIENT_MODE 00101 LOG("Entering"); 00102 observe_cancel(contextP, message->mid, fromSessionH); 00103 #endif 00104 } 00105 00106 static coap_status_t handle_request(lwm2m_context_t * contextP, 00107 void * fromSessionH, 00108 coap_packet_t * message, 00109 coap_packet_t * response) 00110 { 00111 lwm2m_uri_t * uriP; 00112 coap_status_t result = COAP_IGNORE; 00113 00114 LOG("Entering"); 00115 00116 #ifdef LWM2M_CLIENT_MODE 00117 uriP = uri_decode(contextP->altPath, message->uri_path); 00118 #else 00119 uriP = uri_decode(NULL, message->uri_path); 00120 #endif 00121 00122 if (uriP == NULL) return COAP_400_BAD_REQUEST; 00123 00124 switch(uriP->flag & LWM2M_URI_MASK_TYPE) 00125 { 00126 #ifdef LWM2M_CLIENT_MODE 00127 case LWM2M_URI_FLAG_DM: 00128 { 00129 lwm2m_server_t * serverP; 00130 00131 serverP = utils_findServer(contextP, fromSessionH); 00132 if (serverP != NULL) 00133 { 00134 result = dm_handleRequest(contextP, uriP, serverP, message, response); 00135 } 00136 #ifdef LWM2M_BOOTSTRAP 00137 else 00138 { 00139 serverP = utils_findBootstrapServer(contextP, fromSessionH); 00140 if (serverP != NULL) 00141 { 00142 result = bootstrap_handleCommand(contextP, uriP, serverP, message, response); 00143 } 00144 } 00145 #endif 00146 } 00147 break; 00148 00149 #ifdef LWM2M_BOOTSTRAP 00150 case LWM2M_URI_FLAG_DELETE_ALL: 00151 if (COAP_DELETE != message->code) 00152 { 00153 result = COAP_400_BAD_REQUEST; 00154 } 00155 else 00156 { 00157 result = bootstrap_handleDeleteAll(contextP, fromSessionH); 00158 } 00159 break; 00160 00161 case LWM2M_URI_FLAG_BOOTSTRAP: 00162 if (message->code == COAP_POST) 00163 { 00164 result = bootstrap_handleFinish(contextP, fromSessionH); 00165 } 00166 break; 00167 #endif 00168 #endif 00169 00170 #ifdef LWM2M_SERVER_MODE 00171 case LWM2M_URI_FLAG_REGISTRATION: 00172 result = registration_handleRequest(contextP, uriP, fromSessionH, message, response); 00173 break; 00174 #endif 00175 #ifdef LWM2M_BOOTSTRAP_SERVER_MODE 00176 case LWM2M_URI_FLAG_BOOTSTRAP: 00177 result = bootstrap_handleRequest(contextP, uriP, fromSessionH, message, response); 00178 break; 00179 #endif 00180 default: 00181 result = COAP_IGNORE; 00182 break; 00183 } 00184 00185 coap_set_status_code(response, result); 00186 00187 if (COAP_IGNORE < result && result < COAP_400_BAD_REQUEST) 00188 { 00189 result = NO_ERROR; 00190 } 00191 00192 lwm2m_free(uriP); 00193 return result; 00194 } 00195 00196 /* This function is an adaptation of function coap_receive() from Erbium's er-coap-13-engine.c. 00197 * Erbium is Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich 00198 * All rights reserved. 00199 */ 00200 void lwm2m_handle_packet(lwm2m_context_t * contextP, 00201 uint8_t * buffer, 00202 int length, 00203 void * fromSessionH) 00204 { 00205 coap_status_t coap_error_code = NO_ERROR; 00206 static coap_packet_t message[1]; 00207 static coap_packet_t response[1]; 00208 00209 LOG("Entering"); 00210 coap_error_code = coap_parse_message(message, buffer, (uint16_t)length); 00211 if (coap_error_code == NO_ERROR) 00212 { 00213 LOG_ARG("Parsed: ver %u, type %u, tkl %u, code %u.%.2u, mid %u, Content type: %d", 00214 message->version, message->type, message->token_len, message->code >> 5, message->code & 0x1F, message->mid, message->content_type); 00215 LOG_ARG("Payload: %.*s", message->payload_len, message->payload); 00216 if (message->code >= COAP_GET && message->code <= COAP_DELETE) 00217 { 00218 uint32_t block_num = 0; 00219 uint16_t block_size = REST_MAX_CHUNK_SIZE; 00220 uint32_t block_offset = 0; 00221 int64_t new_offset = 0; 00222 00223 /* prepare response */ 00224 if (message->type == COAP_TYPE_CON) 00225 { 00226 /* Reliable CON requests are answered with an ACK. */ 00227 coap_init_message(response, COAP_TYPE_ACK, COAP_205_CONTENT, message->mid); 00228 } 00229 else 00230 { 00231 /* Unreliable NON requests are answered with a NON as well. */ 00232 coap_init_message(response, COAP_TYPE_NON, COAP_205_CONTENT, contextP->nextMID++); 00233 } 00234 00235 /* mirror token */ 00236 if (message->token_len) 00237 { 00238 coap_set_header_token(response, message->token, message->token_len); 00239 } 00240 00241 /* get offset for blockwise transfers */ 00242 if (coap_get_header_block2(message, &block_num, NULL, &block_size, &block_offset)) 00243 { 00244 LOG_ARG("Blockwise: block request %u (%u/%u) @ %u bytes", block_num, block_size, REST_MAX_CHUNK_SIZE, block_offset); 00245 block_size = MIN(block_size, REST_MAX_CHUNK_SIZE); 00246 new_offset = block_offset; 00247 } 00248 00249 /* handle block1 option */ 00250 if (IS_OPTION(message, COAP_OPTION_BLOCK1)) 00251 { 00252 #ifdef LWM2M_CLIENT_MODE 00253 // get server 00254 lwm2m_server_t * serverP; 00255 serverP = utils_findServer(contextP, fromSessionH); 00256 #ifdef LWM2M_BOOTSTRAP 00257 if (serverP == NULL) 00258 { 00259 serverP = utils_findBootstrapServer(contextP, fromSessionH); 00260 } 00261 #endif 00262 if (serverP == NULL) 00263 { 00264 coap_error_code = COAP_500_INTERNAL_SERVER_ERROR; 00265 } 00266 else 00267 { 00268 uint32_t block1_num; 00269 uint8_t block1_more; 00270 uint16_t block1_size; 00271 uint8_t * complete_buffer = NULL; 00272 size_t complete_buffer_size; 00273 00274 // parse block1 header 00275 coap_get_header_block1(message, &block1_num, &block1_more, &block1_size, NULL); 00276 LOG_ARG("Blockwise: block1 request NUM %u (SZX %u/ SZX Max%u) MORE %u", block1_num, block1_size, REST_MAX_CHUNK_SIZE, block1_more); 00277 00278 // handle block 1 00279 coap_error_code = coap_block1_handler(&serverP->block1Data, message->mid, message->payload, message->payload_len, block1_size, block1_num, block1_more, &complete_buffer, &complete_buffer_size); 00280 00281 // if payload is complete, replace it in the coap message. 00282 if (coap_error_code == NO_ERROR) 00283 { 00284 message->payload = complete_buffer; 00285 message->payload_len = complete_buffer_size; 00286 } 00287 else if (coap_error_code == COAP_231_CONTINUE) 00288 { 00289 block1_size = MIN(block1_size, REST_MAX_CHUNK_SIZE); 00290 coap_set_header_block1(response,block1_num, block1_more,block1_size); 00291 } 00292 } 00293 #else 00294 coap_error_code = COAP_501_NOT_IMPLEMENTED; 00295 #endif 00296 } 00297 if (coap_error_code == NO_ERROR) 00298 { 00299 coap_error_code = handle_request(contextP, fromSessionH, message, response); 00300 } 00301 if (coap_error_code==NO_ERROR) 00302 { 00303 if ( IS_OPTION(message, COAP_OPTION_BLOCK2) ) 00304 { 00305 /* unchanged new_offset indicates that resource is unaware of blockwise transfer */ 00306 if (new_offset==block_offset) 00307 { 00308 LOG_ARG("Blockwise: unaware resource with payload length %u/%u", response->payload_len, block_size); 00309 if (block_offset >= response->payload_len) 00310 { 00311 LOG("handle_incoming_data(): block_offset >= response->payload_len"); 00312 00313 response->code = COAP_402_BAD_OPTION; 00314 coap_set_payload(response, "BlockOutOfScope", 15); /* a const char str[] and sizeof(str) produces larger code size */ 00315 } 00316 else 00317 { 00318 coap_set_header_block2(response, block_num, response->payload_len - block_offset > block_size, block_size); 00319 coap_set_payload(response, response->payload+block_offset, MIN(response->payload_len - block_offset, block_size)); 00320 } /* if (valid offset) */ 00321 } 00322 else 00323 { 00324 /* resource provides chunk-wise data */ 00325 LOG_ARG("Blockwise: blockwise resource, new offset %d", (int) new_offset); 00326 coap_set_header_block2(response, block_num, new_offset!=-1 || response->payload_len > block_size, block_size); 00327 if (response->payload_len > block_size) coap_set_payload(response, response->payload, block_size); 00328 } /* if (resource aware of blockwise) */ 00329 } 00330 else if (new_offset!=0) 00331 { 00332 LOG_ARG("Blockwise: no block option for blockwise resource, using block size %u", REST_MAX_CHUNK_SIZE); 00333 00334 coap_set_header_block2(response, 0, new_offset!=-1, REST_MAX_CHUNK_SIZE); 00335 coap_set_payload(response, response->payload, MIN(response->payload_len, REST_MAX_CHUNK_SIZE)); 00336 } /* if (blockwise request) */ 00337 00338 coap_error_code = message_send(contextP, response, fromSessionH); 00339 00340 lwm2m_free(response->payload); 00341 response->payload = NULL; 00342 response->payload_len = 0; 00343 } 00344 else if (coap_error_code != COAP_IGNORE) 00345 { 00346 if (1 == coap_set_status_code(response, coap_error_code)) 00347 { 00348 coap_error_code = message_send(contextP, response, fromSessionH); 00349 } 00350 } 00351 } 00352 else 00353 { 00354 /* Responses */ 00355 switch (message->type) 00356 { 00357 case COAP_TYPE_NON: 00358 case COAP_TYPE_CON: 00359 { 00360 bool done = transaction_handleResponse(contextP, fromSessionH, message, response); 00361 00362 #ifdef LWM2M_SERVER_MODE 00363 if (!done && IS_OPTION(message, COAP_OPTION_OBSERVE) && 00364 ((message->code == COAP_204_CHANGED) || (message->code == COAP_205_CONTENT))) 00365 { 00366 done = observe_handleNotify(contextP, fromSessionH, message, response); 00367 } 00368 #endif 00369 if (!done && message->type == COAP_TYPE_CON ) 00370 { 00371 coap_init_message(response, COAP_TYPE_ACK, 0, message->mid); 00372 coap_error_code = message_send(contextP, response, fromSessionH); 00373 } 00374 } 00375 break; 00376 00377 case COAP_TYPE_RST: 00378 /* Cancel possible subscriptions. */ 00379 handle_reset(contextP, fromSessionH, message); 00380 transaction_handleResponse(contextP, fromSessionH, message, NULL); 00381 break; 00382 00383 case COAP_TYPE_ACK: 00384 transaction_handleResponse(contextP, fromSessionH, message, NULL); 00385 break; 00386 00387 default: 00388 break; 00389 } 00390 } /* Request or Response */ 00391 coap_free_header(message); 00392 } /* if (parsed correctly) */ 00393 else 00394 { 00395 LOG_ARG("Message parsing failed %u.%2u", coap_error_code >> 5, coap_error_code & 0x1F); 00396 } 00397 00398 if (coap_error_code != NO_ERROR && coap_error_code != COAP_IGNORE) 00399 { 00400 LOG_ARG("ERROR %u: %s", coap_error_code, coap_error_message); 00401 00402 /* Set to sendable error code. */ 00403 if (coap_error_code >= 192) 00404 { 00405 coap_error_code = COAP_500_INTERNAL_SERVER_ERROR; 00406 } 00407 /* Reuse input buffer for error message. */ 00408 coap_init_message(message, COAP_TYPE_ACK, coap_error_code, message->mid); 00409 coap_set_payload(message, coap_error_message, strlen(coap_error_message)); 00410 message_send(contextP, message, fromSessionH); 00411 } 00412 } 00413 00414 00415 coap_status_t message_send(lwm2m_context_t * contextP, 00416 coap_packet_t * message, 00417 void * sessionH) 00418 { 00419 coap_status_t result = COAP_500_INTERNAL_SERVER_ERROR; 00420 uint8_t * pktBuffer; 00421 size_t pktBufferLen = 0; 00422 size_t allocLen; 00423 00424 LOG("Entering"); 00425 allocLen = coap_serialize_get_size(message); 00426 LOG_ARG("Size to allocate: %d", allocLen); 00427 if (allocLen == 0) return COAP_500_INTERNAL_SERVER_ERROR; 00428 00429 pktBuffer = (uint8_t *)lwm2m_malloc(allocLen); 00430 if (pktBuffer != NULL) 00431 { 00432 pktBufferLen = coap_serialize_message(message, pktBuffer); 00433 LOG_ARG("coap_serialize_message() returned %d", pktBufferLen); 00434 if (0 != pktBufferLen) 00435 { 00436 result = lwm2m_buffer_send(sessionH, pktBuffer, pktBufferLen, contextP->userData); 00437 } 00438 lwm2m_free(pktBuffer); 00439 } 00440 00441 return result; 00442 } 00443
Generated on Thu Jul 14 2022 09:09:49 by
1.7.2