From 6eae4ded849b959f0bee57cede47ae990b7fbb30 Mon Sep 17 00:00:00 2001 From: Ken Bannister Date: Fri, 17 Apr 2020 06:10:16 -0400 Subject: [PATCH] net/gcoap: create CoAP ping request --- sys/include/net/gcoap.h | 6 ++++- sys/net/application_layer/gcoap/gcoap.c | 32 ++++++++++++++--------- tests/unittests/tests-gcoap/tests-gcoap.c | 23 ++++++++++++++++ 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/sys/include/net/gcoap.h b/sys/include/net/gcoap.h index a0cdb03c32..d2c104a65e 100644 --- a/sys/include/net/gcoap.h +++ b/sys/include/net/gcoap.h @@ -734,10 +734,14 @@ void gcoap_register_listener(gcoap_listener_t *listener); /** * @brief Initializes a CoAP request PDU on a buffer. * + * If @p code is COAP_CODE_EMPTY, prepares a complete "CoAP ping" 4 byte empty + * message request, ready to send. + * * @param[out] pdu Request metadata * @param[out] buf Buffer containing the PDU * @param[in] len Length of the buffer - * @param[in] code Request code, one of COAP_METHOD_XXX + * @param[in] code Request code, one of COAP_METHOD_XXX or COAP_CODE_EMPTY + * to ping * @param[in] path Resource path, may be NULL * * @pre @p path must start with `/` if not NULL diff --git a/sys/net/application_layer/gcoap/gcoap.c b/sys/net/application_layer/gcoap/gcoap.c index 8121502b7c..5c3bd4ba9b 100644 --- a/sys/net/application_layer/gcoap/gcoap.c +++ b/sys/net/application_layer/gcoap/gcoap.c @@ -657,22 +657,28 @@ int gcoap_req_init(coap_pkt_t *pdu, uint8_t *buf, size_t len, pdu->hdr = (coap_hdr_t *)buf; /* generate token */ + uint16_t msgid = (uint16_t)atomic_fetch_add(&_coap_state.next_message_id, 1); + ssize_t res; + if (code) { #if CONFIG_GCOAP_TOKENLEN - uint8_t token[CONFIG_GCOAP_TOKENLEN]; - for (size_t i = 0; i < CONFIG_GCOAP_TOKENLEN; i += 4) { - uint32_t rand = random_uint32(); - memcpy(&token[i], - &rand, - (CONFIG_GCOAP_TOKENLEN - i >= 4) ? 4 : CONFIG_GCOAP_TOKENLEN - i); - } - uint16_t msgid = (uint16_t)atomic_fetch_add(&_coap_state.next_message_id, 1); - ssize_t res = coap_build_hdr(pdu->hdr, COAP_TYPE_NON, &token[0], - CONFIG_GCOAP_TOKENLEN, code, msgid); + uint8_t token[CONFIG_GCOAP_TOKENLEN]; + for (size_t i = 0; i < CONFIG_GCOAP_TOKENLEN; i += 4) { + uint32_t rand = random_uint32(); + memcpy(&token[i], + &rand, + (CONFIG_GCOAP_TOKENLEN - i >= 4) ? 4 : CONFIG_GCOAP_TOKENLEN - i); + } + res = coap_build_hdr(pdu->hdr, COAP_TYPE_NON, &token[0], + CONFIG_GCOAP_TOKENLEN, code, msgid); #else - uint16_t msgid = (uint16_t)atomic_fetch_add(&_coap_state.next_message_id, 1); - ssize_t res = coap_build_hdr(pdu->hdr, COAP_TYPE_NON, NULL, - CONFIG_GCOAP_TOKENLEN, code, msgid); + res = coap_build_hdr(pdu->hdr, COAP_TYPE_NON, NULL, + CONFIG_GCOAP_TOKENLEN, code, msgid); #endif + } + else { + /* ping request */ + res = coap_build_hdr(pdu->hdr, COAP_TYPE_CON, NULL, 0, code, msgid); + } coap_pkt_init(pdu, buf, len - CONFIG_GCOAP_REQ_OPTIONS_BUF, res); if (path != NULL) { diff --git a/tests/unittests/tests-gcoap/tests-gcoap.c b/tests/unittests/tests-gcoap/tests-gcoap.c index c458046ac8..10047629dc 100644 --- a/tests/unittests/tests-gcoap/tests-gcoap.c +++ b/tests/unittests/tests-gcoap/tests-gcoap.c @@ -203,6 +203,28 @@ static void test_gcoap__client_get_path_defer(void) TEST_ASSERT_EQUAL_STRING(&path[0], &uri[0]); } +/* + * Validate client CoAP ping empty message request. + */ +static void test_gcoap__client_ping(void) +{ + uint8_t buf[CONFIG_GCOAP_PDU_BUF_SIZE]; + coap_pkt_t pdu; + int res; + + res = gcoap_req_init(&pdu, buf, CONFIG_GCOAP_PDU_BUF_SIZE, COAP_CODE_EMPTY, + NULL); + + TEST_ASSERT_EQUAL_INT(0, res); + TEST_ASSERT_EQUAL_INT(COAP_CODE_EMPTY, coap_get_code(&pdu)); + TEST_ASSERT_EQUAL_INT(COAP_TYPE_CON, coap_get_type(&pdu)); + TEST_ASSERT_EQUAL_INT(0, coap_get_token_len(&pdu)); + + /* confirm length */ + res = coap_opt_finish(&pdu, COAP_OPT_FINISH_NONE); + TEST_ASSERT_EQUAL_INT(4, res); +} + /* * Helper for server_get tests below. * Request from libcoap example for gcoap_cli /cli/stats resource @@ -371,6 +393,7 @@ Test *tests_gcoap_tests(void) new_TestFixture(test_gcoap__client_put_req), new_TestFixture(test_gcoap__client_put_req_overfill), new_TestFixture(test_gcoap__client_get_path_defer), + new_TestFixture(test_gcoap__client_ping), new_TestFixture(test_gcoap__server_get_req), new_TestFixture(test_gcoap__server_get_resp), new_TestFixture(test_gcoap__server_con_req),