1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #18154 from benpicco/nanocoap_no-response

nanocoap: add support for no-response option
This commit is contained in:
benpicco 2022-10-15 21:16:00 +02:00 committed by GitHub
commit 4d0c533260
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 127 additions and 5 deletions

View File

@ -53,6 +53,11 @@ extern "C" {
#define COAP_OPT_BLOCK1 (27)
#define COAP_OPT_PROXY_URI (35)
#define COAP_OPT_PROXY_SCHEME (39)
/**
* @brief suppress CoAP response
* @see [RFC 7968](https://datatracker.ietf.org/doc/html/rfc7967)
*/
#define COAP_OPT_NO_RESPONSE (258)
/** @} */
/**

View File

@ -1817,6 +1817,13 @@ ssize_t coap_build_hdr(coap_hdr_t *hdr, unsigned type, uint8_t *token,
* @param[in] payload_len length of payload
*
* @returns size of reply packet on success
*
* Note that this size can be severely shortened if due to a No-Response option there
* is only an empty ACK to be sent back. The caller may just continue populating the
* payload (the space was checked to suffice), but may also skip that needless step
* if the returned length is less than the requested payload length.
*
* @returns 0 if no response should be sent due to a No-Response option in the request
* @returns <0 on error
* @returns -ENOSPC if @p rbuf too small
*/

View File

@ -240,6 +240,25 @@ ssize_t nanocoap_sock_put(nanocoap_sock_t *sock, const char *path,
const void *request, size_t len,
void *response, size_t len_max);
/**
* @brief Simple non-confirmable PUT
*
* @param[in] sock socket to use for the request
* @param[in] path remote path
* @param[in] request buffer containing the payload
* @param[in] len length of the payload to send
* @param[out] response buffer for the response, may be NULL
* @param[in] len_max length of @p response
*
* @returns length of response payload on success
* @returns 0 if the request was sent and no response buffer was provided,
* independently of success (because no response is requested in that case)
* @returns <0 on error
*/
ssize_t nanocoap_sock_put_non(nanocoap_sock_t *sock, const char *path,
const void *request, size_t len,
void *response, size_t len_max);
/**
* @brief Simple synchronous CoAP (confirmable) PUT to URL
*
@ -273,6 +292,25 @@ ssize_t nanocoap_sock_post(nanocoap_sock_t *sock, const char *path,
const void *request, size_t len,
void *response, size_t len_max);
/**
* @brief Simple non-confirmable POST
*
* @param[in] sock socket to use for the request
* @param[in] path remote path
* @param[in] request buffer containing the payload
* @param[in] len length of the payload to send
* @param[out] response buffer for the response, may be NULL
* @param[in] len_max length of @p response
*
* @returns length of response payload on success
* @returns 0 if the request was sent and no response buffer was provided,
* independently of success (because no response is requested in that case)
* @returns <0 on error
*/
ssize_t nanocoap_sock_post_non(nanocoap_sock_t *sock, const char *path,
const void *request, size_t len,
void *response, size_t len_max);
/**
* @brief Simple synchronous CoAP (confirmable) POST to URL
*

View File

@ -513,6 +513,32 @@ ssize_t coap_build_reply(coap_pkt_t *pkt, unsigned code,
}
}
uint32_t no_response;
if (coap_opt_get_uint(pkt, COAP_OPT_NO_RESPONSE, &no_response) == 0) {
const uint8_t no_response_index = (code >> 5) - 1;
/* If the handler code misbehaved here, we'd face UB otherwise */
assert(no_response_index < 7);
const uint8_t mask = 1 << no_response_index;
/* option contains bitmap of disinterest */
if (no_response & mask) {
switch (coap_get_type(pkt)) {
case COAP_TYPE_NON:
/* no response and no ACK */
return 0;
default:
/* There is an immediate ACK response, but it is an empty response */
code = COAP_CODE_EMPTY;
len = sizeof(coap_hdr_t);
tkl = 0;
payload_len = 0;
break;
}
}
}
coap_build_hdr((coap_hdr_t *)rbuf, type, coap_get_token(pkt), tkl, code,
ntohs(pkt->hdr->id));
coap_hdr_set_type((coap_hdr_t *)rbuf, type);

View File

