CoAP API Options Update
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.
- Add COAP_OPTIONS_SORT macro to toggle inclusion of option sorting code. Defaults to not included.
coap_opt_finish()to finalize header+options, including optional sort of options.
- Adapt gcoap API to deprecate
gcoap_opt_finish_format(), which internally calls
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.
- 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, presently triggers and assert. Alternatively, it could return a negative value.
- Advances payload ptr and decrements payload_len.
- Adds coap_optpos_t element to pkt.options and increments pkt.options_len.
'flags' is a bitwise parameter. Returns length of header+options.
- COAP_OPT_FINISH_NONE = 0 -- No flags
- COAP_OPT_FINISH_PAYLOAD = 1 -- Expect a payload; writes payload marker and decrements payload_len.
- COAP_OPT_FINISH_SORT = 2 -- Sort options; see below
The COAP_OPT_FINISH_SORT flag for coap_opt_finish() allows the user to trigger sorting of the Options in the pkt. Useful if options were not entered in option number order or otherwise not in final form for a message. The user decides when to include this flag. nanocoap itself does not need to track if a packet must be sorted.
- 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.
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, flags, 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. This means the payload likely must be moved. 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 Content-Format option from content_format, and calls coap_opt_finish(). Use COAP_FORMAT_NONE if no format and COAP_FORMAT_NO_PAYLOAD if no payload. 'flags' is unused presently and ignored. It is included for future use, to adapt to any new flags used by coap_opt_finish(). 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(pkt, payload_len, content_format) (deprecated)
If no payload or content_format is COAP_FORMAT_NONE, removes the Content-Format option. Otherwise, updates the value of the option. Then calls coap_opt_finish(). Usually sorts options. 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().