Skip to content

CoAP API Options Update

Ken Bannister edited this page May 14, 2018 · 19 revisions

Below are proposed changes to the nanocoap and gcoap APIs, primarily to support specification of CoAP options. At the highest level these changes add a nanocoap API to use coap_pkt_t to build a packet/PDU. They also adapt the gcoap API to use this new nanocoap API. The gcoap API now can be seen basically as convenience/sugar on top of the nanocoap API.

Specifics:

  • Add COAP_OPTIONS_SORT macro to toggle inclusion of option sorting code. Defaults to not included.
  • Add coap_pkt_init()
  • Add coap_opt_add_[string|buf|uint]().
  • Add coap_opt_sort() to sort options if COAP_OPTIONS_SORT defined.
  • Add coap_opt_finish() to finalize header+options.
  • Adapt gcoap API to deprecate gcoap_finish() and add gcoap_opt_finish_format(), which internally calls coap_opt_sort() and coap_opt_finish(). gcoap usually sorts options.

API Outline

coap_build_hdr(hdr, type, token, token_len, code, msgid)

Use as defined presently. Required for coap_pkt_init() below.

coap_pkt_init(pkt, buf, len, header_len)

  • Initializes coap_pkt_t. Assumes hdr* = buf*.
  • Initializes payload pointer and payload_len. These will be maintained while adding options as the location of the next option. User can query pkt.payload_len to know maximum length available for payload.

coap_opt_add_[string|buf|uint](pkt, ...)

  • Writes option data to buf at payload pointer.
  • If option number is less than previous, action depends on status of COAP_OPTIONS_SORT. If active, sets delta to 0. If not active, returns a negative value.
  • Advances payload ptr and decrements payload_len.
  • Adds element to coap_optpos_t and increments options_len.

coap_opt_sort(pkt)

Sorts options. Only useful if options are not in order or otherwise not in final form for a message. The user is responsible for calling this function if necessary. This responsibility means that the user may enter options in order and avoid the overhead of this function if they wish. It also means nanocoap itself does not need to track if a packet must be sorted. We considered addition of a 'flags' attribute to coap_pkt_t for this purpose.

  • Allocates a buffer on the stack to hold sorted options.
  • Reads each option, in option number order, and copies to stack buffer with coap_put_option().
  • Also reorders coap_pkt_t options array attribute.
  • Replaces existing options in packet buffer with stack buffer contents.
  • Updates payload ptr and payload_len.

coap_opt_finish(pkt, expect_payload)

If 'expect_payload' is true, writes payload marker and decrements payload_len. Returns length of header+options.

How gcoap uses the API

gcoap uses this basic API, and adds additional function calls to make simple messaging easy for the user. For example, gcoap_req_init() includes the request path, as this will be defined with each request. Since CoAP saves the path as an option, gcoap_req_init() stores it by calling coap_opt_add_string(). gcoap usually sorts options.

1. gcoap_req_init(), gcoap_resp_init(), gcoap_obs_init()

gcoap_req_init() and gcoap_obs_init() use coap_build_hdr and coap_pkt_init() as these create a new coap_pkt_t. gcoap_resp_init() reuses the packet from the request.

Until gcoap_finish() is removed, always adds a Content-Format option with value COAP_FORMAT_NO_PAYLOAD. This step means the unsorted options always will be at least as long as the final, sorted options. This condition means that the final options will not overlap the payload that the user already will have written.

As mentioned, gcoap_req_init() sets Uri-Path option. gcoap_obs_init() sets Observe option.

2. User adds other options as required

3. gcoap_opt_finish_format(pkt, content_format)

This step is new, and will replace gcoap_finish(). Presently, use of gcoap_finish() is troublesome because it specifies the Content-Format option after the payload has been written. So, we deprecate use of gcoap_finish() in favor of gcoap_opt_finish_format(). Currently use is optional, but after some time we can require it because it simplifies the implementation. It also allows the user to know exactly how many bytes are available for the payload.

This function sets the packet format and calls coap_opt_sort() and coap_opt_finish(). Use COAP_FORMAT_NONE if no format and COAP_FORMAT_NO_PAYLOAD if no payload. Returns the size of the PDU so far, including header and options.

4. User writes payload if necessary

Length available for the payload is the original buffer less the value returned by gcoap_opt_finish_format().

5. gcoap_finish() (deprecated)

If no payload or Content-Format option is COAP_FORMAT_NONE, removes the Content-Format option. Then calls coap_opt_sort(). Then sets pkt.payload_len as it does currently. Returns size of PDU.

It will be OK to remove this function. The only functionality remaining is to set pkt.payload_len and return the size of the PDU. However, we don't need to set payload_len because we don't need the pkt any longer. The user knows the length of the payload because they just set it, and they know the length of header+options from gcoap_opt_finish_format().

Clone this wiki locally