net/gcoap: Use nanocoap options API
Observe still uses coap_pkt_t attribute.
This commit is contained in:
parent
fa5ab4eeb6
commit
f0b966d65d
@ -253,26 +253,28 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Size of the buffer used to write options, other than Uri-Path, in a
|
* @brief Reduce payload length by this value for a request created with
|
||||||
* request
|
* gcoap_req_init()
|
||||||
*
|
*
|
||||||
* Accommodates Content-Format and Uri-Queries
|
* Accommodates writing Content-Format option in gcoap_finish()
|
||||||
*/
|
*/
|
||||||
#define GCOAP_REQ_OPTIONS_BUF (40)
|
#define GCOAP_REQ_OPTIONS_BUF (4)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Size of the buffer used to write options in a response
|
* @brief Reduce payload length by this value for a respons created with
|
||||||
|
* gcoap_resp_init()
|
||||||
*
|
*
|
||||||
* Accommodates Content-Format.
|
* Accommodates writing Content-Format option in gcoap_finish()
|
||||||
*/
|
*/
|
||||||
#define GCOAP_RESP_OPTIONS_BUF (8)
|
#define GCOAP_RESP_OPTIONS_BUF (4)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Size of the buffer used to write options in an Observe notification
|
* @brief Reduce payload length by this value for an observe notification
|
||||||
|
* created with gcoap_obs_init()
|
||||||
*
|
*
|
||||||
* Accommodates Content-Format and Observe.
|
* Accommodates writing Content-Format option in gcoap_finish()
|
||||||
*/
|
*/
|
||||||
#define GCOAP_OBS_OPTIONS_BUF (8)
|
#define GCOAP_OBS_OPTIONS_BUF (4)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Maximum number of requests awaiting a response
|
* @brief Maximum number of requests awaiting a response
|
||||||
@ -506,6 +508,11 @@ void gcoap_register_listener(gcoap_listener_t *listener);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initializes a CoAP request PDU on a buffer.
|
* @brief Initializes a CoAP request PDU on a buffer.
|
||||||
|
|
||||||
|
* @warning After you use this function, you may not add Options with option
|
||||||
|
* number less than COAP_OPT_URI_PATH. Otherwise, use the struct-based API
|
||||||
|
* described with @link net_nanocoap nanocoap @endlink to initialize the
|
||||||
|
* message. See the implementation of gcoap_req_init() itself as an example.
|
||||||
*
|
*
|
||||||
* @param[out] pdu Request metadata
|
* @param[out] pdu Request metadata
|
||||||
* @param[out] buf Buffer containing the PDU
|
* @param[out] buf Buffer containing the PDU
|
||||||
@ -525,8 +532,14 @@ int gcoap_req_init(coap_pkt_t *pdu, uint8_t *buf, size_t len,
|
|||||||
/**
|
/**
|
||||||
* @brief Finishes formatting a CoAP PDU after the payload has been written
|
* @brief Finishes formatting a CoAP PDU after the payload has been written
|
||||||
*
|
*
|
||||||
* Assumes the PDU has been initialized with gcoap_req_init() or
|
* Assumes the PDU has been initialized with a gcoap_xxx_init() function, like
|
||||||
* gcoap_resp_init().
|
* gcoap_req_init().
|
||||||
|
*
|
||||||
|
* @warning To use this function, you only may have added an Option with
|
||||||
|
* option number less than COAP_OPT_CONTENT_FORMAT. Otherwise, use the
|
||||||
|
* struct-based API described with @link net_nanocoap nanocoap. @endlink With
|
||||||
|
* this API, you specify the format with coap_opt_add_uint(), prepare for the
|
||||||
|
* payload with coap_opt_finish(), and then write the payload.
|
||||||
*
|
*
|
||||||
* @param[in,out] pdu Request metadata
|
* @param[in,out] pdu Request metadata
|
||||||
* @param[in] payload_len Length of the payload, or 0 if none
|
* @param[in] payload_len Length of the payload, or 0 if none
|
||||||
|
|||||||
@ -38,20 +38,12 @@
|
|||||||
#define GCOAP_RESOURCE_WRONG_METHOD -1
|
#define GCOAP_RESOURCE_WRONG_METHOD -1
|
||||||
#define GCOAP_RESOURCE_NO_PATH -2
|
#define GCOAP_RESOURCE_NO_PATH -2
|
||||||
|
|
||||||
/*
|
|
||||||
* gcoap internal Content-Format option value. Not intended for use in a
|
|
||||||
* transmitted packet. Must be a 3-byte unsigned value.
|
|
||||||
*/
|
|
||||||
#define COAP_FORMAT_NO_PAYLOAD (UINT16_MAX + 1)
|
|
||||||
|
|
||||||
/* Internal functions */
|
/* Internal functions */
|
||||||
static void *_event_loop(void *arg);
|
static void *_event_loop(void *arg);
|
||||||
static void _listen(sock_udp_t *sock);
|
static void _listen(sock_udp_t *sock);
|
||||||
static ssize_t _well_known_core_handler(coap_pkt_t* pdu, uint8_t *buf, size_t len, void *ctx);
|
static ssize_t _well_known_core_handler(coap_pkt_t* pdu, uint8_t *buf, size_t len, void *ctx);
|
||||||
static ssize_t _write_options(coap_pkt_t *pdu, uint8_t *buf, size_t len);
|
|
||||||
static size_t _handle_req(coap_pkt_t *pdu, uint8_t *buf, size_t len,
|
static size_t _handle_req(coap_pkt_t *pdu, uint8_t *buf, size_t len,
|
||||||
sock_udp_ep_t *remote);
|
sock_udp_ep_t *remote);
|
||||||
static ssize_t _finish_pdu(coap_pkt_t *pdu, uint8_t *buf, size_t len);
|
|
||||||
static void _expire_request(gcoap_request_memo_t *memo);
|
static void _expire_request(gcoap_request_memo_t *memo);
|
||||||
static void _find_req_memo(gcoap_request_memo_t **memo_ptr, coap_pkt_t *pdu,
|
static void _find_req_memo(gcoap_request_memo_t **memo_ptr, coap_pkt_t *pdu,
|
||||||
const sock_udp_ep_t *remote);
|
const sock_udp_ep_t *remote);
|
||||||
@ -343,9 +335,6 @@ static size_t _handle_req(coap_pkt_t *pdu, uint8_t *buf, size_t len,
|
|||||||
memcpy(&memo->token[0], pdu->token, memo->token_len);
|
memcpy(&memo->token[0], pdu->token, memo->token_len);
|
||||||
}
|
}
|
||||||
DEBUG("gcoap: Registered observer for: %s\n", memo->resource->path);
|
DEBUG("gcoap: Registered observer for: %s\n", memo->resource->path);
|
||||||
/* generate initial notification value */
|
|
||||||
uint32_t now = xtimer_now_usec();
|
|
||||||
pdu->observe_value = (now >> GCOAP_OBS_TICK_EXPONENT) & 0xFFFFFF;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (coap_get_observe(pdu) == COAP_OBS_DEREGISTER) {
|
} else if (coap_get_observe(pdu) == COAP_OBS_DEREGISTER) {
|
||||||
@ -429,29 +418,6 @@ static int _find_resource(coap_pkt_t *pdu, const coap_resource_t **resource_ptr,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Finishes handling a PDU -- write options and reposition payload.
|
|
||||||
*
|
|
||||||
* Returns the size of the PDU within the buffer, or < 0 on error.
|
|
||||||
*/
|
|
||||||
static ssize_t _finish_pdu(coap_pkt_t *pdu, uint8_t *buf, size_t len)
|
|
||||||
{
|
|
||||||
ssize_t hdr_len = _write_options(pdu, buf, len);
|
|
||||||
DEBUG("gcoap: header length: %i\n", (int)hdr_len);
|
|
||||||
|
|
||||||
if (hdr_len > 0) {
|
|
||||||
/* move payload over unused space after options */
|
|
||||||
if (pdu->payload_len) {
|
|
||||||
memmove(buf + hdr_len, pdu->payload, pdu->payload_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
return hdr_len + pdu->payload_len;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return -1; /* generic failure code */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Finds the memo for an outstanding request within the _coap_state.open_reqs
|
* Finds the memo for an outstanding request within the _coap_state.open_reqs
|
||||||
* array. Matches on remote endpoint and token.
|
* array. Matches on remote endpoint and token.
|
||||||
@ -535,69 +501,6 @@ static ssize_t _well_known_core_handler(coap_pkt_t* pdu, uint8_t *buf, size_t le
|
|||||||
return gcoap_finish(pdu, (size_t)plen, COAP_FORMAT_LINK);
|
return gcoap_finish(pdu, (size_t)plen, COAP_FORMAT_LINK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Creates CoAP options and sets payload marker, if any.
|
|
||||||
*
|
|
||||||
* Returns length of header + options, or -EINVAL on illegal path.
|
|
||||||
*/
|
|
||||||
static ssize_t _write_options(coap_pkt_t *pdu, uint8_t *buf, size_t len)
|
|
||||||
{
|
|
||||||
uint8_t last_optnum = 0;
|
|
||||||
(void)len;
|
|
||||||
|
|
||||||
uint8_t *bufpos = buf + coap_get_total_hdr_len(pdu); /* position for write */
|
|
||||||
|
|
||||||
/* Observe for notification or registration response */
|
|
||||||
if (coap_get_code_class(pdu) == COAP_CLASS_SUCCESS && coap_has_observe(pdu)) {
|
|
||||||
uint32_t nval = htonl(pdu->observe_value);
|
|
||||||
uint8_t *nbyte = (uint8_t *)&nval;
|
|
||||||
unsigned i;
|
|
||||||
/* find address of non-zero MSB; max 3 bytes */
|
|
||||||
for (i = 1; i < 4; i++) {
|
|
||||||
if (*(nbyte+i) > 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bufpos += coap_put_option(bufpos, last_optnum, COAP_OPT_OBSERVE,
|
|
||||||
nbyte+i, 4-i);
|
|
||||||
last_optnum = COAP_OPT_OBSERVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Uri-Path for request */
|
|
||||||
if (coap_get_code_class(pdu) == COAP_CLASS_REQ) {
|
|
||||||
size_t url_len = strlen((char *)pdu->url);
|
|
||||||
if (url_len) {
|
|
||||||
if (pdu->url[0] != '/') {
|
|
||||||
DEBUG("gcoap: _write_options: path does not start with '/'\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
bufpos += coap_opt_put_uri_path(bufpos, last_optnum,
|
|
||||||
(char *)pdu->url);
|
|
||||||
last_optnum = COAP_OPT_URI_PATH;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Content-Format */
|
|
||||||
if (pdu->content_type != COAP_FORMAT_NONE) {
|
|
||||||
bufpos += coap_put_option_ct(bufpos, last_optnum, pdu->content_type);
|
|
||||||
last_optnum = COAP_OPT_CONTENT_FORMAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Uri-query for requests */
|
|
||||||
if (coap_get_code_class(pdu) == COAP_CLASS_REQ) {
|
|
||||||
bufpos += coap_opt_put_uri_query(bufpos, last_optnum,
|
|
||||||
(char *)pdu->qs);
|
|
||||||
/* uncomment when further options are added below ... */
|
|
||||||
/* last_optnum = COAP_OPT_URI_QUERY; */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* write payload marker */
|
|
||||||
if (pdu->payload_len) {
|
|
||||||
*bufpos++ = GCOAP_PAYLOAD_MARKER;
|
|
||||||
}
|
|
||||||
return bufpos - buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find registered observer for a remote address and port.
|
* Find registered observer for a remote address and port.
|
||||||
*
|
*
|
||||||
@ -729,11 +632,7 @@ int gcoap_req_init(coap_pkt_t *pdu, uint8_t *buf, size_t len,
|
|||||||
{
|
{
|
||||||
assert((path != NULL) && (path[0] == '/'));
|
assert((path != NULL) && (path[0] == '/'));
|
||||||
|
|
||||||
(void)len;
|
|
||||||
|
|
||||||
pdu->hdr = (coap_hdr_t *)buf;
|
pdu->hdr = (coap_hdr_t *)buf;
|
||||||
memset(pdu->url, 0, NANOCOAP_URL_MAX);
|
|
||||||
memset(pdu->qs, 0, NANOCOAP_QS_MAX);
|
|
||||||
|
|
||||||
/* generate token */
|
/* generate token */
|
||||||
#if GCOAP_TOKENLEN
|
#if GCOAP_TOKENLEN
|
||||||
@ -754,15 +653,8 @@ int gcoap_req_init(coap_pkt_t *pdu, uint8_t *buf, size_t len,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (hdrlen > 0) {
|
if (hdrlen > 0) {
|
||||||
/* Reserve some space between the header and payload to write options later */
|
coap_pkt_init(pdu, buf, len - GCOAP_REQ_OPTIONS_BUF, hdrlen);
|
||||||
pdu->payload = buf + coap_get_total_hdr_len(pdu) + strlen(path)
|
coap_opt_add_string(pdu, COAP_OPT_URI_PATH, path, '/');
|
||||||
+ GCOAP_REQ_OPTIONS_BUF;
|
|
||||||
/* Payload length really zero at this point, but we set this to the available
|
|
||||||
* length in the buffer. Allows us to reconstruct buffer length later. */
|
|
||||||
pdu->payload_len = len - (pdu->payload - buf);
|
|
||||||
pdu->content_type = COAP_FORMAT_NONE;
|
|
||||||
|
|
||||||
memcpy(&pdu->url[0], path, strlen(path));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -771,14 +663,43 @@ int gcoap_req_init(coap_pkt_t *pdu, uint8_t *buf, size_t len,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Assumes pdu.payload_len attribute was reduced in gcoap_xxx_init() to
|
||||||
|
* ensure enough space in PDU buffer to write Content-Format option and
|
||||||
|
* payload marker here.
|
||||||
|
*/
|
||||||
ssize_t gcoap_finish(coap_pkt_t *pdu, size_t payload_len, unsigned format)
|
ssize_t gcoap_finish(coap_pkt_t *pdu, size_t payload_len, unsigned format)
|
||||||
{
|
{
|
||||||
/* reconstruct full PDU buffer length */
|
assert( !(pdu->options_len) ||
|
||||||
size_t len = pdu->payload_len + (pdu->payload - (uint8_t *)pdu->hdr);
|
!(payload_len) ||
|
||||||
|
(format == COAP_FORMAT_NONE) ||
|
||||||
|
(pdu->options[pdu->options_len-1].opt_num < COAP_OPT_CONTENT_FORMAT));
|
||||||
|
|
||||||
pdu->content_type = format;
|
if (payload_len) {
|
||||||
pdu->payload_len = payload_len;
|
/* determine Content-Format option length */
|
||||||
return _finish_pdu(pdu, (uint8_t *)pdu->hdr, len);
|
unsigned format_optlen = 1;
|
||||||
|
if (format == COAP_FORMAT_NONE) {
|
||||||
|
format_optlen = 0;
|
||||||
|
}
|
||||||
|
else if (format > 255) {
|
||||||
|
format_optlen = 3;
|
||||||
|
}
|
||||||
|
else if (format > 0) {
|
||||||
|
format_optlen = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* move payload to accommodate option and payload marker */
|
||||||
|
memmove(pdu->payload+format_optlen+1, pdu->payload, payload_len);
|
||||||
|
|
||||||
|
if (format_optlen) {
|
||||||
|
coap_opt_add_uint(pdu, COAP_OPT_CONTENT_FORMAT, format);
|
||||||
|
}
|
||||||
|
*pdu->payload++ = 0xFF;
|
||||||
|
}
|
||||||
|
/* must write option before updating PDU with actual length */
|
||||||
|
pdu->payload_len = payload_len;
|
||||||
|
|
||||||
|
return pdu->payload_len + (pdu->payload - (uint8_t *)pdu->hdr);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t gcoap_req_send(const uint8_t *buf, size_t len, const ipv6_addr_t *addr,
|
size_t gcoap_req_send(const uint8_t *buf, size_t len, const ipv6_addr_t *addr,
|
||||||
@ -912,12 +833,18 @@ int gcoap_resp_init(coap_pkt_t *pdu, uint8_t *buf, size_t len, unsigned code)
|
|||||||
}
|
}
|
||||||
coap_hdr_set_code(pdu->hdr, code);
|
coap_hdr_set_code(pdu->hdr, code);
|
||||||
|
|
||||||
/* Reserve some space between the header and payload to write options later */
|
unsigned header_len = coap_get_total_hdr_len(pdu);
|
||||||
pdu->payload = buf + coap_get_total_hdr_len(pdu) + GCOAP_RESP_OPTIONS_BUF;
|
|
||||||
/* Payload length really zero at this point, but we set this to the available
|
pdu->options_len = 0;
|
||||||
* length in the buffer. Allows us to reconstruct buffer length later. */
|
pdu->payload = buf + header_len;
|
||||||
pdu->payload_len = len - (pdu->payload - buf);
|
pdu->payload_len = len - header_len - GCOAP_RESP_OPTIONS_BUF;
|
||||||
pdu->content_type = COAP_FORMAT_NONE;
|
|
||||||
|
if (coap_get_observe(pdu) == COAP_OBS_REGISTER) {
|
||||||
|
/* generate initial notification value */
|
||||||
|
uint32_t now = xtimer_now_usec();
|
||||||
|
pdu->observe_value = (now >> GCOAP_OBS_TICK_EXPONENT) & 0xFFFFFF;
|
||||||
|
coap_opt_add_uint(pdu, COAP_OPT_OBSERVE, pdu->observe_value);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -939,15 +866,11 @@ int gcoap_obs_init(coap_pkt_t *pdu, uint8_t *buf, size_t len,
|
|||||||
memo->token_len, COAP_CODE_CONTENT, msgid);
|
memo->token_len, COAP_CODE_CONTENT, msgid);
|
||||||
|
|
||||||
if (hdrlen > 0) {
|
if (hdrlen > 0) {
|
||||||
|
coap_pkt_init(pdu, buf, len - GCOAP_OBS_OPTIONS_BUF, hdrlen);
|
||||||
|
|
||||||
uint32_t now = xtimer_now_usec();
|
uint32_t now = xtimer_now_usec();
|
||||||
pdu->observe_value = (now >> GCOAP_OBS_TICK_EXPONENT) & 0xFFFFFF;
|
pdu->observe_value = (now >> GCOAP_OBS_TICK_EXPONENT) & 0xFFFFFF;
|
||||||
|
coap_opt_add_uint(pdu, COAP_OPT_OBSERVE, pdu->observe_value);
|
||||||
/* Reserve some space between the header and payload to write options later */
|
|
||||||
pdu->payload = buf + coap_get_total_hdr_len(pdu) + GCOAP_OBS_OPTIONS_BUF;
|
|
||||||
/* Payload length really zero at this point, but we set this to the available
|
|
||||||
* length in the buffer. Allows us to reconstruct buffer length later. */
|
|
||||||
pdu->payload_len = len - (pdu->payload - buf);
|
|
||||||
pdu->content_type = COAP_FORMAT_NONE;
|
|
||||||
|
|
||||||
return GCOAP_OBS_INIT_OK;
|
return GCOAP_OBS_INIT_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user