diff --git a/sys/include/net/nanocoap.h b/sys/include/net/nanocoap.h index cf5d7fc64b..adcb940775 100644 --- a/sys/include/net/nanocoap.h +++ b/sys/include/net/nanocoap.h @@ -976,6 +976,9 @@ ssize_t coap_opt_add_opaque(coap_pkt_t *pkt, uint16_t optnum, const uint8_t *val /** * @brief Adds a single Uri-Query option in the form 'key=value' into pkt * + * @note Use this only for null-terminated string. See @ref coap_opt_add_uquery2() + * for non null-terminated string. + * * @param[in,out] pkt 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) @@ -987,6 +990,24 @@ ssize_t coap_opt_add_opaque(coap_pkt_t *pkt, uint16_t optnum, const uint8_t *val */ ssize_t coap_opt_add_uquery(coap_pkt_t *pkt, const char *key, const char *val); +/** + * @brief Adds a single Uri-Query option in the form 'key=value' into pkt + * + * + * @param[in,out] pkt The package that is being build + * @param[in] key Key to add to the query string + * @param[in] key_len Length of @p key + * @param[in] val Value to assign to @p key (may be NULL) + * @param[in] val_len Length of @p val. 0 if @p val is NULL + * + * @pre ((pkt != NULL) && (key != NULL) && (key_len > 0)) + * + * @return overall length of new query string + * @return -1 on error + */ +ssize_t coap_opt_add_uquery2(coap_pkt_t *pkt, const char *key, size_t key_len, + const char *val, size_t val_len); + /** * @brief Encode the given string as option(s) into pkt * diff --git a/sys/net/application_layer/nanocoap/nanocoap.c b/sys/net/application_layer/nanocoap/nanocoap.c index cac69efa12..a4f1a76f3c 100644 --- a/sys/net/application_layer/nanocoap/nanocoap.c +++ b/sys/net/application_layer/nanocoap/nanocoap.c @@ -846,27 +846,35 @@ ssize_t coap_opt_add_string(coap_pkt_t *pkt, uint16_t optnum, const char *string return write_len; } -ssize_t coap_opt_add_uquery(coap_pkt_t *pdu, const char *key, const char *val) +ssize_t coap_opt_add_uquery(coap_pkt_t *pkt, const char *key, const char *val) { - char qs[NANOCOAP_QS_MAX]; - size_t len = strlen(key); - size_t val_len = (val) ? (strlen(val) + 1) : 0; + return coap_opt_add_uquery2(pkt, key, strlen(key), val, val ? strlen(val) : 0); +} - /* test if the query string fits, account for the zero termination */ - if ((len + val_len + 1) >= NANOCOAP_QS_MAX) { +ssize_t coap_opt_add_uquery2(coap_pkt_t *pkt, const char *key, size_t key_len, + const char *val, size_t val_len) +{ + assert(pkt); + assert(key); + assert(key_len); + assert(!val_len || (val && val_len)); + + char qs[NANOCOAP_QS_MAX]; + size_t qs_len = key_len + ((val && val_len) ? (val_len + 1) : 0); + + /* test if the query string fits */ + if (qs_len >= NANOCOAP_QS_MAX) { return -1; } - memcpy(&qs[0], key, len); - if (val) { - qs[len] = '='; - /* the `=` character was already counted in `val_len`, so subtract it here */ - memcpy(&qs[len + 1], val, (val_len - 1)); - len += val_len; + memcpy(&qs[0], key, key_len); + if (val && val_len) { + qs[key_len] = '='; + memcpy(&qs[key_len + 1], val, val_len); } - qs[len] = '\0'; + qs[qs_len] = '\0'; - return coap_opt_add_string(pdu, COAP_OPT_URI_QUERY, qs, '&'); + return coap_opt_add_string(pkt, COAP_OPT_URI_QUERY, qs, '&'); } ssize_t coap_opt_add_opaque(coap_pkt_t *pkt, uint16_t optnum, const uint8_t *val, size_t val_len)