diff --git a/pkg/nanocoap/Makefile b/pkg/nanocoap/Makefile index 1303628ae4bc..d69913484677 100644 --- a/pkg/nanocoap/Makefile +++ b/pkg/nanocoap/Makefile @@ -1,6 +1,6 @@ PKG_NAME=nanocoap PKG_URL=https://github.com/kaspar030/sock -PKG_VERSION=1bba8bb16463914266dd5a04fe2a3eac4ee129ae +PKG_VERSION=fc0a9470536bc760998827a6dc05d7dedf7b93ad PKG_LICENSE=LGPL-2.1 .PHONY: all diff --git a/sys/include/net/gcoap.h b/sys/include/net/gcoap.h index 0c4c4c2070c7..e4b33d8030fb 100644 --- a/sys/include/net/gcoap.h +++ b/sys/include/net/gcoap.h @@ -242,9 +242,9 @@ extern "C" { * @brief Size of the buffer used to write options, other than Uri-Path, in a * request * - * Accommodates Content-Format. + * Accommodates Content-Format and Uri-Queries */ -#define GCOAP_REQ_OPTIONS_BUF (8) +#define GCOAP_REQ_OPTIONS_BUF (40) /** * @brief Size of the buffer used to write options in a response @@ -654,6 +654,23 @@ uint8_t gcoap_op_state(void); */ int gcoap_get_resource_list(void *buf, size_t maxlen, uint8_t cf); +/** + * @brief Adds a single Uri-Query option to a CoAP request + * + * To add multiple Uri-Query options, simply call this function multiple times. + * The Uri-Query options will be added in the order those calls. + * + * @param[out] pdu The package that is being build + * @param[in] key Key to add to the query string + * @param[in] val Value to assign to @p key (may be NULL) + * + * @pre ((pdu != NULL) && (key != NULL)) + * + * @return overall length of new query string + * @return -1 on error + */ +int gcoap_add_qstring(coap_pkt_t *pdu, const char *key, const char *val); + #ifdef __cplusplus } #endif diff --git a/sys/net/application_layer/coap/gcoap.c b/sys/net/application_layer/coap/gcoap.c index a7fbcdc8dd4c..1dfc6fd6437d 100644 --- a/sys/net/application_layer/coap/gcoap.c +++ b/sys/net/application_layer/coap/gcoap.c @@ -440,7 +440,8 @@ static ssize_t _write_options(coap_pkt_t *pdu, uint8_t *buf, size_t len) DEBUG("gcoap: _write_options: path does not start with '/'\n"); return -EINVAL; } - bufpos += coap_put_option_url(bufpos, last_optnum, (char *)&pdu->url[0]); + bufpos += coap_put_option_uri(bufpos, last_optnum, (char *)pdu->url, + COAP_OPT_URI_PATH); last_optnum = COAP_OPT_URI_PATH; } } @@ -448,8 +449,15 @@ static ssize_t _write_options(coap_pkt_t *pdu, uint8_t *buf, size_t len) /* Content-Format */ if (pdu->content_type != COAP_FORMAT_NONE) { bufpos += coap_put_option_ct(bufpos, last_optnum, pdu->content_type); - /* uncomment when add an option after Content-Format */ - /* last_optnum = COAP_OPT_CONTENT_FORMAT; */ + last_optnum = COAP_OPT_CONTENT_FORMAT; + } + + /* Uri-query for requests */ + if (coap_get_code_class(pdu) == COAP_CLASS_REQ) { + bufpos += coap_put_option_uri(bufpos, last_optnum, (char *)pdu->qs, + COAP_OPT_URI_QUERY); + /* uncomment when further options are added below ... */ + /* last_optnum = COAP_OPT_URI_QUERY; */ } /* write payload marker */ @@ -602,6 +610,7 @@ int gcoap_req_init(coap_pkt_t *pdu, uint8_t *buf, size_t len, unsigned code, pdu->hdr = (coap_hdr_t *)buf; memset(pdu->url, 0, NANOCOAP_URL_MAX); + memset(pdu->qs, 0, NANOCOAP_QS_MAX); /* generate token */ #if GCOAP_TOKENLEN @@ -839,4 +848,28 @@ int gcoap_get_resource_list(void *buf, size_t maxlen, uint8_t cf) return (int)pos; } +int gcoap_add_qstring(coap_pkt_t *pdu, const char *key, const char *val) +{ + size_t qs_len = strlen((char *)pdu->qs); + size_t key_len = strlen(key); + size_t val_len = (val) ? (strlen(val) + 1) : 0; + + /* make sure if url_len + the new query string fit into the url buffer */ + if ((qs_len + key_len + val_len + 2) >= NANOCOAP_QS_MAX) { + return -1; + } + + pdu->qs[qs_len++] = '&'; + memcpy(&pdu->qs[qs_len], key, key_len); + qs_len += key_len; + if (val) { + pdu->qs[qs_len++] = '='; + memcpy(&pdu->qs[qs_len], val, val_len); + qs_len += val_len; + } + pdu->qs[qs_len] = '\0'; + + return (int)qs_len; +} + /** @} */