net/gcoap: split out the coap processing part of _on_sock_evt

This commit is contained in:
János Brodbeck 2020-11-05 16:04:02 +01:00
parent 565242f67e
commit c4e646037d
No known key found for this signature in database
GPG Key ID: 65C193B0D8D1BCE6

View File

@ -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);
}