net/gcoap: expose creation of resource list to API

Creating the resource list is useful outside the /.well-known/core
handler, e.g. for the registration to resource directories.
This commit is contained in:
Hauke Petersen 2017-07-25 20:36:24 +02:00
parent 2296d630b4
commit 32ab8cf724
2 changed files with 68 additions and 28 deletions

View File

@ -634,6 +634,26 @@ size_t gcoap_obs_send(const uint8_t *buf, size_t len,
*/ */
uint8_t gcoap_op_state(void); uint8_t gcoap_op_state(void);
/**
* @brief Get the resource list, currently only `CoRE Link Format`
* (COAP_FORMAT_LINK) supported
*
* If @p buf := NULL, nothing will be written but the size of the resulting
* resource list is computed and returned.
*
* @param[out] buf output buffer to write resource list into, my be NULL
* @param[in] maxlen length of @p buf, ignored if @p buf is NULL
* @param[in] cf content format to use for the resource list, currently
* only COAP_FORMAT_LINK supported
*
* @todo add support for `JSON CoRE Link Format`
* @todo add support for 'CBOR CoRE Link Format`
*
* @return the number of bytes written to @p buf
* @return -1 on error
*/
int gcoap_get_resource_list(void *buf, size_t maxlen, uint8_t cf);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -398,35 +398,10 @@ static ssize_t _well_known_core_handler(coap_pkt_t* pdu, uint8_t *buf, size_t le
{ {
/* write header */ /* write header */
gcoap_resp_init(pdu, buf, len, COAP_CODE_CONTENT); gcoap_resp_init(pdu, buf, len, COAP_CODE_CONTENT);
int plen = gcoap_get_resource_list(pdu->payload, (size_t)pdu->payload_len,
/* skip the first listener, gcoap itself */ COAP_FORMAT_LINK);
gcoap_listener_t *listener = _coap_state.listeners->next;
/* write payload */
uint8_t *bufpos = pdu->payload;
while (listener) {
coap_resource_t *resource = listener->resources;
for (size_t i = 0; i < listener->resources_len; i++) {
/* Don't overwrite buffer if paths are too long. */
if (bufpos + strlen(resource->path) + 3 > buf + len) {
break;
}
if (i) {
*bufpos++ = ',';
resource++;
}
*bufpos++ = '<';
unsigned url_len = strlen(resource->path);
memcpy(bufpos, resource->path, url_len);
bufpos += url_len;
*bufpos++ = '>';
}
listener = listener->next;
}
/* response content */ /* response content */
return gcoap_finish(pdu, bufpos - pdu->payload, COAP_FORMAT_LINK); return gcoap_finish(pdu, (size_t)plen, COAP_FORMAT_LINK);
} }
/* /*
@ -819,4 +794,49 @@ uint8_t gcoap_op_state(void)
return count; return count;
} }
int gcoap_get_resource_list(void *buf, size_t maxlen, uint8_t cf)
{
assert(cf == COAP_CT_LINK_FORMAT);
#ifndef DEVELHELP
(void)cf;
#endif
/* skip the first listener, gcoap itself (we skip /.well-known/core) */
gcoap_listener_t *listener = _coap_state.listeners->next;
char *out = (char *)buf;
size_t pos = 0;
/* write payload */
while (listener) {
coap_resource_t *resource = listener->resources;
for (unsigned i = 0; i < listener->resources_len; i++) {
size_t path_len = strlen(resource->path);
if (out) {
/* only add new resources if there is space in the buffer */
if ((pos + path_len + 3) > maxlen) {
break;
}
if (i) {
out[pos++] = ',';
}
out[pos++] = '<';
memcpy(&out[pos], resource->path, path_len);
pos += path_len;
out[pos++] = '>';
}
else {
pos += (i) ? 3 : 2;
pos += path_len;
}
++resource;
}
listener = listener->next;
}
return (int)pos;
}
/** @} */ /** @} */