@ -311,7 +311,7 @@ ssize_t nanocoap_sock_get(nanocoap_sock_t *sock, const char *path, void *buf, si
}
ssize_t _sock_put_post(nanocoap_sock_t *sock, const char *path, unsigned code,
const void *request, size_t len,
uint8_t type, const void *request, size_t len,
void *response, size_t max_len)
{
/* buffer for CoAP header */
@ -333,9 +333,15 @@ ssize_t _sock_put_post(nanocoap_sock_t *sock, const char *path, unsigned code,
.iov_len = max_len,
};
pktpos += coap_build_hdr(pkt.hdr, COAP_TYPE_CON, NULL, 0, code, _get_id());
pktpos += coap_build_hdr(pkt.hdr, type, NULL, 0, code, _get_id());
pktpos += coap_opt_put_uri_path(pktpos, 0, path);
if (response == NULL && type == COAP_TYPE_NON) {
/* all responses (2.xx, 4.xx and 5.xx) are ignored */
pktpos += coap_opt_put_uint(pktpos, COAP_OPT_URI_PATH,
COAP_OPT_NO_RESPONSE, 26);
}
if (len) {
/* set payload marker */
*pktpos++ = 0xFF;
@ -351,14 +357,32 @@ ssize_t nanocoap_sock_put(nanocoap_sock_t *sock, const char *path,
const void *request, size_t len,
void *response, size_t len_max)
{
return _sock_put_post(sock, path, COAP_METHOD_PUT, request, len, response, len_max);
return _sock_put_post(sock, path, COAP_METHOD_PUT, COAP_TYPE_CON, request, len,
response, len_max);
}
ssize_t nanocoap_sock_post(nanocoap_sock_t *sock, const char *path,
const void *request, size_t len,
void *response, size_t len_max)
{
return _sock_put_post(sock, path, COAP_METHOD_POST, request, len, response, len_max);
return _sock_put_post(sock, path, COAP_METHOD_POST, COAP_TYPE_CON, request, len,
response, len_max);
}
ssize_t nanocoap_sock_put_non(nanocoap_sock_t *sock, const char *path,
const void *request, size_t len,
void *response, size_t len_max)
{
return _sock_put_post(sock, path, COAP_METHOD_PUT, COAP_TYPE_NON, request, len,
response, len_max);
}
ssize_t nanocoap_sock_post_non(nanocoap_sock_t *sock, const char *path,
const void *request, size_t len,
void *response, size_t len_max)
{
return _sock_put_post(sock, path, COAP_METHOD_POST, COAP_TYPE_NON, request, len,
response, len_max);
}
static ssize_t _sock_put_post_url(const char *url, unsigned code,
@ -371,7 +395,8 @@ static ssize_t _sock_put_post_url(const char *url, unsigned code,
return res;
}
res = _sock_put_post(&sock, sock_urlpath(url), code, request, len, response, len_max);
res = _sock_put_post(&sock, sock_urlpath(url), code, COAP_TYPE_CON,
request, len, response, len_max);
nanocoap_sock_close(&sock);
return res;

View File

@ -32,12 +32,14 @@ extern int nanotest_client_cmd(int argc, char **argv);
extern int nanotest_client_url_cmd(int argc, char **argv);
extern int nanotest_server_cmd(int argc, char **argv);
extern int nanotest_client_put_cmd(int argc, char **argv);
extern int nanotest_client_put_non_cmd(int argc, char **argv);
static int _list_all_inet6(int argc, char **argv);
static const shell_command_t shell_commands[] = {
{ "client", "CoAP client", nanotest_client_cmd },
{ "url", "CoAP client URL request", nanotest_client_url_cmd },
{ "put", "experimental put", nanotest_client_put_cmd },
{ "put_non", "non-confirmable put", nanotest_client_put_non_cmd },
{ "server", "CoAP server", nanotest_server_cmd },
{ "inet6", "IPv6 addresses", _list_all_inet6 },
{ NULL, NULL, NULL }

View File

@ -298,3 +298,22 @@ int nanotest_client_put_cmd(int argc, char **argv)
nanocoap_block_request_done(&ctx);
return res;
}
int nanotest_client_put_non_cmd(int argc, char **argv)
{
int res;
if (argc < 3) {
printf("usage: %s <url> <data>\n", argv[0]);
return 1;
}
nanocoap_sock_t sock;
nanocoap_sock_url_connect(argv[1], &sock);
res = nanocoap_sock_put_non(&sock, sock_urlpath(argv[1]), argv[2], strlen(argv[2]),
NULL, 0);
nanocoap_sock_close(&sock);
return res;
}