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.h
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 #ifndef COAP_13_H_ 00043 #define COAP_13_H_ 00044 00045 #include <stdint.h> 00046 #include <stddef.h> /* for size_t */ 00047 00048 /* 00049 * The maximum buffer size that is provided for resource responses and must be respected due to the limited IP buffer. 00050 * Larger data must be handled by the resource and will be sent chunk-wise through a TCP stream or CoAP blocks. 00051 */ 00052 #ifndef REST_MAX_CHUNK_SIZE 00053 #define REST_MAX_CHUNK_SIZE 128 00054 #endif 00055 00056 #define COAP_DEFAULT_MAX_AGE 60 00057 #define COAP_RESPONSE_TIMEOUT 2 00058 #define COAP_MAX_RETRANSMIT 4 00059 #define COAP_ACK_RANDOM_FACTOR 1.5 00060 00061 #define COAP_MAX_TRANSMIT_WAIT ((COAP_RESPONSE_TIMEOUT * ( (1 << (COAP_MAX_RETRANSMIT + 1) ) - 1) * COAP_ACK_RANDOM_FACTOR)) 00062 00063 #define COAP_HEADER_LEN 4 /* | version:0x03 type:0x0C tkl:0xF0 | code | mid:0x00FF | mid:0xFF00 | */ 00064 #define COAP_ETAG_LEN 8 /* The maximum number of bytes for the ETag */ 00065 #define COAP_TOKEN_LEN 8 /* The maximum number of bytes for the Token */ 00066 #define COAP_MAX_ACCEPT_NUM 2 /* The maximum number of accept preferences to parse/store */ 00067 00068 #define COAP_MAX_OPTION_HEADER_LEN 5 00069 00070 #define COAP_HEADER_VERSION_MASK 0xC0 00071 #define COAP_HEADER_VERSION_POSITION 6 00072 #define COAP_HEADER_TYPE_MASK 0x30 00073 #define COAP_HEADER_TYPE_POSITION 4 00074 #define COAP_HEADER_TOKEN_LEN_MASK 0x0F 00075 #define COAP_HEADER_TOKEN_LEN_POSITION 0 00076 00077 #define COAP_HEADER_OPTION_DELTA_MASK 0xF0 00078 #define COAP_HEADER_OPTION_SHORT_LENGTH_MASK 0x0F 00079 00080 /* 00081 * Conservative size limit, as not all options have to be set at the same time. 00082 */ 00083 #ifndef COAP_MAX_HEADER_SIZE 00084 /* Hdr CoT Age Tag Obs Tok Blo strings */ 00085 #define COAP_MAX_HEADER_SIZE (4 + 3 + 5 + 1+COAP_ETAG_LEN + 3 + 1+COAP_TOKEN_LEN + 4 + 30) /* 70 */ 00086 #endif /* COAP_MAX_HEADER_SIZE */ 00087 00088 #define COAP_MAX_PACKET_SIZE (COAP_MAX_HEADER_SIZE + REST_MAX_CHUNK_SIZE) 00089 /* 0/14 48 for IPv6 (28 for IPv4) */ 00090 #if COAP_MAX_PACKET_SIZE > (UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN) 00091 //#error "UIP_CONF_BUFFER_SIZE too small for REST_MAX_CHUNK_SIZE" 00092 #endif 00093 00094 00095 /* Bitmap for set options */ 00096 enum { OPTION_MAP_SIZE = sizeof(uint8_t) * 8 }; 00097 #define SET_OPTION(packet, opt) ((packet)->options[opt / OPTION_MAP_SIZE] |= 1 << (opt % OPTION_MAP_SIZE)) 00098 #define IS_OPTION(packet, opt) ((packet)->options[opt / OPTION_MAP_SIZE] & (1 << (opt % OPTION_MAP_SIZE))) 00099 00100 #ifndef MIN 00101 #define MIN(a, b) ((a) < (b)? (a) : (b)) 00102 #endif /* MIN */ 00103 00104 /* CoAP message types */ 00105 typedef enum { 00106 COAP_TYPE_CON, /* confirmables */ 00107 COAP_TYPE_NON, /* non-confirmables */ 00108 COAP_TYPE_ACK, /* acknowledgements */ 00109 COAP_TYPE_RST /* reset */ 00110 } coap_message_type_t; 00111 00112 /* CoAP request method codes */ 00113 typedef enum { 00114 COAP_GET = 1, 00115 COAP_POST, 00116 COAP_PUT, 00117 COAP_DELETE 00118 } coap_method_t; 00119 00120 /* CoAP response codes */ 00121 typedef enum { 00122 NO_ERROR = 0, 00123 00124 CREATED_2_01 = 65, /* CREATED */ 00125 DELETED_2_02 = 66, /* DELETED */ 00126 VALID_2_03 = 67, /* NOT_MODIFIED */ 00127 CHANGED_2_04 = 68, /* CHANGED */ 00128 CONTENT_2_05 = 69, /* OK */ 00129 00130 BAD_REQUEST_4_00 = 128, /* BAD_REQUEST */ 00131 UNAUTHORIZED_4_01 = 129, /* UNAUTHORIZED */ 00132 BAD_OPTION_4_02 = 130, /* BAD_OPTION */ 00133 FORBIDDEN_4_03 = 131, /* FORBIDDEN */ 00134 NOT_FOUND_4_04 = 132, /* NOT_FOUND */ 00135 METHOD_NOT_ALLOWED_4_05 = 133, /* METHOD_NOT_ALLOWED */ 00136 NOT_ACCEPTABLE_4_06 = 134, /* NOT_ACCEPTABLE */ 00137 PRECONDITION_FAILED_4_12 = 140, /* BAD_REQUEST */ 00138 REQUEST_ENTITY_TOO_LARGE_4_13 = 141, /* REQUEST_ENTITY_TOO_LARGE */ 00139 UNSUPPORTED_MEDIA_TYPE_4_15 = 143, /* UNSUPPORTED_MEDIA_TYPE */ 00140 00141 INTERNAL_SERVER_ERROR_5_00 = 160, /* INTERNAL_SERVER_ERROR */ 00142 NOT_IMPLEMENTED_5_01 = 161, /* NOT_IMPLEMENTED */ 00143 BAD_GATEWAY_5_02 = 162, /* BAD_GATEWAY */ 00144 SERVICE_UNAVAILABLE_5_03 = 163, /* SERVICE_UNAVAILABLE */ 00145 GATEWAY_TIMEOUT_5_04 = 164, /* GATEWAY_TIMEOUT */ 00146 PROXYING_NOT_SUPPORTED_5_05 = 165, /* PROXYING_NOT_SUPPORTED */ 00147 00148 /* Erbium errors */ 00149 MEMORY_ALLOCATION_ERROR = 192, 00150 PACKET_SERIALIZATION_ERROR, 00151 00152 /* Erbium hooks */ 00153 MANUAL_RESPONSE 00154 00155 } coap_status_t; 00156 00157 /* CoAP header options */ 00158 typedef enum { 00159 COAP_OPTION_IF_MATCH = 1, /* 0-8 B */ 00160 COAP_OPTION_URI_HOST = 3, /* 1-255 B */ 00161 COAP_OPTION_ETAG = 4, /* 1-8 B */ 00162 COAP_OPTION_IF_NONE_MATCH = 5, /* 0 B */ 00163 COAP_OPTION_OBSERVE = 6, /* 0-3 B */ 00164 COAP_OPTION_URI_PORT = 7, /* 0-2 B */ 00165 COAP_OPTION_LOCATION_PATH = 8, /* 0-255 B */ 00166 COAP_OPTION_URI_PATH = 11, /* 0-255 B */ 00167 COAP_OPTION_CONTENT_TYPE = 12, /* 0-2 B */ 00168 COAP_OPTION_MAX_AGE = 14, /* 0-4 B */ 00169 COAP_OPTION_URI_QUERY = 15, /* 0-270 B */ 00170 COAP_OPTION_ACCEPT = 17, /* 0-2 B */ 00171 COAP_OPTION_TOKEN = 19, /* 1-8 B */ 00172 COAP_OPTION_LOCATION_QUERY = 20, /* 1-270 B */ 00173 COAP_OPTION_BLOCK2 = 23, /* 1-3 B */ 00174 COAP_OPTION_BLOCK1 = 27, /* 1-3 B */ 00175 COAP_OPTION_SIZE = 28, /* 0-4 B */ 00176 COAP_OPTION_PROXY_URI = 35, /* 1-270 B */ 00177 OPTION_MAX_VALUE = 0xFFFF 00178 } coap_option_t; 00179 00180 /* CoAP Content-Types */ 00181 typedef enum { 00182 TEXT_PLAIN = 0, 00183 TEXT_XML = 1, /* Indented types are not in the initial registry. */ 00184 TEXT_CSV = 2, 00185 TEXT_HTML = 3, 00186 IMAGE_GIF = 21, 00187 IMAGE_JPEG = 22, 00188 IMAGE_PNG = 23, 00189 IMAGE_TIFF = 24, 00190 AUDIO_RAW = 25, 00191 VIDEO_RAW = 26, 00192 APPLICATION_LINK_FORMAT = 40, 00193 APPLICATION_XML = 41, 00194 APPLICATION_OCTET_STREAM = 42, 00195 APPLICATION_RDF_XML = 43, 00196 APPLICATION_SOAP_XML = 44, 00197 APPLICATION_ATOM_XML = 45, 00198 APPLICATION_XMPP_XML = 46, 00199 APPLICATION_EXI = 47, 00200 APPLICATION_FASTINFOSET = 48, 00201 APPLICATION_SOAP_FASTINFOSET = 49, 00202 APPLICATION_JSON = 50, 00203 APPLICATION_X_OBIX_BINARY = 51, 00204 CONTENT_MAX_VALUE = 0xFFFF 00205 } coap_content_type_t; 00206 00207 typedef struct _multi_option_t { 00208 struct _multi_option_t *next; 00209 uint8_t is_static; 00210 uint8_t len; 00211 uint8_t *data; 00212 } multi_option_t; 00213 00214 /* Parsed message struct */ 00215 typedef struct { 00216 uint8_t *buffer; /* pointer to CoAP header / incoming packet buffer / memory to serialize packet */ 00217 00218 uint8_t version; 00219 coap_message_type_t type; 00220 uint8_t code; 00221 uint16_t mid; 00222 00223 uint8_t options[COAP_OPTION_PROXY_URI / OPTION_MAP_SIZE + 1]; /* Bitmap to check if option is set */ 00224 00225 coap_content_type_t content_type; /* Parse options once and store; allows setting options in random order */ 00226 uint32_t max_age; 00227 size_t proxy_uri_len; 00228 const uint8_t *proxy_uri; 00229 uint8_t etag_len; 00230 uint8_t etag[COAP_ETAG_LEN]; 00231 size_t uri_host_len; 00232 const uint8_t *uri_host; 00233 multi_option_t *location_path; 00234 uint16_t uri_port; 00235 size_t location_query_len; 00236 uint8_t *location_query; 00237 multi_option_t *uri_path; 00238 uint32_t observe; 00239 uint8_t token_len; 00240 uint8_t token[COAP_TOKEN_LEN]; 00241 uint8_t accept_num; 00242 uint16_t accept[COAP_MAX_ACCEPT_NUM]; 00243 uint8_t if_match_len; 00244 uint8_t if_match[COAP_ETAG_LEN]; 00245 uint32_t block2_num; 00246 uint8_t block2_more; 00247 uint16_t block2_size; 00248 uint32_t block2_offset; 00249 uint32_t block1_num; 00250 uint8_t block1_more; 00251 uint16_t block1_size; 00252 uint32_t block1_offset; 00253 uint32_t size; 00254 multi_option_t *uri_query; 00255 uint8_t if_none_match; 00256 00257 uint16_t payload_len; 00258 uint8_t *payload; 00259 00260 } coap_packet_t; 00261 00262 /* Option format serialization*/ 00263 #define COAP_SERIALIZE_INT_OPTION(number, field, text) \ 00264 if (IS_OPTION(coap_pkt, number)) { \ 00265 PRINTF(text" [%u]\n", coap_pkt->field); \ 00266 option += coap_serialize_int_option(number, current_number, option, coap_pkt->field); \ 00267 current_number = number; \ 00268 } 00269 #define COAP_SERIALIZE_BYTE_OPTION(number, field, text) \ 00270 if (IS_OPTION(coap_pkt, number)) { \ 00271 PRINTF(text" %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", coap_pkt->field##_len, \ 00272 coap_pkt->field[0], \ 00273 coap_pkt->field[1], \ 00274 coap_pkt->field[2], \ 00275 coap_pkt->field[3], \ 00276 coap_pkt->field[4], \ 00277 coap_pkt->field[5], \ 00278 coap_pkt->field[6], \ 00279 coap_pkt->field[7] \ 00280 ); /*FIXME always prints 8 bytes */ \ 00281 option += coap_serialize_array_option(number, current_number, option, coap_pkt->field, coap_pkt->field##_len, '\0'); \ 00282 current_number = number; \ 00283 } 00284 #define COAP_SERIALIZE_STRING_OPTION(number, field, splitter, text) \ 00285 if (IS_OPTION(coap_pkt, number)) { \ 00286 PRINTF(text" [%.*s]\n", coap_pkt->field##_len, coap_pkt->field); \ 00287 option += coap_serialize_array_option(number, current_number, option, (uint8_t *) coap_pkt->field, coap_pkt->field##_len, splitter); \ 00288 current_number = number; \ 00289 } 00290 #define COAP_SERIALIZE_MULTI_OPTION(number, field, text) \ 00291 if (IS_OPTION(coap_pkt, number)) { \ 00292 PRINTF(text); \ 00293 option += coap_serialize_multi_option(number, current_number, option, coap_pkt->field); \ 00294 current_number = number; \ 00295 } 00296 #define COAP_SERIALIZE_ACCEPT_OPTION(number, field, text) \ 00297 if (IS_OPTION(coap_pkt, number)) { \ 00298 int i; \ 00299 for (i=0; i<coap_pkt->field##_num; ++i) \ 00300 { \ 00301 PRINTF(text" [%u]\n", coap_pkt->field[i]); \ 00302 option += coap_serialize_int_option(number, current_number, option, coap_pkt->field[i]); \ 00303 current_number = number; \ 00304 } \ 00305 } 00306 #define COAP_SERIALIZE_BLOCK_OPTION(number, field, text) \ 00307 if (IS_OPTION(coap_pkt, number)) \ 00308 { \ 00309 uint32_t block = coap_pkt->field##_num << 4; \ 00310 PRINTF(text" [%lu%s (%u B/blk)]\n", coap_pkt->field##_num, coap_pkt->field##_more ? "+" : "", coap_pkt->field##_size); \ 00311 if (coap_pkt->field##_more) block |= 0x8; \ 00312 block |= 0xF & coap_log_2(coap_pkt->field##_size/16); \ 00313 PRINTF(text" encoded: 0x%lX\n", block); \ 00314 option += coap_serialize_int_option(number, current_number, option, block); \ 00315 current_number = number; \ 00316 } 00317 00318 /* To store error code and human-readable payload */ 00319 extern const char *coap_error_message; 00320 00321 uint16_t coap_get_mid(void); 00322 00323 void coap_init_message(void *packet, coap_message_type_t type, uint8_t code, uint16_t mid); 00324 size_t coap_serialize_get_size(void *packet); 00325 size_t coap_serialize_message(void *packet, uint8_t *buffer); 00326 coap_status_t coap_parse_message(void *request, uint8_t *data, uint16_t data_len); 00327 void coap_free_header(void *packet); 00328 00329 char * coap_get_multi_option_as_string(multi_option_t * option); 00330 void coap_add_multi_option(multi_option_t **dst, uint8_t *option, size_t option_len, uint8_t is_static); 00331 void free_multi_option(multi_option_t *dst); 00332 00333 int coap_get_query_variable(void *packet, const char *name, const char **output); 00334 int coap_get_post_variable(void *packet, const char *name, const char **output); 00335 00336 /*-----------------------------------------------------------------------------------*/ 00337 00338 int coap_set_status_code(void *packet, unsigned int code); 00339 00340 unsigned int coap_get_header_content_type(void *packet); 00341 int coap_set_header_content_type(void *packet, unsigned int content_type); 00342 00343 int coap_get_header_accept(void *packet, const uint16_t **accept); 00344 int coap_set_header_accept(void *packet, uint16_t accept); 00345 00346 int coap_get_header_max_age(void *packet, uint32_t *age); 00347 int coap_set_header_max_age(void *packet, uint32_t age); 00348 00349 int coap_get_header_etag(void *packet, const uint8_t **etag); 00350 int coap_set_header_etag(void *packet, const uint8_t *etag, size_t etag_len); 00351 00352 int coap_get_header_if_match(void *packet, const uint8_t **etag); 00353 int coap_set_header_if_match(void *packet, const uint8_t *etag, size_t etag_len); 00354 00355 int coap_get_header_if_none_match(void *packet); 00356 int coap_set_header_if_none_match(void *packet); 00357 00358 int coap_get_header_token(void *packet, const uint8_t **token); 00359 int coap_set_header_token(void *packet, const uint8_t *token, size_t token_len); 00360 00361 int coap_get_header_proxy_uri(void *packet, const char **uri); /* In-place string might not be 0-terminated. */ 00362 int coap_set_header_proxy_uri(void *packet, const char *uri); 00363 00364 int coap_get_header_uri_host(void *packet, const char **host); /* In-place string might not be 0-terminated. */ 00365 int coap_set_header_uri_host(void *packet, const char *host); 00366 00367 int coap_get_header_uri_path(void *packet, const char **path); /* In-place string might not be 0-terminated. */ 00368 int coap_set_header_uri_path(void *packet, const char *path); 00369 int coap_set_header_uri_path_segment(void *packet, const char *path); 00370 00371 int coap_get_header_uri_query(void *packet, const char **query); /* In-place string might not be 0-terminated. */ 00372 int coap_set_header_uri_query(void *packet, const char *query); 00373 00374 int coap_get_header_location_path(void *packet, const char **path); /* In-place string might not be 0-terminated. */ 00375 int coap_set_header_location_path(void *packet, const char *path); /* Also splits optional query into Location-Query option. */ 00376 00377 int coap_get_header_location_query(void *packet, const char **query); /* In-place string might not be 0-terminated. */ 00378 int coap_set_header_location_query(void *packet, char *query); 00379 00380 int coap_get_header_observe(void *packet, uint32_t *observe); 00381 int coap_set_header_observe(void *packet, uint32_t observe); 00382 00383 int coap_get_header_block2(void *packet, uint32_t *num, uint8_t *more, uint16_t *size, uint32_t *offset); 00384 int coap_set_header_block2(void *packet, uint32_t num, uint8_t more, uint16_t size); 00385 00386 int coap_get_header_block1(void *packet, uint32_t *num, uint8_t *more, uint16_t *size, uint32_t *offset); 00387 int coap_set_header_block1(void *packet, uint32_t num, uint8_t more, uint16_t size); 00388 00389 int coap_get_header_size(void *packet, uint32_t *size); 00390 int coap_set_header_size(void *packet, uint32_t size); 00391 00392 int coap_get_payload(void *packet, const uint8_t **payload); 00393 int coap_set_payload(void *packet, const void *payload, size_t length); 00394 00395 #endif /* COAP_13_H_ */
Generated on Sun Jul 17 2022 20:01:04 by
1.7.2