nanocoap.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2016-18 Kaspar Schleiser <kaspar@schleiser.de>
3  * 2018 Freie Universit├Ąt Berlin
4  * 2018 Inria
5  * 2018 Ken Bannister <kb2ma@runbox.com>
6  *
7  * This file is subject to the terms and conditions of the GNU Lesser
8  * General Public License v2.1. See the file LICENSE in the top level
9  * directory for more details.
10  */
11 
79 #ifndef NET_NANOCOAP_H
80 #define NET_NANOCOAP_H
81 
82 #include <assert.h>
83 #include <stdint.h>
84 #include <stdbool.h>
85 #include <stddef.h>
86 #include <unistd.h>
87 
88 #ifdef RIOT_VERSION
89 #include "byteorder.h"
90 #include "net/coap.h"
91 #else
92 #include "coap.h"
93 #include <arpa/inet.h>
94 #endif
95 
96 #ifdef __cplusplus
97 extern "C" {
98 #endif
99 
104 #define COAP_GET (0x1)
105 #define COAP_POST (0x2)
106 #define COAP_PUT (0x4)
107 #define COAP_DELETE (0x8)
108 #define COAP_MATCH_SUBTREE (0x8000)
115 #define COAP_FORMAT_NONE (UINT16_MAX)
124 #ifndef NANOCOAP_NOPTS_MAX
125 #define NANOCOAP_NOPTS_MAX (16)
126 #endif
127 
132 #ifndef NANOCOAP_URI_MAX
133 #define NANOCOAP_URI_MAX (64)
134 #endif
135 
139 #ifndef NANOCOAP_BLOCK_SIZE_EXP_MAX
140 #define NANOCOAP_BLOCK_SIZE_EXP_MAX (6)
141 #endif
142 
143 #if defined(MODULE_GCOAP) || defined(DOXYGEN)
144 
145 #ifndef NANOCOAP_QS_MAX
146 #define NANOCOAP_QS_MAX (64)
147 #endif
148 #endif
149 
158 #define COAP_OPT_FINISH_NONE (0x0000)
160 #define COAP_OPT_FINISH_PAYLOAD (0x0001)
166 typedef struct __attribute__((packed)) {
167  uint8_t ver_t_tkl;
168  uint8_t code;
169  uint16_t id;
171 
175 typedef struct {
176  uint16_t opt_num;
177  uint16_t offset;
179 
183 typedef struct {
184  coap_hdr_t *hdr;
185  uint8_t *token;
186  uint8_t *payload;
187  uint16_t payload_len;
188  uint16_t options_len;
190 #ifdef MODULE_GCOAP
191  uint32_t observe_value;
192 #endif
193 } coap_pkt_t;
194 
198 typedef ssize_t (*coap_handler_t)(coap_pkt_t *pkt, uint8_t *buf, size_t len, void *context);
203 typedef struct {
204  const char *path;
205  unsigned methods;
206  coap_handler_t handler;
207  void *context;
209 
213 typedef struct {
214  size_t offset;
215  uint32_t blknum;
216  unsigned szx;
217  int more;
219 } coap_block1_t;
220 
224 typedef struct {
225  size_t start;
226  size_t end;
227  size_t cur;
228  uint8_t *opt;
230 
234 extern const coap_resource_t coap_resources[];
235 
239 extern const unsigned coap_resources_numof;
240 
241 
256 static inline uint8_t coap_code(unsigned cls, unsigned detail)
257 {
258  return (cls << 5) | detail;
259 }
260 
268 static inline unsigned coap_get_code_class(coap_pkt_t *pkt)
269 {
270  return pkt->hdr->code >> 5;
271 }
272 
280 static inline unsigned coap_get_code_detail(coap_pkt_t *pkt)
281 {
282  return pkt->hdr->code & 0x1f;
283 }
284 
292 static inline unsigned coap_get_code(coap_pkt_t *pkt)
293 {
294  return (coap_get_code_class(pkt) * 100) + coap_get_code_detail(pkt);
295 }
296 
304 static inline unsigned coap_get_code_raw(coap_pkt_t *pkt)
305 {
306  return (unsigned)pkt->hdr->code;
307 }
308 
316 static inline unsigned coap_get_id(coap_pkt_t *pkt)
317 {
318  return ntohs(pkt->hdr->id);
319 }
320 
328 static inline unsigned coap_get_token_len(coap_pkt_t *pkt)
329 {
330  return (pkt->hdr->ver_t_tkl & 0xf);
331 }
332 
340 static inline unsigned coap_get_total_hdr_len(coap_pkt_t *pkt)
341 {
342  return sizeof(coap_hdr_t) + coap_get_token_len(pkt);
343 }
344 
355 static inline unsigned coap_get_type(coap_pkt_t *pkt)
356 {
357  return (pkt->hdr->ver_t_tkl & 0x30) >> 4;
358 }
359 
367 static inline unsigned coap_get_ver(coap_pkt_t *pkt)
368 {
369  return (pkt->hdr->ver_t_tkl & 0x60) >> 6;
370 }
371 
379 static inline uint8_t *coap_hdr_data_ptr(coap_hdr_t *hdr)
380 {
381  return ((uint8_t *)hdr) + sizeof(coap_hdr_t);
382 }
383 
390 static inline void coap_hdr_set_code(coap_hdr_t *hdr, uint8_t code)
391 {
392  hdr->code = code;
393 }
394 
403 static inline void coap_hdr_set_type(coap_hdr_t *hdr, unsigned type)
404 {
405  /* assert correct range of type */
406  assert(!(type & ~0x3));
407 
408  hdr->ver_t_tkl &= ~0x30;
409  hdr->ver_t_tkl |= type << 4;
410 }
428 unsigned coap_get_content_type(coap_pkt_t *pkt);
429 
447 ssize_t coap_opt_get_string(const coap_pkt_t *pkt, uint16_t optnum,
448  uint8_t *target, size_t max_len, char separator);
449 
465 static inline ssize_t coap_get_location_path(const coap_pkt_t *pkt,
466  uint8_t *target, size_t max_len)
467 {
468  return coap_opt_get_string(pkt, COAP_OPT_LOCATION_PATH,
469  target, max_len, '/');
470 }
471 
487 static inline ssize_t coap_get_location_query(const coap_pkt_t *pkt,
488  uint8_t *target, size_t max_len)
489 {
490  return coap_opt_get_string(pkt, COAP_OPT_LOCATION_QUERY,
491  target, max_len, '&');
492 }
493 
508 static inline ssize_t coap_get_uri_path(const coap_pkt_t *pkt, uint8_t *target)
509 {
510  return coap_opt_get_string(pkt, COAP_OPT_URI_PATH, target,
511  NANOCOAP_URI_MAX, '/');
512 }
513 
528 static inline ssize_t coap_get_uri_query(const coap_pkt_t *pkt, uint8_t *target)
529 {
530  return coap_opt_get_string(pkt, COAP_OPT_URI_QUERY, target,
531  NANOCOAP_URI_MAX, '&');
532 }
555 
566 
581 size_t coap_blockwise_put_bytes(coap_block_slicer_t *slicer, uint8_t *bufpos,
582  const uint8_t *c, size_t len);
583 
597 size_t coap_blockwise_put_char(coap_block_slicer_t *slicer, uint8_t *bufpos, char c);
598 
616 int coap_get_block1(coap_pkt_t *pkt, coap_block1_t *block1);
617 
627 int coap_get_block2(coap_pkt_t *pkt, coap_block1_t *block2);
628 
641 int coap_get_blockopt(coap_pkt_t *pkt, uint16_t option, uint32_t *blknum, unsigned *szx);
642 
650 static inline unsigned coap_szx2size(unsigned szx)
651 {
652  return (1 << (szx + 4));
653 }
676 ssize_t coap_opt_add_uint(coap_pkt_t *pkt, uint16_t optnum, uint32_t value);
677 
691 static inline ssize_t coap_opt_add_format(coap_pkt_t *pkt, uint16_t format)
692 {
693  return coap_opt_add_uint(pkt, COAP_OPT_CONTENT_FORMAT, format);
694 }
695 
711 ssize_t coap_opt_add_opaque(coap_pkt_t *pkt, uint16_t optnum, const uint8_t *val, size_t val_len);
712 
730 ssize_t coap_opt_add_string(coap_pkt_t *pkt, uint16_t optnum, const char *string, char separator);
731 
744 ssize_t coap_opt_finish(coap_pkt_t *pkt, uint16_t flags);
769 size_t coap_opt_put_block2(uint8_t *buf, uint16_t lastonum, coap_block_slicer_t *slicer, bool more);
770 
783 size_t coap_opt_put_string(uint8_t *buf, uint16_t lastonum, uint16_t optnum,
784  const char *string, char separator);
785 
796 static inline size_t coap_opt_put_location_path(uint8_t *buf,
797  uint16_t lastonum,
798  const char *location)
799 {
800  return coap_opt_put_string(buf, lastonum, COAP_OPT_LOCATION_PATH,
801  location, '/');
802 }
803 
814 static inline size_t coap_opt_put_location_query(uint8_t *buf,
815  uint16_t lastonum,
816  const char *location)
817 {
818  return coap_opt_put_string(buf, lastonum, COAP_OPT_LOCATION_QUERY,
819  location, '&');
820 }
821 
832 static inline size_t coap_opt_put_uri_path(uint8_t *buf, uint16_t lastonum,
833  const char *uri)
834 {
835  return coap_opt_put_string(buf, lastonum, COAP_OPT_URI_PATH, uri, '/');
836 }
837 
848 static inline size_t coap_opt_put_uri_query(uint8_t *buf, uint16_t lastonum,
849  const char *uri)
850 {
851  return coap_opt_put_string(buf, lastonum, COAP_OPT_URI_QUERY, uri, '&');
852 }
853 
871 size_t coap_put_block1_ok(uint8_t *pkt_pos, coap_block1_t *block1, uint16_t lastonum);
872 
889 size_t coap_put_option(uint8_t *buf, uint16_t lastonum, uint16_t onum, const uint8_t *odata, size_t olen);
890 
903 size_t coap_put_option_block1(uint8_t *buf, uint16_t lastonum, unsigned blknum, unsigned szx, int more);
904 
915 size_t coap_put_option_ct(uint8_t *buf, uint16_t lastonum, uint16_t content_type);
942 ssize_t coap_block2_build_reply(coap_pkt_t *pkt, unsigned code,
943  uint8_t *rbuf, unsigned rlen, unsigned payload_len,
944  coap_block_slicer_t *slicer);
945 
960 ssize_t coap_build_hdr(coap_hdr_t *hdr, unsigned type, uint8_t *token,
961  size_t token_len, unsigned code, uint16_t id);
962 
984 ssize_t coap_build_reply(coap_pkt_t *pkt, unsigned code,
985  uint8_t *rbuf, unsigned rlen, unsigned payload_len);
986 
1000 ssize_t coap_handle_req(coap_pkt_t *pkt, uint8_t *resp_buf, unsigned resp_buf_len);
1001 
1009 static inline unsigned coap_method2flag(unsigned code)
1011  return (1 << (code - 1));
1012 }
1013 
1028 int coap_parse(coap_pkt_t *pkt, uint8_t *buf, size_t len);
1029 
1044 void coap_pkt_init(coap_pkt_t *pkt, uint8_t *buf, size_t len, size_t header_len);
1045 
1067 ssize_t coap_reply_simple(coap_pkt_t *pkt,
1068  unsigned code,
1069  uint8_t *buf, size_t len,
1070  unsigned ct,
1071  const uint8_t *payload, uint8_t payload_len);
1072 
1077 extern ssize_t coap_well_known_core_default_handler(coap_pkt_t *pkt, \
1078  uint8_t *buf, size_t len,
1079  void *context);
1098 int coap_match_path(const coap_resource_t *resource, uint8_t *uri);
1099 
1100 #if defined(MODULE_GCOAP) || defined(DOXYGEN)
1101 
1113 static inline bool coap_has_observe(coap_pkt_t *pkt)
1115  return pkt->observe_value != UINT32_MAX;
1116 }
1117 
1123 static inline void coap_clear_observe(coap_pkt_t *pkt)
1125  pkt->observe_value = UINT32_MAX;
1126 }
1127 
1135 static inline uint32_t coap_get_observe(coap_pkt_t *pkt)
1137  return pkt->observe_value;
1138 }
1140 #endif
1141 
1145 #define COAP_WELL_KNOWN_CORE_DEFAULT_HANDLER \
1146  { \
1147  .path = "/.well-known/core", \
1148  .methods = COAP_GET, \
1149  .handler = coap_well_known_core_default_handler \
1150  }
1151 
1152 #ifdef __cplusplus
1153 }
1154 #endif
1155 #endif /* NET_NANOCOAP_H */
1156 
static void coap_hdr_set_type(coap_hdr_t *hdr, unsigned type)
Set the message type for the given CoAP header.
Definition: nanocoap.h:404
static unsigned coap_get_code_raw(coap_pkt_t *pkt)
Get a message&#39;s raw code (class + detail)
Definition: nanocoap.h:305
size_t coap_blockwise_put_bytes(coap_block_slicer_t *slicer, uint8_t *bufpos, const uint8_t *c, size_t len)
Add a byte array to a block2 reply.
static unsigned coap_get_code_detail(coap_pkt_t *pkt)
Get a message&#39;s code detail (5 least significant bits of code)
Definition: nanocoap.h:281
int coap_get_block1(coap_pkt_t *pkt, coap_block1_t *block1)
Block1 option getter.
int coap_match_path(const coap_resource_t *resource, uint8_t *uri)
Checks if a CoAP resource path matches a given URI.
int coap_get_blockopt(coap_pkt_t *pkt, uint16_t option, uint32_t *blknum, unsigned *szx)
Generic block option getter.
const unsigned coap_resources_numof
Number of entries in global CoAP resource list.
size_t coap_opt_put_block2(uint8_t *buf, uint16_t lastonum, coap_block_slicer_t *slicer, bool more)
Insert block2 option into buffer.
static unsigned coap_get_code_class(coap_pkt_t *pkt)
Get a message&#39;s code class (3 most significant bits of code)
Definition: nanocoap.h:269
size_t coap_put_option_ct(uint8_t *buf, uint16_t lastonum, uint16_t content_type)
Insert content type option into buffer.
static size_t coap_opt_put_uri_path(uint8_t *buf, uint16_t lastonum, const char *uri)
Convenience function for inserting URI_PATH option into buffer.
Definition: nanocoap.h:833
static size_t coap_opt_put_location_query(uint8_t *buf, uint16_t lastonum, const char *location)
Convenience function for inserting LOCATION_QUERY option into buffer.
Definition: nanocoap.h:815
ssize_t coap_handle_req(coap_pkt_t *pkt, uint8_t *resp_buf, unsigned resp_buf_len)
Handle incoming CoAP request.
Raw CoAP PDU header structure.
Definition: nanocoap.h:167
static unsigned coap_szx2size(unsigned szx)
Helper to decode SZX value to size in bytes.
Definition: nanocoap.h:651
static ssize_t coap_opt_add_format(coap_pkt_t *pkt, uint16_t format)
Append a Content-Format option to the pkt buffer.
Definition: nanocoap.h:692
ssize_t coap_opt_add_string(coap_pkt_t *pkt, uint16_t optnum, const char *string, char separator)
Encode the given string as option(s) into pkt.
CoAP option array entry.
Definition: nanocoap.h:176
static ssize_t coap_get_uri_query(const coap_pkt_t *pkt, uint8_t *target)
Convenience function for getting the packet&#39;s URI_QUERY option.
Definition: nanocoap.h:529
Blockwise transfer helper struct.
Definition: nanocoap.h:225
uint8_t code
CoAP code (e.g.m 205)
Definition: nanocoap.h:169
static ssize_t coap_get_location_path(const coap_pkt_t *pkt, uint8_t *target, size_t max_len)
Convenience function for getting the packet&#39;s LOCATION_PATH option.
Definition: nanocoap.h:466
ssize_t coap_build_hdr(coap_hdr_t *hdr, unsigned type, uint8_t *token, size_t token_len, unsigned code, uint16_t id)
Builds a CoAP header.
static size_t coap_opt_put_location_path(uint8_t *buf, uint16_t lastonum, const char *location)
Convenience function for inserting LOCATION_PATH option into buffer.
Definition: nanocoap.h:797
Type for CoAP resource entry.
Definition: nanocoap.h:204
static unsigned coap_get_total_hdr_len(coap_pkt_t *pkt)
Get the total header length (4-byte header + token length)
Definition: nanocoap.h:341
ssize_t coap_opt_get_string(const coap_pkt_t *pkt, uint16_t optnum, uint8_t *target, size_t max_len, char separator)
Read a full option as null terminated string into the target buffer.
POSIX.1-2008 compliant version of the assert macro.
signed int ssize_t
Used for a count of bytes or an error indication.
Definition: msp430_types.h:89
coap_hdr_t * hdr
pointer to raw packet
Definition: nanocoap.h:185
static void coap_clear_observe(coap_pkt_t *pkt)
Clears the observe option value from a packet.
Definition: nanocoap.h:1124
unsigned coap_get_content_type(coap_pkt_t *pkt)
Get content type from packet.
static void coap_hdr_set_code(coap_hdr_t *hdr, uint8_t code)
Write the given raw message code to given CoAP header.
Definition: nanocoap.h:391
ssize_t coap_opt_finish(coap_pkt_t *pkt, uint16_t flags)
Finalizes options as required and prepares for payload.
static unsigned coap_get_ver(coap_pkt_t *pkt)
Get the CoAP version number.
Definition: nanocoap.h:368
#define assert(cond)
abort the program if assertion is false
Definition: assert.h:104
uint8_t ver_t_tkl
version, token, token length
Definition: nanocoap.h:168
Block1 helper struct.
Definition: nanocoap.h:214
static uint8_t coap_code(unsigned cls, unsigned detail)
Encode given code class and code detail to raw code.
Definition: nanocoap.h:257
size_t coap_opt_put_string(uint8_t *buf, uint16_t lastonum, uint16_t optnum, const char *string, char separator)
Encode the given string as multi-part option into buffer.
int coap_parse(coap_pkt_t *pkt, uint8_t *buf, size_t len)
Parse a CoAP PDU.
void coap_block2_init(coap_pkt_t *pkt, coap_block_slicer_t *slicer)
Initialize a block2 slicer struct for writing the payload.
static unsigned coap_get_id(coap_pkt_t *pkt)
Get the message ID of the given CoAP packet.
Definition: nanocoap.h:317
int coap_get_block2(coap_pkt_t *pkt, coap_block1_t *block2)
Block2 option getter.
ssize_t coap_reply_simple(coap_pkt_t *pkt, unsigned code, uint8_t *buf, size_t len, unsigned ct, const uint8_t *payload, uint8_t payload_len)
Create CoAP reply (convenience function)
ssize_t coap_build_reply(coap_pkt_t *pkt, unsigned code, uint8_t *rbuf, unsigned rlen, unsigned payload_len)
Build reply to CoAP request.
static uint32_t coap_get_observe(coap_pkt_t *pkt)
Get the value of the observe option from the given packet.
Definition: nanocoap.h:1136
static size_t coap_opt_put_uri_query(uint8_t *buf, uint16_t lastonum, const char *uri)
Convenience function for inserting URI_QUERY option into buffer.
Definition: nanocoap.h:849
#define NANOCOAP_NOPTS_MAX
Maximum number of Options in a message.
Definition: nanocoap.h:126
Functions to work with different byte orders.
static unsigned coap_get_token_len(coap_pkt_t *pkt)
Get a message&#39;s token length [in byte].
Definition: nanocoap.h:329
void coap_block2_finish(coap_block_slicer_t *slicer)
Finish a block2 response.
static uint16_t ntohs(uint16_t v)
Convert from network byte order to host byte order, 16 bit.
Definition: byteorder.h:428
void coap_pkt_init(coap_pkt_t *pkt, uint8_t *buf, size_t len, size_t header_len)
Initialize a packet struct, to build a message buffer.
size_t coap_put_option_block1(uint8_t *buf, uint16_t lastonum, unsigned blknum, unsigned szx, int more)
Insert block1 option into buffer.
Definitions for internet operations.
ssize_t coap_well_known_core_default_handler(coap_pkt_t *pkt, uint8_t *buf, size_t len, void *context)
Reference to the default .well-known/core handler defined by the application.
size_t coap_put_block1_ok(uint8_t *pkt_pos, coap_block1_t *block1, uint16_t lastonum)
Insert block1 option into buffer (from coap_block1_t)
ssize_t coap_block2_build_reply(coap_pkt_t *pkt, unsigned code, uint8_t *rbuf, unsigned rlen, unsigned payload_len, coap_block_slicer_t *slicer)
Build reply to CoAP block2 request.
static unsigned coap_method2flag(unsigned code)
Convert message code (request method) into a corresponding bit field.
Definition: nanocoap.h:1010
static ssize_t coap_get_uri_path(const coap_pkt_t *pkt, uint8_t *target)
Convenience function for getting the packet&#39;s URI_PATH.
Definition: nanocoap.h:509
ssize_t coap_opt_add_uint(coap_pkt_t *pkt, uint16_t optnum, uint32_t value)
Encode the given uint option into pkt.
static uint8_t * coap_hdr_data_ptr(coap_hdr_t *hdr)
Get the start of data after the header.
Definition: nanocoap.h:380
uint16_t id
Req/resp ID.
Definition: nanocoap.h:170
static bool coap_has_observe(coap_pkt_t *pkt)
Identifies a packet containing an observe option.
Definition: nanocoap.h:1114
size_t coap_blockwise_put_char(coap_block_slicer_t *slicer, uint8_t *bufpos, char c)
Add a single character to a block2 reply.
Generic CoAP values as defined by RFC7252.
static unsigned coap_get_type(coap_pkt_t *pkt)
Get the message type.
Definition: nanocoap.h:356
ssize_t(* coap_handler_t)(coap_pkt_t *pkt, uint8_t *buf, size_t len, void *context)
Resource handler type.
Definition: nanocoap.h:199
ssize_t coap_opt_add_opaque(coap_pkt_t *pkt, uint16_t optnum, const uint8_t *val, size_t val_len)
Encode the given buffer as an opaque data option into pkt.
#define NANOCOAP_URI_MAX
Maximum length of a resource path string read from or written to a message.
Definition: nanocoap.h:134
static unsigned coap_get_code(coap_pkt_t *pkt)
Get a message&#39;s code in decimal format ((class * 100) + detail)
Definition: nanocoap.h:293
CoAP PDU parsing context structure.
Definition: nanocoap.h:184
size_t coap_put_option(uint8_t *buf, uint16_t lastonum, uint16_t onum, const uint8_t *odata, size_t olen)
Insert a CoAP option into buffer.
static ssize_t coap_get_location_query(const coap_pkt_t *pkt, uint8_t *target, size_t max_len)
Convenience function for getting the packet&#39;s LOCATION_QUERY option.
Definition: nanocoap.h:488
const coap_resource_t coap_resources[]
Global CoAP resource list.