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.
er-coap-13.c
00001 /* 00002 * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the Institute nor the names of its contributors 00014 * may be used to endorse or promote products derived from this software 00015 * without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00018 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00021 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00022 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00023 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00024 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00025 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00026 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00027 * SUCH DAMAGE. 00028 * 00029 * This file is part of the Contiki operating system. 00030 */ 00031 00032 /** 00033 * \file 00034 * An implementation of the Constrained Application Protocol (draft 12) 00035 * \author 00036 * Matthias Kovatsch <kovatsch@inf.ethz.ch> 00037 * \contributors 00038 * David Navarro, Intel Corporation - Adapt to usage in liblwm2m 00039 */ 00040 00041 00042 #include <stdlib.h> 00043 00044 #include <string.h> 00045 #include <stdio.h> 00046 00047 #include "er-coap-13.h" 00048 00049 #include "liblwm2m.h" /* for lwm2m_malloc() and lwm2m_free() */ 00050 00051 #define DEBUG 0 00052 #if DEBUG 00053 #include <stdio.h> 00054 #define PRINTF(...) printf(__VA_ARGS__) 00055 #define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) 00056 #define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]",(lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3],(lladdr)->addr[4], (lladdr)->addr[5]) 00057 #else 00058 #define PRINTF(...) 00059 #define PRINT6ADDR(addr) 00060 #define PRINTLLADDR(addr) 00061 #endif 00062 00063 /*-----------------------------------------------------------------------------------*/ 00064 /*- Variables -----------------------------------------------------------------------*/ 00065 /*-----------------------------------------------------------------------------------*/ 00066 static uint16_t current_mid = 0; 00067 00068 coap_status_t coap_error_code = NO_ERROR; 00069 const char *coap_error_message = ""; 00070 /*-----------------------------------------------------------------------------------*/ 00071 /*- LOCAL HELP FUNCTIONS ------------------------------------------------------------*/ 00072 /*-----------------------------------------------------------------------------------*/ 00073 static 00074 uint16_t 00075 coap_log_2(uint16_t value) 00076 { 00077 uint16_t result = 0; 00078 do { 00079 value = value >> 1; 00080 result++; 00081 } while (value); 00082 00083 return result ? result - 1 : result; 00084 } 00085 /*-----------------------------------------------------------------------------------*/ 00086 static 00087 uint32_t 00088 coap_parse_int_option(uint8_t *bytes, size_t length) 00089 { 00090 uint32_t var = 0; 00091 size_t i = 0; 00092 while (i<length) 00093 { 00094 var <<= 8; 00095 var |= bytes[i++]; 00096 } 00097 return var; 00098 } 00099 /*-----------------------------------------------------------------------------------*/ 00100 static 00101 uint8_t 00102 coap_option_nibble(unsigned int value) 00103 { 00104 if (value<13) 00105 { 00106 return value; 00107 } 00108 else if (value<=0xFF+13) 00109 { 00110 return 13; 00111 } 00112 else 00113 { 00114 return 14; 00115 } 00116 } 00117 /*-----------------------------------------------------------------------------------*/ 00118 static 00119 size_t 00120 coap_set_option_header(unsigned int delta, size_t length, uint8_t *buffer) 00121 { 00122 size_t written = 0; 00123 unsigned int *x = δ 00124 00125 buffer[0] = coap_option_nibble(delta)<<4 | coap_option_nibble(length); 00126 00127 /* avoids code duplication without function overhead */ 00128 do 00129 { 00130 if (*x>268) 00131 { 00132 buffer[++written] = (*x-269)>>8; 00133 buffer[++written] = (*x-269); 00134 } 00135 else if (*x>12) 00136 { 00137 buffer[++written] = (*x-13); 00138 } 00139 } 00140 while (x!=(unsigned int *)&length && (x=(unsigned int *)&length)); 00141 00142 PRINTF("WRITTEN %u B opt header\n", written); 00143 00144 return ++written; 00145 } 00146 /*-----------------------------------------------------------------------------------*/ 00147 static 00148 size_t 00149 coap_serialize_int_option(unsigned int number, unsigned int current_number, uint8_t *buffer, uint32_t value) 00150 { 00151 size_t i = 0; 00152 00153 if (0xFF000000 & value) ++i; 00154 if (0xFFFF0000 & value) ++i; 00155 if (0xFFFFFF00 & value) ++i; 00156 if (0xFFFFFFFF & value) ++i; 00157 00158 PRINTF("OPTION %u (delta %u, len %u)\n", number, number - current_number, i); 00159 00160 i = coap_set_option_header(number - current_number, i, buffer); 00161 00162 if (0xFF000000 & value) buffer[i++] = (uint8_t) (value>>24); 00163 if (0xFFFF0000 & value) buffer[i++] = (uint8_t) (value>>16); 00164 if (0xFFFFFF00 & value) buffer[i++] = (uint8_t) (value>>8); 00165 if (0xFFFFFFFF & value) buffer[i++] = (uint8_t) (value); 00166 00167 return i; 00168 } 00169 /*-----------------------------------------------------------------------------------*/ 00170 static 00171 size_t 00172 coap_serialize_array_option(unsigned int number, unsigned int current_number, uint8_t *buffer, uint8_t *array, size_t length, char split_char) 00173 { 00174 size_t i = 0; 00175 00176 if (split_char!='\0') 00177 { 00178 size_t j; 00179 uint8_t *part_start = array; 00180 uint8_t *part_end = NULL; 00181 size_t temp_length; 00182 00183 for (j = 0; j<=length; ++j) 00184 { 00185 if (array[j]==split_char || j==length) 00186 { 00187 part_end = array + j; 00188 temp_length = part_end-part_start; 00189 00190 i += coap_set_option_header(number - current_number, temp_length, &buffer[i]); 00191 memcpy(&buffer[i], part_start, temp_length); 00192 i += temp_length; 00193 00194 PRINTF("OPTION type %u, delta %u, len %u, part [%.*s]\n", number, number - current_number, i, temp_length, part_start); 00195 00196 ++j; /* skip the splitter */ 00197 current_number = number; 00198 part_start = array + j; 00199 } 00200 } /* for */ 00201 } 00202 else 00203 { 00204 i += coap_set_option_header(number - current_number, length, &buffer[i]); 00205 memcpy(&buffer[i], array, length); 00206 i += length; 00207 00208 PRINTF("OPTION type %u, delta %u, len %u\n", number, number - current_number, length); 00209 } 00210 00211 return i; 00212 } 00213 /*-----------------------------------------------------------------------------------*/ 00214 static 00215 size_t 00216 coap_serialize_multi_option(unsigned int number, unsigned int current_number, uint8_t *buffer, multi_option_t *array) 00217 { 00218 size_t i = 0; 00219 multi_option_t * j; 00220 00221 for (j = array; j != NULL; j= j->next) 00222 { 00223 i += coap_set_option_header(number - current_number, j->len, &buffer[i]); 00224 current_number = number; 00225 memcpy(&buffer[i], j->data, j->len); 00226 i += j->len; 00227 } /* for */ 00228 00229 return i; 00230 } 00231 /*-----------------------------------------------------------------------------------*/ 00232 static 00233 void 00234 coap_merge_multi_option(uint8_t **dst, size_t *dst_len, uint8_t *option, size_t option_len, char separator) 00235 { 00236 /* Merge multiple options. */ 00237 if (*dst_len > 0) 00238 { 00239 /* dst already contains an option: concatenate */ 00240 (*dst)[*dst_len] = separator; 00241 *dst_len += 1; 00242 00243 /* memmove handles 2-byte option headers */ 00244 memmove((*dst)+(*dst_len), option, option_len); 00245 00246 *dst_len += option_len; 00247 } 00248 else 00249 { 00250 /* dst is empty: set to option */ 00251 *dst = option; 00252 *dst_len = option_len; 00253 } 00254 } 00255 00256 void 00257 coap_add_multi_option(multi_option_t **dst, uint8_t *option, size_t option_len, uint8_t is_static) 00258 { 00259 multi_option_t *opt = (multi_option_t *)lwm2m_malloc(sizeof(multi_option_t)); 00260 00261 if (opt) 00262 { 00263 opt->next = NULL; 00264 opt->len = (uint8_t)option_len; 00265 if (is_static) 00266 { 00267 opt->data = option; 00268 opt->is_static = 1; 00269 } 00270 else 00271 { 00272 opt->is_static = 0; 00273 opt->data = (uint8_t *)lwm2m_malloc(option_len); 00274 if (opt->data == NULL) 00275 { 00276 lwm2m_free(opt); 00277 return; 00278 } 00279 memcpy(opt->data, option, option_len); 00280 } 00281 00282 if (*dst) 00283 { 00284 multi_option_t * i = *dst; 00285 while (i->next) 00286 { 00287 i = i->next; 00288 } 00289 i->next = opt; 00290 } 00291 else 00292 { 00293 *dst = opt; 00294 } 00295 } 00296 } 00297 00298 void 00299 free_multi_option(multi_option_t *dst) 00300 { 00301 if (dst) 00302 { 00303 multi_option_t *n = dst->next; 00304 dst->next = NULL; 00305 if (dst->is_static == 0) 00306 { 00307 lwm2m_free(dst->data); 00308 } 00309 lwm2m_free(dst); 00310 free_multi_option(n); 00311 } 00312 } 00313 00314 char * coap_get_multi_option_as_string(multi_option_t * option) 00315 { 00316 size_t len = 0; 00317 multi_option_t * opt; 00318 char * output; 00319 00320 for (opt = option; opt != NULL; opt = opt->next) 00321 { 00322 len += opt->len + 1; // for separator 00323 } 00324 00325 output = lwm2m_malloc(len + 1); // for String terminator 00326 if (output != NULL) 00327 { 00328 size_t i = 0; 00329 00330 for (opt = option; opt != NULL; opt = opt->next) 00331 { 00332 output[i] = '/'; 00333 i += 1; 00334 00335 memmove(output + i, opt->data, opt->len); 00336 i += opt->len; 00337 } 00338 output[i] = 0; 00339 } 00340 00341 return output; 00342 } 00343 00344 /*-----------------------------------------------------------------------------------*/ 00345 static 00346 int 00347 coap_get_variable(const uint8_t *buffer, size_t length, const char *name, const char **output) 00348 { 00349 const uint8_t *start = NULL; 00350 const uint8_t *end = NULL; 00351 const uint8_t *value_end = NULL; 00352 size_t name_len = 0; 00353 00354 /*initialize the output buffer first*/ 00355 *output = 0; 00356 00357 name_len = strlen(name); 00358 end = buffer + length; 00359 00360 for (start = buffer; start + name_len < end; ++start){ 00361 if ((start == buffer || start[-1] == '&') && start[name_len] == '=' && 00362 strncmp(name, (char *)start, name_len)==0) { 00363 00364 /* Point start to variable value */ 00365 start += name_len + 1; 00366 00367 /* Point end to the end of the value */ 00368 value_end = (const uint8_t *) memchr(start, '&', end - start); 00369 if (value_end == NULL) { 00370 value_end = end; 00371 } 00372 00373 *output = (char *)start; 00374 00375 return (value_end - start); 00376 } 00377 } 00378 00379 return 0; 00380 } 00381 00382 /*-----------------------------------------------------------------------------------*/ 00383 uint16_t 00384 coap_get_mid() 00385 { 00386 return ++current_mid; 00387 } 00388 /*-----------------------------------------------------------------------------------*/ 00389 /*- MEASSAGE PROCESSING -------------------------------------------------------------*/ 00390 /*-----------------------------------------------------------------------------------*/ 00391 void 00392 coap_init_message(void *packet, coap_message_type_t type, uint8_t code, uint16_t mid) 00393 { 00394 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 00395 00396 /* Important thing */ 00397 memset(coap_pkt, 0, sizeof(coap_packet_t)); 00398 00399 coap_pkt->type = type; 00400 coap_pkt->code = code; 00401 coap_pkt->mid = mid; 00402 } 00403 00404 void 00405 coap_free_header(void *packet) 00406 { 00407 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 00408 00409 free_multi_option(coap_pkt->uri_path); 00410 free_multi_option(coap_pkt->uri_query); 00411 free_multi_option(coap_pkt->location_path); 00412 coap_pkt->uri_path = NULL; 00413 coap_pkt->uri_query = NULL; 00414 coap_pkt->location_path = NULL; 00415 } 00416 00417 /*-----------------------------------------------------------------------------------*/ 00418 size_t coap_serialize_get_size(void *packet) 00419 { 00420 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 00421 size_t length = 0; 00422 00423 length = COAP_HEADER_LEN + coap_pkt->payload_len + coap_pkt->token_len; 00424 00425 if (IS_OPTION(coap_pkt, COAP_OPTION_IF_MATCH)) 00426 { 00427 length += COAP_MAX_OPTION_HEADER_LEN + coap_pkt->if_match_len; 00428 } 00429 if (IS_OPTION(coap_pkt, COAP_OPTION_URI_HOST)) 00430 { 00431 length += COAP_MAX_OPTION_HEADER_LEN + coap_pkt->uri_host_len; 00432 } 00433 if (IS_OPTION(coap_pkt, COAP_OPTION_ETAG)) 00434 { 00435 length += COAP_MAX_OPTION_HEADER_LEN + coap_pkt->etag_len; 00436 } 00437 if (IS_OPTION(coap_pkt, COAP_OPTION_IF_NONE_MATCH)) 00438 { 00439 // can be stored in extended fields 00440 length += COAP_MAX_OPTION_HEADER_LEN; 00441 } 00442 if (IS_OPTION(coap_pkt, COAP_OPTION_OBSERVE)) 00443 { 00444 // can be stored in extended fields 00445 length += COAP_MAX_OPTION_HEADER_LEN; 00446 } 00447 if (IS_OPTION(coap_pkt, COAP_OPTION_URI_PORT)) 00448 { 00449 // can be stored in extended fields 00450 length += COAP_MAX_OPTION_HEADER_LEN; 00451 } 00452 if (IS_OPTION(coap_pkt, COAP_OPTION_LOCATION_PATH)) 00453 { 00454 multi_option_t * optP; 00455 00456 for (optP = coap_pkt->location_path ; optP != NULL ; optP = optP->next) 00457 { 00458 length += COAP_MAX_OPTION_HEADER_LEN + optP->len; 00459 } 00460 } 00461 if (IS_OPTION(coap_pkt, COAP_OPTION_URI_PATH)) 00462 { 00463 multi_option_t * optP; 00464 00465 for (optP = coap_pkt->uri_path ; optP != NULL ; optP = optP->next) 00466 { 00467 length += COAP_MAX_OPTION_HEADER_LEN + optP->len; 00468 } 00469 } 00470 if (IS_OPTION(coap_pkt, COAP_OPTION_CONTENT_TYPE)) 00471 { 00472 // can be stored in extended fields 00473 length += COAP_MAX_OPTION_HEADER_LEN; 00474 } 00475 if (IS_OPTION(coap_pkt, COAP_OPTION_MAX_AGE)) 00476 { 00477 // can be stored in extended fields 00478 length += COAP_MAX_OPTION_HEADER_LEN; 00479 } 00480 if (IS_OPTION(coap_pkt, COAP_OPTION_URI_QUERY)) 00481 { 00482 multi_option_t * optP; 00483 00484 for (optP = coap_pkt->uri_query ; optP != NULL ; optP = optP->next) 00485 { 00486 length += COAP_MAX_OPTION_HEADER_LEN + optP->len; 00487 } 00488 } 00489 if (IS_OPTION(coap_pkt, COAP_OPTION_ACCEPT)) 00490 { 00491 length += coap_pkt->accept_num * COAP_MAX_OPTION_HEADER_LEN; 00492 } 00493 if (IS_OPTION(coap_pkt, COAP_OPTION_LOCATION_QUERY)) 00494 { 00495 length += COAP_MAX_OPTION_HEADER_LEN + coap_pkt->location_query_len; 00496 } 00497 if (IS_OPTION(coap_pkt, COAP_OPTION_BLOCK2)) 00498 { 00499 // can be stored in extended fields 00500 length += COAP_MAX_OPTION_HEADER_LEN; 00501 } 00502 if (IS_OPTION(coap_pkt, COAP_OPTION_BLOCK1)) 00503 { 00504 // can be stored in extended fields 00505 length += COAP_MAX_OPTION_HEADER_LEN; 00506 } 00507 if (IS_OPTION(coap_pkt, COAP_OPTION_SIZE)) 00508 { 00509 // can be stored in extended fields 00510 length += COAP_MAX_OPTION_HEADER_LEN; 00511 } 00512 if (IS_OPTION(coap_pkt, COAP_OPTION_PROXY_URI)) 00513 { 00514 length += COAP_MAX_OPTION_HEADER_LEN + coap_pkt->proxy_uri_len; 00515 } 00516 00517 return length; 00518 } 00519 00520 /*-----------------------------------------------------------------------------------*/ 00521 size_t 00522 coap_serialize_message(void *packet, uint8_t *buffer) 00523 { 00524 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 00525 uint8_t *option; 00526 unsigned int current_number = 0; 00527 00528 /* Initialize */ 00529 coap_pkt->buffer = buffer; 00530 coap_pkt->version = 1; 00531 00532 PRINTF("-Serializing MID %u to %p, ", coap_pkt->mid, coap_pkt->buffer); 00533 00534 /* set header fields */ 00535 coap_pkt->buffer[0] = 0x00; 00536 coap_pkt->buffer[0] |= COAP_HEADER_VERSION_MASK & (coap_pkt->version)<<COAP_HEADER_VERSION_POSITION; 00537 coap_pkt->buffer[0] |= COAP_HEADER_TYPE_MASK & (coap_pkt->type)<<COAP_HEADER_TYPE_POSITION; 00538 coap_pkt->buffer[0] |= COAP_HEADER_TOKEN_LEN_MASK & (coap_pkt->token_len)<<COAP_HEADER_TOKEN_LEN_POSITION; 00539 coap_pkt->buffer[1] = coap_pkt->code; 00540 coap_pkt->buffer[2] = (uint8_t) ((coap_pkt->mid)>>8); 00541 coap_pkt->buffer[3] = (uint8_t) (coap_pkt->mid); 00542 00543 /* set Token */ 00544 PRINTF("Token (len %u)", coap_pkt->token_len); 00545 option = coap_pkt->buffer + COAP_HEADER_LEN; 00546 for (current_number=0; current_number<coap_pkt->token_len; ++current_number) 00547 { 00548 PRINTF(" %02X", coap_pkt->token[current_number]); 00549 *option = coap_pkt->token[current_number]; 00550 ++option; 00551 } 00552 PRINTF("-\n"); 00553 00554 /* Serialize options */ 00555 current_number = 0; 00556 00557 PRINTF("-Serializing options at %p-\n", option); 00558 00559 /* The options must be serialized in the order of their number */ 00560 COAP_SERIALIZE_BYTE_OPTION( COAP_OPTION_IF_MATCH, if_match, "If-Match") 00561 COAP_SERIALIZE_STRING_OPTION( COAP_OPTION_URI_HOST, uri_host, '\0', "Uri-Host") 00562 COAP_SERIALIZE_BYTE_OPTION( COAP_OPTION_ETAG, etag, "ETag") 00563 COAP_SERIALIZE_INT_OPTION( COAP_OPTION_IF_NONE_MATCH, content_type-coap_pkt->content_type, "If-None-Match") /* hack to get a zero field */ 00564 COAP_SERIALIZE_INT_OPTION( COAP_OPTION_OBSERVE, observe, "Observe") 00565 COAP_SERIALIZE_INT_OPTION( COAP_OPTION_URI_PORT, uri_port, "Uri-Port") 00566 COAP_SERIALIZE_MULTI_OPTION( COAP_OPTION_LOCATION_PATH, location_path, "Location-Path") 00567 COAP_SERIALIZE_MULTI_OPTION( COAP_OPTION_URI_PATH, uri_path, "Uri-Path") 00568 COAP_SERIALIZE_INT_OPTION( COAP_OPTION_CONTENT_TYPE, content_type, "Content-Format") 00569 COAP_SERIALIZE_INT_OPTION( COAP_OPTION_MAX_AGE, max_age, "Max-Age") 00570 COAP_SERIALIZE_MULTI_OPTION( COAP_OPTION_URI_QUERY, uri_query, "Uri-Query") 00571 COAP_SERIALIZE_ACCEPT_OPTION( COAP_OPTION_ACCEPT, accept, "Accept") 00572 COAP_SERIALIZE_STRING_OPTION( COAP_OPTION_LOCATION_QUERY, location_query, '&', "Location-Query") 00573 COAP_SERIALIZE_BLOCK_OPTION( COAP_OPTION_BLOCK2, block2, "Block2") 00574 COAP_SERIALIZE_BLOCK_OPTION( COAP_OPTION_BLOCK1, block1, "Block1") 00575 COAP_SERIALIZE_INT_OPTION( COAP_OPTION_SIZE, size, "Size") 00576 COAP_SERIALIZE_STRING_OPTION( COAP_OPTION_PROXY_URI, proxy_uri, '\0', "Proxy-Uri") 00577 00578 PRINTF("-Done serializing at %p----\n", option); 00579 00580 /* Free allocated header fields */ 00581 coap_free_header(packet); 00582 00583 /* Pack payload */ 00584 /* Payload marker */ 00585 if (coap_pkt->payload_len) 00586 { 00587 *option = 0xFF; 00588 ++option; 00589 } 00590 00591 memmove(option, coap_pkt->payload, coap_pkt->payload_len); 00592 00593 PRINTF("-Done %u B (header len %u, payload len %u)-\n", coap_pkt->payload_len + option - buffer, option - buffer, coap_pkt->payload_len); 00594 00595 PRINTF("Dump [0x%02X %02X %02X %02X %02X %02X %02X %02X]\n", 00596 coap_pkt->buffer[0], 00597 coap_pkt->buffer[1], 00598 coap_pkt->buffer[2], 00599 coap_pkt->buffer[3], 00600 coap_pkt->buffer[4], 00601 coap_pkt->buffer[5], 00602 coap_pkt->buffer[6], 00603 coap_pkt->buffer[7] 00604 ); 00605 00606 return (option - buffer) + coap_pkt->payload_len; /* packet length */ 00607 } 00608 /*-----------------------------------------------------------------------------------*/ 00609 coap_status_t 00610 coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) 00611 { 00612 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 00613 uint8_t *current_option; 00614 unsigned int option_number = 0; 00615 unsigned int option_delta = 0; 00616 size_t option_length = 0; 00617 unsigned int *x; 00618 00619 /* Initialize packet */ 00620 memset(coap_pkt, 0, sizeof(coap_packet_t)); 00621 00622 /* pointer to packet bytes */ 00623 coap_pkt->buffer = data; 00624 00625 /* parse header fields */ 00626 coap_pkt->version = (COAP_HEADER_VERSION_MASK & coap_pkt->buffer[0])>>COAP_HEADER_VERSION_POSITION; 00627 coap_pkt->type = (COAP_HEADER_TYPE_MASK & coap_pkt->buffer[0])>>COAP_HEADER_TYPE_POSITION; 00628 coap_pkt->token_len = MIN(COAP_TOKEN_LEN, (COAP_HEADER_TOKEN_LEN_MASK & coap_pkt->buffer[0])>>COAP_HEADER_TOKEN_LEN_POSITION); 00629 coap_pkt->code = coap_pkt->buffer[1]; 00630 coap_pkt->mid = coap_pkt->buffer[2]<<8 | coap_pkt->buffer[3]; 00631 00632 if (coap_pkt->version != 1) 00633 { 00634 coap_error_message = "CoAP version must be 1"; 00635 return BAD_REQUEST_4_00; 00636 } 00637 00638 current_option = data + COAP_HEADER_LEN; 00639 00640 if (coap_pkt->token_len != 0) 00641 { 00642 memcpy(coap_pkt->token, current_option, coap_pkt->token_len); 00643 SET_OPTION(coap_pkt, COAP_OPTION_TOKEN); 00644 00645 PRINTF("Token (len %u) [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", coap_pkt->token_len, 00646 coap_pkt->token[0], 00647 coap_pkt->token[1], 00648 coap_pkt->token[2], 00649 coap_pkt->token[3], 00650 coap_pkt->token[4], 00651 coap_pkt->token[5], 00652 coap_pkt->token[6], 00653 coap_pkt->token[7] 00654 ); /*FIXME always prints 8 bytes */ 00655 } 00656 00657 /* parse options */ 00658 current_option += coap_pkt->token_len; 00659 00660 while (current_option < data+data_len) 00661 { 00662 /* Payload marker 0xFF, currently only checking for 0xF* because rest is reserved */ 00663 if ((current_option[0] & 0xF0)==0xF0) 00664 { 00665 coap_pkt->payload = ++current_option; 00666 coap_pkt->payload_len = data_len - (coap_pkt->payload - data); 00667 00668 break; 00669 } 00670 00671 option_delta = current_option[0]>>4; 00672 option_length = current_option[0] & 0x0F; 00673 ++current_option; 00674 00675 /* avoids code duplication without function overhead */ 00676 x = &option_delta; 00677 do 00678 { 00679 if (*x==13) 00680 { 00681 *x += current_option[0]; 00682 ++current_option; 00683 } 00684 else if (*x==14) 00685 { 00686 *x += 255; 00687 *x += current_option[0]<<8; 00688 ++current_option; 00689 *x += current_option[0]; 00690 ++current_option; 00691 } 00692 } 00693 while (x!=(unsigned int *)&option_length && (x=(unsigned int *)&option_length)); 00694 00695 option_number += option_delta; 00696 00697 PRINTF("OPTION %u (delta %u, len %u): ", option_number, option_delta, option_length); 00698 00699 SET_OPTION(coap_pkt, option_number); 00700 00701 switch (option_number) 00702 { 00703 case COAP_OPTION_CONTENT_TYPE: 00704 coap_pkt->content_type = coap_parse_int_option(current_option, option_length); 00705 PRINTF("Content-Format [%u]\n", coap_pkt->content_type); 00706 break; 00707 case COAP_OPTION_MAX_AGE: 00708 coap_pkt->max_age = coap_parse_int_option(current_option, option_length); 00709 PRINTF("Max-Age [%lu]\n", coap_pkt->max_age); 00710 break; 00711 case COAP_OPTION_ETAG: 00712 coap_pkt->etag_len = (uint8_t)(MIN(COAP_ETAG_LEN, option_length)); 00713 memcpy(coap_pkt->etag, current_option, coap_pkt->etag_len); 00714 PRINTF("ETag %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", coap_pkt->etag_len, 00715 coap_pkt->etag[0], 00716 coap_pkt->etag[1], 00717 coap_pkt->etag[2], 00718 coap_pkt->etag[3], 00719 coap_pkt->etag[4], 00720 coap_pkt->etag[5], 00721 coap_pkt->etag[6], 00722 coap_pkt->etag[7] 00723 ); /*FIXME always prints 8 bytes */ 00724 break; 00725 case COAP_OPTION_ACCEPT: 00726 if (coap_pkt->accept_num < COAP_MAX_ACCEPT_NUM) 00727 { 00728 coap_pkt->accept[coap_pkt->accept_num] = coap_parse_int_option(current_option, option_length); 00729 coap_pkt->accept_num += 1; 00730 PRINTF("Accept [%u]\n", coap_pkt->content_type); 00731 } 00732 break; 00733 case COAP_OPTION_IF_MATCH: 00734 /*FIXME support multiple ETags */ 00735 coap_pkt->if_match_len = (uint8_t)(MIN(COAP_ETAG_LEN, option_length)); 00736 memcpy(coap_pkt->if_match, current_option, coap_pkt->if_match_len); 00737 PRINTF("If-Match %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", coap_pkt->if_match_len, 00738 coap_pkt->if_match[0], 00739 coap_pkt->if_match[1], 00740 coap_pkt->if_match[2], 00741 coap_pkt->if_match[3], 00742 coap_pkt->if_match[4], 00743 coap_pkt->if_match[5], 00744 coap_pkt->if_match[6], 00745 coap_pkt->if_match[7] 00746 ); /*FIXME always prints 8 bytes */ 00747 break; 00748 case COAP_OPTION_IF_NONE_MATCH: 00749 coap_pkt->if_none_match = 1; 00750 PRINTF("If-None-Match\n"); 00751 break; 00752 00753 case COAP_OPTION_URI_HOST: 00754 coap_pkt->uri_host = current_option; 00755 coap_pkt->uri_host_len = option_length; 00756 PRINTF("Uri-Host [%.*s]\n", coap_pkt->uri_host_len, coap_pkt->uri_host); 00757 break; 00758 case COAP_OPTION_URI_PORT: 00759 coap_pkt->uri_port = coap_parse_int_option(current_option, option_length); 00760 PRINTF("Uri-Port [%u]\n", coap_pkt->uri_port); 00761 break; 00762 case COAP_OPTION_URI_PATH: 00763 /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */ 00764 // coap_merge_multi_option( (char **) &(coap_pkt->uri_path), &(coap_pkt->uri_path_len), current_option, option_length, 0); 00765 coap_add_multi_option( &(coap_pkt->uri_path), current_option, option_length, 1); 00766 PRINTF("Uri-Path [%.*s]\n", option_length, current_option); 00767 break; 00768 case COAP_OPTION_URI_QUERY: 00769 /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */ 00770 // coap_merge_multi_option( (char **) &(coap_pkt->uri_query), &(coap_pkt->uri_query_len), current_option, option_length, '&'); 00771 coap_add_multi_option( &(coap_pkt->uri_query), current_option, option_length, 1); 00772 PRINTF("Uri-Query [%.*s]\n", option_length, current_option); 00773 break; 00774 00775 case COAP_OPTION_LOCATION_PATH: 00776 coap_add_multi_option( &(coap_pkt->location_path), current_option, option_length, 1); 00777 break; 00778 case COAP_OPTION_LOCATION_QUERY: 00779 /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */ 00780 coap_merge_multi_option( &(coap_pkt->location_query), &(coap_pkt->location_query_len), current_option, option_length, '&'); 00781 PRINTF("Location-Query [%.*s]\n", option_length, current_option); 00782 break; 00783 00784 case COAP_OPTION_PROXY_URI: 00785 /*FIXME check for own end-point */ 00786 coap_pkt->proxy_uri = current_option; 00787 coap_pkt->proxy_uri_len = option_length; 00788 /*TODO length > 270 not implemented (actually not required) */ 00789 PRINTF("Proxy-Uri NOT IMPLEMENTED [%.*s]\n", coap_pkt->proxy_uri_len, coap_pkt->proxy_uri); 00790 coap_error_message = "This is a constrained server (Contiki)"; 00791 return PROXYING_NOT_SUPPORTED_5_05; 00792 break; 00793 00794 case COAP_OPTION_OBSERVE: 00795 coap_pkt->observe = coap_parse_int_option(current_option, option_length); 00796 PRINTF("Observe [%lu]\n", coap_pkt->observe); 00797 break; 00798 case COAP_OPTION_BLOCK2: 00799 coap_pkt->block2_num = coap_parse_int_option(current_option, option_length); 00800 coap_pkt->block2_more = (coap_pkt->block2_num & 0x08)>>3; 00801 coap_pkt->block2_size = 16 << (coap_pkt->block2_num & 0x07); 00802 coap_pkt->block2_offset = (coap_pkt->block2_num & ~0x0000000F)<<(coap_pkt->block2_num & 0x07); 00803 coap_pkt->block2_num >>= 4; 00804 PRINTF("Block2 [%lu%s (%u B/blk)]\n", coap_pkt->block2_num, coap_pkt->block2_more ? "+" : "", coap_pkt->block2_size); 00805 break; 00806 case COAP_OPTION_BLOCK1: 00807 coap_pkt->block1_num = coap_parse_int_option(current_option, option_length); 00808 coap_pkt->block1_more = (coap_pkt->block1_num & 0x08)>>3; 00809 coap_pkt->block1_size = 16 << (coap_pkt->block1_num & 0x07); 00810 coap_pkt->block1_offset = (coap_pkt->block1_num & ~0x0000000F)<<(coap_pkt->block1_num & 0x07); 00811 coap_pkt->block1_num >>= 4; 00812 PRINTF("Block1 [%lu%s (%u B/blk)]\n", coap_pkt->block1_num, coap_pkt->block1_more ? "+" : "", coap_pkt->block1_size); 00813 break; 00814 case COAP_OPTION_SIZE: 00815 coap_pkt->size = coap_parse_int_option(current_option, option_length); 00816 PRINTF("Size [%lu]\n", coap_pkt->size); 00817 break; 00818 default: 00819 PRINTF("unknown (%u)\n", option_number); 00820 /* Check if critical (odd) */ 00821 if (option_number & 1) 00822 { 00823 coap_error_message = "Unsupported critical option"; 00824 return BAD_OPTION_4_02; 00825 } 00826 } 00827 00828 current_option += option_length; 00829 } /* for */ 00830 PRINTF("-Done parsing-------\n"); 00831 00832 00833 00834 return NO_ERROR; 00835 } 00836 /*-----------------------------------------------------------------------------------*/ 00837 /*- REST FRAMEWORK FUNCTIONS --------------------------------------------------------*/ 00838 /*-----------------------------------------------------------------------------------*/ 00839 int 00840 coap_get_query_variable(void *packet, const char *name, const char **output) 00841 { 00842 /* 00843 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 00844 00845 if (IS_OPTION(coap_pkt, COAP_OPTION_URI_QUERY)) { 00846 return coap_get_variable(coap_pkt->uri_query, coap_pkt->uri_query_len, name, output); 00847 } 00848 */ 00849 return 0; 00850 } 00851 00852 int 00853 coap_get_post_variable(void *packet, const char *name, const char **output) 00854 { 00855 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 00856 00857 if (coap_pkt->payload_len) { 00858 return coap_get_variable(coap_pkt->payload, coap_pkt->payload_len, name, output); 00859 } 00860 return 0; 00861 } 00862 /*-----------------------------------------------------------------------------------*/ 00863 int 00864 coap_set_status_code(void *packet, unsigned int code) 00865 { 00866 if (code <= 0xFF) 00867 { 00868 ((coap_packet_t *)packet)->code = (uint8_t) code; 00869 return 1; 00870 } 00871 else 00872 { 00873 return 0; 00874 } 00875 } 00876 /*-----------------------------------------------------------------------------------*/ 00877 /*- HEADER OPTION GETTERS AND SETTERS -----------------------------------------------*/ 00878 /*-----------------------------------------------------------------------------------*/ 00879 unsigned int 00880 coap_get_header_content_type(void *packet) 00881 { 00882 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 00883 00884 if (!IS_OPTION(coap_pkt, COAP_OPTION_CONTENT_TYPE)) return -1; 00885 00886 return coap_pkt->content_type; 00887 } 00888 00889 int 00890 coap_set_header_content_type(void *packet, unsigned int content_type) 00891 { 00892 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 00893 00894 coap_pkt->content_type = (coap_content_type_t) content_type; 00895 SET_OPTION(coap_pkt, COAP_OPTION_CONTENT_TYPE); 00896 return 1; 00897 } 00898 /*-----------------------------------------------------------------------------------*/ 00899 int 00900 coap_get_header_accept(void *packet, const uint16_t **accept) 00901 { 00902 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 00903 00904 if (!IS_OPTION(coap_pkt, COAP_OPTION_ACCEPT)) return 0; 00905 00906 *accept = coap_pkt->accept; 00907 return coap_pkt->accept_num; 00908 } 00909 00910 int 00911 coap_set_header_accept(void *packet, uint16_t accept) 00912 { 00913 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 00914 00915 if (coap_pkt->accept_num < COAP_MAX_ACCEPT_NUM) 00916 { 00917 coap_pkt->accept[coap_pkt->accept_num] = accept; 00918 coap_pkt->accept_num += 1; 00919 00920 SET_OPTION(coap_pkt, COAP_OPTION_ACCEPT); 00921 } 00922 return coap_pkt->accept_num; 00923 } 00924 /*-----------------------------------------------------------------------------------*/ 00925 int 00926 coap_get_header_max_age(void *packet, uint32_t *age) 00927 { 00928 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 00929 00930 if (!IS_OPTION(coap_pkt, COAP_OPTION_MAX_AGE)) { 00931 *age = COAP_DEFAULT_MAX_AGE; 00932 } else { 00933 *age = coap_pkt->max_age; 00934 } 00935 return 1; 00936 } 00937 00938 int 00939 coap_set_header_max_age(void *packet, uint32_t age) 00940 { 00941 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 00942 00943 coap_pkt->max_age = age; 00944 SET_OPTION(coap_pkt, COAP_OPTION_MAX_AGE); 00945 return 1; 00946 } 00947 /*-----------------------------------------------------------------------------------*/ 00948 int 00949 coap_get_header_etag(void *packet, const uint8_t **etag) 00950 { 00951 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 00952 00953 if (!IS_OPTION(coap_pkt, COAP_OPTION_ETAG)) return 0; 00954 00955 *etag = coap_pkt->etag; 00956 return coap_pkt->etag_len; 00957 } 00958 00959 int 00960 coap_set_header_etag(void *packet, const uint8_t *etag, size_t etag_len) 00961 { 00962 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 00963 00964 coap_pkt->etag_len = (uint8_t)(MIN(COAP_ETAG_LEN, etag_len)); 00965 memcpy(coap_pkt->etag, etag, coap_pkt->etag_len); 00966 00967 SET_OPTION(coap_pkt, COAP_OPTION_ETAG); 00968 return coap_pkt->etag_len; 00969 } 00970 /*-----------------------------------------------------------------------------------*/ 00971 /*FIXME support multiple ETags */ 00972 int 00973 coap_get_header_if_match(void *packet, const uint8_t **etag) 00974 { 00975 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 00976 00977 if (!IS_OPTION(coap_pkt, COAP_OPTION_IF_MATCH)) return 0; 00978 00979 *etag = coap_pkt->if_match; 00980 return coap_pkt->if_match_len; 00981 } 00982 00983 int 00984 coap_set_header_if_match(void *packet, const uint8_t *etag, size_t etag_len) 00985 { 00986 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 00987 00988 coap_pkt->if_match_len = (uint8_t)(MIN(COAP_ETAG_LEN, etag_len)); 00989 memcpy(coap_pkt->if_match, etag, coap_pkt->if_match_len); 00990 00991 SET_OPTION(coap_pkt, COAP_OPTION_IF_MATCH); 00992 return coap_pkt->if_match_len; 00993 } 00994 /*-----------------------------------------------------------------------------------*/ 00995 int 00996 coap_get_header_if_none_match(void *packet) 00997 { 00998 return IS_OPTION((coap_packet_t *)packet, COAP_OPTION_IF_NONE_MATCH) ? 1 : 0; 00999 } 01000 01001 int 01002 coap_set_header_if_none_match(void *packet) 01003 { 01004 SET_OPTION((coap_packet_t *)packet, COAP_OPTION_IF_NONE_MATCH); 01005 return 1; 01006 } 01007 /*-----------------------------------------------------------------------------------*/ 01008 int 01009 coap_get_header_token(void *packet, const uint8_t **token) 01010 { 01011 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 01012 01013 if (!IS_OPTION(coap_pkt, COAP_OPTION_TOKEN)) return 0; 01014 01015 *token = coap_pkt->token; 01016 return coap_pkt->token_len; 01017 } 01018 01019 int 01020 coap_set_header_token(void *packet, const uint8_t *token, size_t token_len) 01021 { 01022 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 01023 01024 coap_pkt->token_len = (uint8_t)(MIN(COAP_TOKEN_LEN, token_len)); 01025 memcpy(coap_pkt->token, token, coap_pkt->token_len); 01026 01027 SET_OPTION(coap_pkt, COAP_OPTION_TOKEN); 01028 return coap_pkt->token_len; 01029 } 01030 /*-----------------------------------------------------------------------------------*/ 01031 int 01032 coap_get_header_proxy_uri(void *packet, const char **uri) 01033 { 01034 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 01035 01036 if (!IS_OPTION(coap_pkt, COAP_OPTION_PROXY_URI)) return 0; 01037 01038 *uri = (const char *)coap_pkt->proxy_uri; 01039 return coap_pkt->proxy_uri_len; 01040 } 01041 01042 int 01043 coap_set_header_proxy_uri(void *packet, const char *uri) 01044 { 01045 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 01046 01047 coap_pkt->proxy_uri = (uint8_t *)uri; 01048 coap_pkt->proxy_uri_len = strlen(uri); 01049 01050 SET_OPTION(coap_pkt, COAP_OPTION_PROXY_URI); 01051 return coap_pkt->proxy_uri_len; 01052 } 01053 /*-----------------------------------------------------------------------------------*/ 01054 int 01055 coap_get_header_uri_host(void *packet, const char **host) 01056 { 01057 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 01058 01059 if (!IS_OPTION(coap_pkt, COAP_OPTION_URI_HOST)) return 0; 01060 01061 *host = (char *)coap_pkt->uri_host; 01062 return coap_pkt->uri_host_len; 01063 } 01064 01065 int 01066 coap_set_header_uri_host(void *packet, const char *host) 01067 { 01068 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 01069 01070 coap_pkt->uri_host = (uint8_t *)host; 01071 coap_pkt->uri_host_len = strlen(host); 01072 01073 SET_OPTION(coap_pkt, COAP_OPTION_URI_HOST); 01074 return coap_pkt->uri_host_len; 01075 } 01076 /*-----------------------------------------------------------------------------------*/ 01077 int 01078 coap_get_header_uri_path(void *packet, const char **path) 01079 { 01080 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 01081 01082 if (!IS_OPTION(coap_pkt, COAP_OPTION_URI_PATH)) return 0; 01083 01084 *path = NULL; //coap_pkt->uri_path; 01085 return 0; //coap_pkt->uri_path_len; 01086 } 01087 01088 int 01089 coap_set_header_uri_path(void *packet, const char *path) 01090 { 01091 coap_packet_t *coap_pkt = (coap_packet_t *) packet; 01092 int length = 0; 01093 01094 free_multi_option(coap_pkt->uri_path); 01095 coap_pkt->uri_path = NULL; 01096 01097 if (path[0]=='/') ++path; 01098 01099 do 01100 { 01101 int i = 0; 01102 01103 while (path[i] != 0 && path[i] != '/') i++; 01104 coap_add_multi_option(&(coap_pkt->uri_path), (uint8_t *)path, i, 0); 01105 01106 if (path[i] == '/') i++; 01107 path += i; 01108 length += i; 01109 } while (path[0] != 0); 01110 01111 SET_OPTION(coap_pkt, COAP_OPTION_URI_PATH); 01112 return length; 01113 } 01114 01115 int 01116 coap_set_header_uri_path_segment(void *packet, const char *segment) 01117 { 01118 coap_packet_t *coap_pkt = (coap_packet_t *) packet; 01119 int length; 01120 01121 if (segment == NULL || segment[0] == 0) 01122 { 01123 coap_add_multi_option(&(coap_pkt->uri_path), NULL, 0, 1); 01124 length = 0; 01125 } 01126 else 01127 { 01128 length = strlen(segment); 01129 coap_add_multi_option(&(coap_pkt->uri_path), (uint8_t *)segment, length, 0); 01130 } 01131 01132 SET_OPTION(coap_pkt, COAP_OPTION_URI_PATH); 01133 return length; 01134 } 01135 /*-----------------------------------------------------------------------------------*/ 01136 int 01137 coap_get_header_uri_query(void *packet, const char **query) 01138 { 01139 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 01140 01141 if (!IS_OPTION(coap_pkt, COAP_OPTION_URI_QUERY)) return 0; 01142 01143 *query = NULL; //coap_pkt->uri_query; 01144 return 0; //coap_pkt->uri_query_len; 01145 } 01146 01147 int 01148 coap_set_header_uri_query(void *packet, const char *query) 01149 { 01150 int length = 0; 01151 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 01152 01153 free_multi_option(coap_pkt->uri_query); 01154 coap_pkt->uri_query = NULL; 01155 01156 if (query[0]=='?') ++query; 01157 01158 do 01159 { 01160 int i = 0; 01161 01162 while (query[i] != 0 && query[i] != '&') i++; 01163 coap_add_multi_option(&(coap_pkt->uri_query), (uint8_t *)query, i, 0); 01164 01165 if (query[i] == '&') i++; 01166 query += i; 01167 length += i; 01168 } while (query[0] != 0); 01169 01170 SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY); 01171 return length; 01172 } 01173 /*-----------------------------------------------------------------------------------*/ 01174 int 01175 coap_get_header_location_path(void *packet, const char **path) 01176 { 01177 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 01178 01179 if (!IS_OPTION(coap_pkt, COAP_OPTION_LOCATION_PATH)) return 0; 01180 01181 *path = NULL; //coap_pkt->location_path; 01182 return 0; //coap_pkt->location_path_len; 01183 } 01184 01185 int 01186 coap_set_header_location_path(void *packet, const char *path) 01187 { 01188 coap_packet_t *coap_pkt = (coap_packet_t *) packet; 01189 int length = 0; 01190 01191 free_multi_option(coap_pkt->location_path); 01192 coap_pkt->location_path = NULL; 01193 01194 if (path[0]=='/') ++path; 01195 01196 do 01197 { 01198 int i = 0; 01199 01200 while (path[i] != 0 && path[i] != '/') i++; 01201 coap_add_multi_option(&(coap_pkt->location_path), (uint8_t *)path, i, 0); 01202 01203 if (path[i] == '/') i++; 01204 path += i; 01205 length += i; 01206 } while (path[0] != 0); 01207 01208 SET_OPTION(coap_pkt, COAP_OPTION_LOCATION_PATH); 01209 return length; 01210 } 01211 /*-----------------------------------------------------------------------------------*/ 01212 int 01213 coap_get_header_location_query(void *packet, const char **query) 01214 { 01215 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 01216 01217 if (!IS_OPTION(coap_pkt, COAP_OPTION_LOCATION_QUERY)) return 0; 01218 01219 *query = (const char*)coap_pkt->location_query; 01220 return coap_pkt->location_query_len; 01221 } 01222 01223 int 01224 coap_set_header_location_query(void *packet, char *query) 01225 { 01226 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 01227 01228 while (query[0]=='?') ++query; 01229 01230 coap_pkt->location_query = (uint8_t *)query; 01231 coap_pkt->location_query_len = strlen(query); 01232 01233 SET_OPTION(coap_pkt, COAP_OPTION_LOCATION_QUERY); 01234 return coap_pkt->location_query_len; 01235 } 01236 /*-----------------------------------------------------------------------------------*/ 01237 int 01238 coap_get_header_observe(void *packet, uint32_t *observe) 01239 { 01240 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 01241 01242 if (!IS_OPTION(coap_pkt, COAP_OPTION_OBSERVE)) return 0; 01243 01244 *observe = coap_pkt->observe; 01245 return 1; 01246 } 01247 01248 int 01249 coap_set_header_observe(void *packet, uint32_t observe) 01250 { 01251 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 01252 01253 coap_pkt->observe = 0x00FFFFFF & observe; 01254 SET_OPTION(coap_pkt, COAP_OPTION_OBSERVE); 01255 return 1; 01256 } 01257 /*-----------------------------------------------------------------------------------*/ 01258 int 01259 coap_get_header_block2(void *packet, uint32_t *num, uint8_t *more, uint16_t *size, uint32_t *offset) 01260 { 01261 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 01262 01263 if (!IS_OPTION(coap_pkt, COAP_OPTION_BLOCK2)) return 0; 01264 01265 /* pointers may be NULL to get only specific block parameters */ 01266 if (num!=NULL) *num = coap_pkt->block2_num; 01267 if (more!=NULL) *more = coap_pkt->block2_more; 01268 if (size!=NULL) *size = coap_pkt->block2_size; 01269 if (offset!=NULL) *offset = coap_pkt->block2_offset; 01270 01271 return 1; 01272 } 01273 01274 int 01275 coap_set_header_block2(void *packet, uint32_t num, uint8_t more, uint16_t size) 01276 { 01277 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 01278 01279 if (size<16) return 0; 01280 if (size>2048) return 0; 01281 if (num>0x0FFFFF) return 0; 01282 01283 coap_pkt->block2_num = num; 01284 coap_pkt->block2_more = more ? 1 : 0; 01285 coap_pkt->block2_size = size; 01286 01287 SET_OPTION(coap_pkt, COAP_OPTION_BLOCK2); 01288 return 1; 01289 } 01290 /*-----------------------------------------------------------------------------------*/ 01291 int 01292 coap_get_header_block1(void *packet, uint32_t *num, uint8_t *more, uint16_t *size, uint32_t *offset) 01293 { 01294 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 01295 01296 if (!IS_OPTION(coap_pkt, COAP_OPTION_BLOCK1)) return 0; 01297 01298 /* pointers may be NULL to get only specific block parameters */ 01299 if (num!=NULL) *num = coap_pkt->block1_num; 01300 if (more!=NULL) *more = coap_pkt->block1_more; 01301 if (size!=NULL) *size = coap_pkt->block1_size; 01302 if (offset!=NULL) *offset = coap_pkt->block1_offset; 01303 01304 return 1; 01305 } 01306 01307 int 01308 coap_set_header_block1(void *packet, uint32_t num, uint8_t more, uint16_t size) 01309 { 01310 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 01311 01312 if (size<16) return 0; 01313 if (size>2048) return 0; 01314 if (num>0x0FFFFF) return 0; 01315 01316 coap_pkt->block1_num = num; 01317 coap_pkt->block1_more = more; 01318 coap_pkt->block1_size = size; 01319 01320 SET_OPTION(coap_pkt, COAP_OPTION_BLOCK1); 01321 return 1; 01322 } 01323 /*-----------------------------------------------------------------------------------*/ 01324 int 01325 coap_get_header_size(void *packet, uint32_t *size) 01326 { 01327 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 01328 01329 if (!IS_OPTION(coap_pkt, COAP_OPTION_SIZE)) return 0; 01330 01331 *size = coap_pkt->size; 01332 return 1; 01333 } 01334 01335 int 01336 coap_set_header_size(void *packet, uint32_t size) 01337 { 01338 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 01339 01340 coap_pkt->size = size; 01341 SET_OPTION(coap_pkt, COAP_OPTION_SIZE); 01342 return 1; 01343 } 01344 /*-----------------------------------------------------------------------------------*/ 01345 /*- PAYLOAD -------------------------------------------------------------------------*/ 01346 /*-----------------------------------------------------------------------------------*/ 01347 int 01348 coap_get_payload(void *packet, const uint8_t **payload) 01349 { 01350 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 01351 01352 if (coap_pkt->payload) { 01353 *payload = coap_pkt->payload; 01354 return coap_pkt->payload_len; 01355 } else { 01356 *payload = NULL; 01357 return 0; 01358 } 01359 } 01360 01361 int 01362 coap_set_payload(void *packet, const void *payload, size_t length) 01363 { 01364 coap_packet_t *const coap_pkt = (coap_packet_t *) packet; 01365 01366 coap_pkt->payload = (uint8_t *) payload; 01367 coap_pkt->payload_len = (uint16_t)(length); 01368 01369 return coap_pkt->payload_len; 01370 } 01371 /*-----------------------------------------------------------------------------------*/
Generated on Thu Jul 14 2022 09:09:49 by
1.7.2