From c4e646037d0c457378639f1794dab1fc2dd32f5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A1nos=20Brodbeck?= Date: Thu, 5 Nov 2020 16:04:02 +0100 Subject: [PATCH] net/gcoap: split out the coap processing part of _on_sock_evt --- sys/net/application_layer/gcoap/gcoap.c | 193 +++++++++++++----------- 1 file changed, 101 insertions(+), 92 deletions(-) diff --git a/sys/net/application_layer/gcoap/gcoap.c b/sys/net/application_layer/gcoap/gcoap.c index 641c04b417..b9e2ec05c6 100644 --- a/sys/net/application_layer/gcoap/gcoap.c +++ b/sys/net/application_layer/gcoap/gcoap.c @@ -45,6 +45,8 @@ /* Internal functions */ static void *_event_loop(void *arg); static void _on_sock_evt(sock_udp_t *sock, sock_async_flags_t type, void *arg); +static void _process_coap_pdu(sock_udp_t *sock, sock_udp_ep_t *remote, + uint8_t *buf, size_t len); static ssize_t _well_known_core_handler(coap_pkt_t* pdu, uint8_t *buf, size_t len, void *ctx); static void _cease_retransmission(gcoap_request_memo_t *memo); static size_t _handle_req(coap_pkt_t *pdu, uint8_t *buf, size_t len, @@ -132,11 +134,28 @@ static void *_event_loop(void *arg) return 0; } -/* Handles sock events from the event queue. */ +/* Handles UDP socket events from the event queue. */ static void _on_sock_evt(sock_udp_t *sock, sock_async_flags_t type, void *arg) { - coap_pkt_t pdu; + (void)arg; sock_udp_ep_t remote; + + if (type & SOCK_ASYNC_MSG_RECV) { + ssize_t res = sock_udp_recv(sock, _listen_buf, sizeof(_listen_buf), + 0, &remote); + if (res <= 0) { + DEBUG("gcoap: udp recv failure: %d\n", (int)res); + return; + } + _process_coap_pdu(sock, &remote, _listen_buf, res); + } +} + +/* Processes and evaluates the coap pdu */ +static void _process_coap_pdu(sock_udp_t *sock, sock_udp_ep_t *remote, + uint8_t *buf, size_t len) +{ + coap_pkt_t pdu; gcoap_request_memo_t *memo = NULL; /* Code paths that necessitate a response on the message layer can set a * response type here (COAP_TYPE_RST or COAP_TYPE_ACK). If set, at the end @@ -148,99 +167,89 @@ static void _on_sock_evt(sock_udp_t *sock, sock_async_flags_t type, void *arg) */ int8_t messagelayer_emptyresponse_type = NO_IMMEDIATE_REPLY; - (void)arg; - if (type & SOCK_ASYNC_MSG_RECV) { - ssize_t res = sock_udp_recv(sock, _listen_buf, sizeof(_listen_buf), - 0, &remote); - if (res <= 0) { - DEBUG("gcoap: udp recv failure: %d\n", (int)res); - return; - } + ssize_t res = coap_parse(&pdu, buf, len); + if (res < 0) { + DEBUG("gcoap: parse failure: %d\n", (int)res); + /* If a response, can't clear memo, but it will timeout later. */ + return; + } - res = coap_parse(&pdu, _listen_buf, res); - if (res < 0) { - DEBUG("gcoap: parse failure: %d\n", (int)res); - /* If a response, can't clear memo, but it will timeout later. */ - return; - } - - /* validate class and type for incoming */ - switch (coap_get_code_class(&pdu)) { - /* incoming request or empty */ - case COAP_CLASS_REQ: - if (coap_get_code_raw(&pdu) == COAP_CODE_EMPTY) { - /* ping request */ - if (coap_get_type(&pdu) == COAP_TYPE_CON) { - messagelayer_emptyresponse_type = COAP_TYPE_RST; - DEBUG("gcoap: Answering empty CON request with RST\n"); - } else if (coap_get_type(&pdu) == COAP_TYPE_ACK) { - _find_req_memo(&memo, &pdu, &remote, true); - if ((memo != NULL) && (memo->send_limit != GCOAP_SEND_LIMIT_NON)) { - DEBUG("gcoap: empty ACK processed, stopping retransmissions\n"); - _cease_retransmission(memo); - } else { - DEBUG("gcoap: empty ACK matches no known CON, ignoring\n"); - } + /* validate class and type for incoming */ + switch (coap_get_code_class(&pdu)) { + /* incoming request or empty */ + case COAP_CLASS_REQ: + if (coap_get_code_raw(&pdu) == COAP_CODE_EMPTY) { + /* ping request */ + if (coap_get_type(&pdu) == COAP_TYPE_CON) { + messagelayer_emptyresponse_type = COAP_TYPE_RST; + DEBUG("gcoap: Answering empty CON request with RST\n"); + } else if (coap_get_type(&pdu) == COAP_TYPE_ACK) { + _find_req_memo(&memo, &pdu, remote, true); + if ((memo != NULL) && (memo->send_limit != GCOAP_SEND_LIMIT_NON)) { + DEBUG("gcoap: empty ACK processed, stopping retransmissions\n"); + _cease_retransmission(memo); } else { - DEBUG("gcoap: Ignoring empty non-CON request\n"); + DEBUG("gcoap: empty ACK matches no known CON, ignoring\n"); } + } else { + DEBUG("gcoap: Ignoring empty non-CON request\n"); } - /* normal request */ - else if (coap_get_type(&pdu) == COAP_TYPE_NON - || coap_get_type(&pdu) == COAP_TYPE_CON) { - size_t pdu_len = _handle_req(&pdu, _listen_buf, sizeof(_listen_buf), - &remote); - if (pdu_len > 0) { - ssize_t bytes = sock_udp_send(sock, _listen_buf, pdu_len, - &remote); - if (bytes <= 0) { - DEBUG("gcoap: send response failed: %d\n", (int)bytes); - } - } - } - else { - DEBUG("gcoap: illegal request type: %u\n", coap_get_type(&pdu)); - } - break; - - /* incoming response */ - case COAP_CLASS_SUCCESS: - case COAP_CLASS_CLIENT_FAILURE: - case COAP_CLASS_SERVER_FAILURE: - _find_req_memo(&memo, &pdu, &remote, false); - if (memo) { - switch (coap_get_type(&pdu)) { - case COAP_TYPE_CON: - messagelayer_emptyresponse_type = COAP_TYPE_ACK; - DEBUG("gcoap: Answering CON response with ACK\n"); - /* fall through */ - case COAP_TYPE_NON: - case COAP_TYPE_ACK: - if (memo->resp_evt_tmout.queue) { - event_timeout_clear(&memo->resp_evt_tmout); - } - memo->state = GCOAP_MEMO_RESP; - if (memo->resp_handler) { - memo->resp_handler(memo, &pdu, &remote); - } - - if (memo->send_limit >= 0) { /* if confirmable */ - *memo->msg.data.pdu_buf = 0; /* clear resend PDU buffer */ - } - memo->state = GCOAP_MEMO_UNUSED; - break; - default: - DEBUG("gcoap: illegal response type: %u\n", coap_get_type(&pdu)); - break; - } - } - else { - DEBUG("gcoap: msg not found for ID: %u\n", coap_get_id(&pdu)); - } - break; - default: - DEBUG("gcoap: illegal code class: %u\n", coap_get_code_class(&pdu)); } + /* normal request */ + else if (coap_get_type(&pdu) == COAP_TYPE_NON + || coap_get_type(&pdu) == COAP_TYPE_CON) { + size_t pdu_len = _handle_req(&pdu, _listen_buf, sizeof(_listen_buf), + remote); + if (pdu_len > 0) { + ssize_t bytes = sock_udp_send(sock, _listen_buf, pdu_len, + remote); + if (bytes <= 0) { + DEBUG("gcoap: send response failed: %d\n", (int)bytes); + } + } + } + else { + DEBUG("gcoap: illegal request type: %u\n", coap_get_type(&pdu)); + } + break; + + /* incoming response */ + case COAP_CLASS_SUCCESS: + case COAP_CLASS_CLIENT_FAILURE: + case COAP_CLASS_SERVER_FAILURE: + _find_req_memo(&memo, &pdu, remote, false); + if (memo) { + switch (coap_get_type(&pdu)) { + case COAP_TYPE_CON: + messagelayer_emptyresponse_type = COAP_TYPE_ACK; + DEBUG("gcoap: Answering CON response with ACK\n"); + /* fall through */ + case COAP_TYPE_NON: + case COAP_TYPE_ACK: + if (memo->resp_evt_tmout.queue) { + event_timeout_clear(&memo->resp_evt_tmout); + } + memo->state = GCOAP_MEMO_RESP; + if (memo->resp_handler) { + memo->resp_handler(memo, &pdu, remote); + } + + if (memo->send_limit >= 0) { /* if confirmable */ + *memo->msg.data.pdu_buf = 0; /* clear resend PDU buffer */ + } + memo->state = GCOAP_MEMO_UNUSED; + break; + default: + DEBUG("gcoap: illegal response type: %u\n", coap_get_type(&pdu)); + break; + } + } + else { + DEBUG("gcoap: msg not found for ID: %u\n", coap_get_id(&pdu)); + } + break; + default: + DEBUG("gcoap: illegal code class: %u\n", coap_get_code_class(&pdu)); } if (messagelayer_emptyresponse_type != NO_IMMEDIATE_REPLY) { @@ -253,8 +262,8 @@ static void _on_sock_evt(sock_udp_t *sock, sock_async_flags_t type, void *arg) * */ pdu.hdr->ver_t_tkl &= 0xf0; - ssize_t bytes = sock_udp_send(sock, _listen_buf, - sizeof(coap_hdr_t), &remote); + ssize_t bytes = sock_udp_send(sock, buf, + sizeof(coap_hdr_t), remote); if (bytes <= 0) { DEBUG("gcoap: empty response failed: %d\n", (int)bytes); }