nanocoap.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2016-17 Kaspar Schleiser <kaspar@schleiser.de>
3  * 2018 Freie Universit├Ąt Berlin
4  *
5  * This file is subject to the terms and conditions of the GNU Lesser
6  * General Public License v2.1. See the file LICENSE in the top level
7  * directory for more details.
8  */
9 
25 #ifndef NET_NANOCOAP_H
26 #define NET_NANOCOAP_H
27 
28 #include <assert.h>
29 #include <stdint.h>
30 #include <stdbool.h>
31 #include <stddef.h>
32 #include <unistd.h>
33 
34 #ifdef RIOT_VERSION
35 #include "byteorder.h"
36 #else
37 #include <arpa/inet.h>
38 #endif
39 
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 
47 #define COAP_PORT (5683)
48 
53 #define NANOCOAP_NOPTS_MAX (16)
54 #define NANOCOAP_URI_MAX (64)
55 
57 #ifdef MODULE_GCOAP
58 #define NANOCOAP_URL_MAX NANOCOAP_URI_MAX
59 #define NANOCOAP_QS_MAX (64)
60 #endif
61 
66 #define COAP_OPT_URI_HOST (3)
67 #define COAP_OPT_OBSERVE (6)
68 #define COAP_OPT_LOCATION_PATH (8)
69 #define COAP_OPT_URI_PATH (11)
70 #define COAP_OPT_CONTENT_FORMAT (12)
71 #define COAP_OPT_URI_QUERY (15)
72 #define COAP_OPT_LOCATION_QUERY (20)
73 #define COAP_OPT_BLOCK2 (23)
74 #define COAP_OPT_BLOCK1 (27)
75 
81 #define COAP_REQ (0)
82 #define COAP_RESP (2)
83 #define COAP_RST (3)
84 
89 #define COAP_TYPE_CON (0)
90 #define COAP_TYPE_NON (1)
91 #define COAP_TYPE_ACK (2)
92 #define COAP_TYPE_RST (3)
93 
99 #define COAP_CLASS_REQ (0)
100 #define COAP_METHOD_GET (1)
101 #define COAP_METHOD_POST (2)
102 #define COAP_METHOD_PUT (3)
103 #define COAP_METHOD_DELETE (4)
104 
110 #define COAP_GET (0x1)
111 #define COAP_POST (0x2)
112 #define COAP_PUT (0x4)
113 #define COAP_DELETE (0x8)
114 
120 #define COAP_CODE_EMPTY (0)
121 
127 #define COAP_CLASS_SUCCESS (2)
128 #define COAP_CODE_CREATED ((2 << 5) | 1)
129 #define COAP_CODE_DELETED ((2 << 5) | 2)
130 #define COAP_CODE_VALID ((2 << 5) | 3)
131 #define COAP_CODE_CHANGED ((2 << 5) | 4)
132 #define COAP_CODE_204 ((2 << 5) | 4)
133 #define COAP_CODE_CONTENT ((2 << 5) | 5)
134 #define COAP_CODE_205 ((2 << 5) | 5)
135 #define COAP_CODE_231 ((2 << 5) | 31)
136 
142 #define COAP_CLASS_CLIENT_FAILURE (4)
143 #define COAP_CODE_BAD_REQUEST ((4 << 5) | 0)
144 #define COAP_CODE_UNAUTHORIZED ((4 << 5) | 1)
145 #define COAP_CODE_BAD_OPTION ((4 << 5) | 2)
146 #define COAP_CODE_FORBIDDEN ((4 << 5) | 3)
147 #define COAP_CODE_PATH_NOT_FOUND ((4 << 5) | 4)
148 #define COAP_CODE_404 ((4 << 5) | 4)
149 #define COAP_CODE_METHOD_NOT_ALLOWED ((4 << 5) | 5)
150 #define COAP_CODE_NOT_ACCEPTABLE ((4 << 5) | 6)
151 #define COAP_CODE_REQUEST_ENTITY_INCOMPLETE ((4 << 5) | 8)
152 #define COAP_CODE_PRECONDITION_FAILED ((4 << 5) | 0xC)
153 #define COAP_CODE_REQUEST_ENTITY_TOO_LARGE ((4 << 5) | 0xD)
154 #define COAP_CODE_UNSUPPORTED_CONTENT_FORMAT ((4 << 5) | 0xF)
155 
161 #define COAP_CLASS_SERVER_FAILURE (5)
162 #define COAP_CODE_INTERNAL_SERVER_ERROR ((5 << 5) | 0)
163 #define COAP_CODE_NOT_IMPLEMENTED ((5 << 5) | 1)
164 #define COAP_CODE_BAD_GATEWAY ((5 << 5) | 2)
165 #define COAP_CODE_SERVICE_UNAVAILABLE ((5 << 5) | 3)
166 #define COAP_CODE_GATEWAY_TIMEOUT ((5 << 5) | 4)
167 #define COAP_CODE_PROXYING_NOT_SUPPORTED ((5 << 5) | 5)
168 
174 #define COAP_CT_LINK_FORMAT (40)
175 #define COAP_CT_XML (41)
176 #define COAP_CT_OCTET_STREAM (42)
177 #define COAP_CT_EXI (47)
178 #define COAP_CT_JSON (50)
179 
185 #define COAP_FORMAT_TEXT (0)
186 #define COAP_FORMAT_LINK (40)
187 #define COAP_FORMAT_OCTET (42)
188 #define COAP_FORMAT_JSON (50)
189 #define COAP_FORMAT_CBOR (60)
190 
191 #define COAP_FORMAT_NONE (65535)
192 
198 #define COAP_OBS_REGISTER (0)
199 #define COAP_OBS_DEREGISTER (1)
200 
206 #define COAP_ACK_TIMEOUT (2U)
207 #define COAP_RANDOM_FACTOR (1.5)
208 
216 #define COAP_ACK_VARIANCE (1U)
217 #define COAP_MAX_RETRANSMIT (4)
218 #define COAP_NSTART (1)
219 #define COAP_DEFAULT_LEISURE (5)
220 
226 #define COAP_BLOCKWISE_NUM_OFF (4)
227 #define COAP_BLOCKWISE_MORE_OFF (3)
228 #define COAP_BLOCKWISE_SZX_MASK (0x07)
229 #define COAP_BLOCKWISE_SZX_MAX (7)
230 
239 #define COAP_OPT_FINISH_NONE (0x0000)
240 
241 #define COAP_OPT_FINISH_PAYLOAD (0x0001)
242 
247 typedef struct __attribute__((packed)) {
248  uint8_t ver_t_tkl;
249  uint8_t code;
250  uint16_t id;
251  uint8_t data[];
252 } coap_hdr_t;
253 
257 typedef struct {
258  uint16_t opt_num;
259  uint16_t offset;
260 } coap_optpos_t;
261 
265 typedef struct {
267  uint8_t *token;
268  uint8_t *payload;
269  uint16_t payload_len;
270  uint16_t options_len;
271  coap_optpos_t options[NANOCOAP_NOPTS_MAX];
272 #ifdef MODULE_GCOAP
273  uint8_t url[NANOCOAP_URI_MAX];
274  uint8_t qs[NANOCOAP_QS_MAX];
275  uint16_t content_type;
276  uint32_t observe_value;
277 #endif
278 } coap_pkt_t;
279 
283 typedef ssize_t (*coap_handler_t)(coap_pkt_t *pkt, uint8_t *buf, size_t len, void *context);
284 
288 typedef struct {
289  const char *path;
290  unsigned methods;
292  void *context;
294 
298 typedef struct {
299  size_t offset;
300  uint32_t blknum;
301  unsigned szx;
302  int more;
304 } coap_block1_t;
305 
309 extern const coap_resource_t coap_resources[];
310 
314 extern const unsigned coap_resources_numof;
315 
330 int coap_parse(coap_pkt_t *pkt, uint8_t *buf, size_t len);
331 
349 ssize_t coap_build_reply(coap_pkt_t *pkt, unsigned code,
350  uint8_t *rbuf, unsigned rlen, unsigned payload_len);
351 
373  unsigned code,
374  uint8_t *buf, size_t len,
375  unsigned ct,
376  const uint8_t *payload, uint8_t payload_len);
377 
391 ssize_t coap_handle_req(coap_pkt_t *pkt, uint8_t *resp_buf, unsigned resp_buf_len);
392 
407 ssize_t coap_build_hdr(coap_hdr_t *hdr, unsigned type, uint8_t *token,
408  size_t token_len, unsigned code, uint16_t id);
409 
424 void coap_pkt_init(coap_pkt_t *pkt, uint8_t *buf, size_t len, size_t header_len);
425 
442 size_t coap_put_option(uint8_t *buf, uint16_t lastonum, uint16_t onum, uint8_t *odata, size_t olen);
443 
454 size_t coap_put_option_ct(uint8_t *buf, uint16_t lastonum, uint16_t content_type);
455 
468 size_t coap_opt_put_string(uint8_t *buf, uint16_t lastonum, uint16_t optnum,
469  const char *string, char separator);
470 
481 static inline size_t coap_opt_put_uri_path(uint8_t *buf, uint16_t lastonum,
482  const char *uri)
483 {
484  return coap_opt_put_string(buf, lastonum, COAP_OPT_URI_PATH, uri, '/');
485 }
486 
497 static inline size_t coap_opt_put_uri_query(uint8_t *buf, uint16_t lastonum,
498  const char *uri)
499 {
500  return coap_opt_put_string(buf, lastonum, COAP_OPT_URI_QUERY, uri, '&');
501 }
502 
513 static inline size_t coap_opt_put_location_path(uint8_t *buf,
514  uint16_t lastonum,
515  const char *location)
516 {
517  return coap_opt_put_string(buf, lastonum, COAP_OPT_LOCATION_PATH,
518  location, '/');
519 }
520 
531 static inline size_t coap_opt_put_location_query(uint8_t *buf,
532  uint16_t lastonum,
533  const char *location)
534 {
535  return coap_opt_put_string(buf, lastonum, COAP_OPT_LOCATION_QUERY,
536  location, '&');
537 }
538 
551 int coap_get_blockopt(coap_pkt_t *pkt, uint16_t option, uint32_t *blknum, unsigned *szx);
552 
570 int coap_get_block1(coap_pkt_t *pkt, coap_block1_t *block1);
571 
584 size_t coap_put_option_block1(uint8_t *buf, uint16_t lastonum, unsigned blknum, unsigned szx, int more);
585 
603 size_t coap_put_block1_ok(uint8_t *pkt_pos, coap_block1_t *block1, uint16_t lastonum);
604 
621 ssize_t coap_opt_add_string(coap_pkt_t *pkt, uint16_t optnum, const char *string, char separator);
622 
636 ssize_t coap_opt_add_uint(coap_pkt_t *pkt, uint16_t optnum, uint32_t value);
637 
649 ssize_t coap_opt_finish(coap_pkt_t *pkt, uint16_t flags);
650 
659 unsigned coap_get_content_type(coap_pkt_t *pkt);
660 
678 ssize_t coap_opt_get_string(const coap_pkt_t *pkt, uint16_t optnum,
679  uint8_t *target, size_t max_len, char separator);
680 
695 static inline ssize_t coap_get_uri_path(const coap_pkt_t *pkt, uint8_t *target)
696 {
697  return coap_opt_get_string(pkt, COAP_OPT_URI_PATH, target,
698  NANOCOAP_URI_MAX, '/');
699 }
700 
715 static inline ssize_t coap_get_uri_query(const coap_pkt_t *pkt, uint8_t *target)
716 {
717  return coap_opt_get_string(pkt, COAP_OPT_URI_QUERY, target,
718  NANOCOAP_URI_MAX, '&');
719 }
720 
736 static inline ssize_t coap_get_location_path(const coap_pkt_t *pkt,
737  uint8_t *target, size_t max_len)
738 {
739  return coap_opt_get_string(pkt, COAP_OPT_LOCATION_PATH,
740  target, max_len, '/');
741 }
742 
758 static inline ssize_t coap_get_location_query(const coap_pkt_t *pkt,
759  uint8_t *target, size_t max_len)
760 {
761  return coap_opt_get_string(pkt, COAP_OPT_LOCATION_QUERY,
762  target, max_len, '&');
763 }
764 
772 static inline unsigned coap_szx2size(unsigned szx)
773 {
774  return (1 << (szx + 4));
775 }
776 
784 static inline unsigned coap_get_ver(coap_pkt_t *pkt)
785 {
786  return (pkt->hdr->ver_t_tkl & 0x60) >> 6;
787 }
788 
799 static inline unsigned coap_get_type(coap_pkt_t *pkt)
800 {
801  return (pkt->hdr->ver_t_tkl & 0x30) >> 4;
802 }
803 
811 static inline unsigned coap_get_token_len(coap_pkt_t *pkt)
812 {
813  return (pkt->hdr->ver_t_tkl & 0xf);
814 }
815 
823 static inline unsigned coap_get_code_class(coap_pkt_t *pkt)
824 {
825  return pkt->hdr->code >> 5;
826 }
827 
835 static inline unsigned coap_get_code_detail(coap_pkt_t *pkt)
836 {
837  return pkt->hdr->code & 0x1f;
838 }
839 
847 static inline unsigned coap_get_code_raw(coap_pkt_t *pkt)
848 {
849  return (unsigned)pkt->hdr->code;
850 }
851 
859 static inline unsigned coap_get_code(coap_pkt_t *pkt)
860 {
861  return (coap_get_code_class(pkt) * 100) + coap_get_code_detail(pkt);
862 }
863 
871 static inline unsigned coap_get_id(coap_pkt_t *pkt)
872 {
873  return ntohs(pkt->hdr->id);
874 }
875 
883 static inline unsigned coap_get_total_hdr_len(coap_pkt_t *pkt)
884 {
885  return sizeof(coap_hdr_t) + coap_get_token_len(pkt);
886 }
887 
896 static inline uint8_t coap_code(unsigned class, unsigned detail)
897 {
898  return (class << 5) | detail;
899 }
900 
907 static inline void coap_hdr_set_code(coap_hdr_t *hdr, uint8_t code)
908 {
909  hdr->code = code;
910 }
911 
920 static inline void coap_hdr_set_type(coap_hdr_t *hdr, unsigned type)
921 {
922  /* assert correct range of type */
923  assert(!(type & ~0x3));
924 
925  hdr->ver_t_tkl &= ~0x30;
926  hdr->ver_t_tkl |= type << 4;
927 }
928 
936 static inline unsigned coap_method2flag(unsigned code)
937 {
938  return (1 << (code - 1));
939 }
940 
941 #if defined(MODULE_GCOAP) || defined(DOXYGEN)
942 
950 static inline bool coap_has_observe(coap_pkt_t *pkt)
951 {
952  return pkt->observe_value != UINT32_MAX;
953 }
954 
960 static inline void coap_clear_observe(coap_pkt_t *pkt)
961 {
962  pkt->observe_value = UINT32_MAX;
963 }
964 
972 static inline uint32_t coap_get_observe(coap_pkt_t *pkt)
973 {
974  return pkt->observe_value;
975 }
976 #endif
977 
983  uint8_t *buf, size_t len,
984  void *context);
985 
989 #define COAP_WELL_KNOWN_CORE_DEFAULT_HANDLER \
990  { \
991  .path = "/.well-known/core", \
992  .methods = COAP_GET, \
993  .handler = coap_well_known_core_default_handler \
994  }
995 
996 #ifdef __cplusplus
997 }
998 #endif
999 #endif /* NET_NANOCOAP_H */
1000 
static void coap_hdr_set_type(coap_hdr_t *hdr, unsigned type)
Set the message type for the given CoAP header.
Definition: nanocoap.h:920
static unsigned coap_get_code_raw(coap_pkt_t *pkt)
Get a message&#39;s raw code (class + detail)
Definition: nanocoap.h:847
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:835
int coap_get_block1(coap_pkt_t *pkt, coap_block1_t *block1)
Block1 option getter.
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.
uint32_t blknum
block number
Definition: nanocoap.h:300
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:823
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:481
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:531
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:247
static unsigned coap_szx2size(unsigned szx)
Helper to decode SZX value to size in bytes.
Definition: nanocoap.h:772
void * context
ptr to user defined context data
Definition: nanocoap.h:292
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.
uint16_t payload_len
length of payload
Definition: nanocoap.h:269
CoAP option array entry.
Definition: nanocoap.h:257
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:715
uint8_t * token
pointer to token
Definition: nanocoap.h:267
uint8_t code
CoAP code (e.g.m 205)
Definition: nanocoap.h:249
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:736
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:513
Type for CoAP resource entry.
Definition: nanocoap.h:288
static unsigned coap_get_total_hdr_len(coap_pkt_t *pkt)
Get the total header length (4-byte header + token length)
Definition: nanocoap.h:883
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:266
static void coap_clear_observe(coap_pkt_t *pkt)
Clears the observe option value from a packet.
Definition: nanocoap.h:960
unsigned coap_get_content_type(coap_pkt_t *pkt)
Get content type from packet.
static uint8_t coap_code(unsigned class, unsigned detail)
Encode given code class and code detail to raw code.
Definition: nanocoap.h:896
uint16_t opt_num
full CoAP option number
Definition: nanocoap.h:258
unistd.h wrapper for MSP430
#define assert(cond)
abort the program if assertion is false
Definition: assert.h:104
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:907
ssize_t coap_opt_finish(coap_pkt_t *pkt, uint16_t flags)
Finalizes options as required and prepares for payload.
unsigned methods
OR&#39;ed methods this resource allows.
Definition: nanocoap.h:290
static unsigned coap_get_ver(coap_pkt_t *pkt)
Get the CoAP version number.
Definition: nanocoap.h:784
const char * path
URI path of resource.
Definition: nanocoap.h:289
uint16_t options_len
length of options array
Definition: nanocoap.h:270
uint8_t ver_t_tkl
version, token, token length
Definition: nanocoap.h:248
Block1 helper struct.
Definition: nanocoap.h:298
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.
static unsigned coap_get_id(coap_pkt_t *pkt)
Get the message ID of the given CoAP packet.
Definition: nanocoap.h:871
size_t offset
offset of received data
Definition: nanocoap.h:299
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:972
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:497
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:811
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)
uint8_t * payload
pointer to payload
Definition: nanocoap.h:268
static unsigned coap_method2flag(unsigned code)
Convert message code (request method) into a corresponding bit field.
Definition: nanocoap.h:936
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:695
ssize_t coap_opt_add_uint(coap_pkt_t *pkt, uint16_t optnum, uint32_t value)
Encode the given uint option into pkt.
uint16_t offset
offset in packet
Definition: nanocoap.h:259
unsigned szx
szx value
Definition: nanocoap.h:301
uint16_t id
Req/resp ID.
Definition: nanocoap.h:250
static bool coap_has_observe(coap_pkt_t *pkt)
Identifies a packet containing an observe option.
Definition: nanocoap.h:950
coap_handler_t handler
ptr to resource handler
Definition: nanocoap.h:291
static unsigned coap_get_type(coap_pkt_t *pkt)
Get the message type.
Definition: nanocoap.h:799
ssize_t(* coap_handler_t)(coap_pkt_t *pkt, uint8_t *buf, size_t len, void *context)
Resource handler type.
Definition: nanocoap.h:283
int more
-1 for no option, 0 for last block, 1 for more blocks coming
Definition: nanocoap.h:302
static unsigned coap_get_code(coap_pkt_t *pkt)
Get a message&#39;s code in decimal format ((class * 100) + detail)
Definition: nanocoap.h:859
CoAP PDU parsing context structure.
Definition: nanocoap.h:265
size_t coap_put_option(uint8_t *buf, uint16_t lastonum, uint16_t onum, 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:758
const coap_resource_t coap_resources[]
Global CoAP resource list.
static uint16_t ntohs(uint16_t v)
Convert from network byte order to host byte order, 16 bit.
Definition: byteorder.h:428