net/gcoap: split out the coap processing part of _on_sock_evt
This commit is contained in:
parent
565242f67e
commit
c4e646037d
@ -45,6 +45,8 @@
|
|||||||
/* Internal functions */
|
/* Internal functions */
|
||||||
static void *_event_loop(void *arg);
|
static void *_event_loop(void *arg);
|
||||||
static void _on_sock_evt(sock_udp_t *sock, sock_async_flags_t type, 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 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 void _cease_retransmission(gcoap_request_memo_t *memo);
|
||||||
static size_t _handle_req(coap_pkt_t *pdu, uint8_t *buf, size_t len,
|
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;
|
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)
|
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;
|
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;
|
gcoap_request_memo_t *memo = NULL;
|
||||||
/* Code paths that necessitate a response on the message layer can set a
|
/* 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
|
* 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;
|
int8_t messagelayer_emptyresponse_type = NO_IMMEDIATE_REPLY;
|
||||||
|
|
||||||
(void)arg;
|
ssize_t res = coap_parse(&pdu, buf, len);
|
||||||
if (type & SOCK_ASYNC_MSG_RECV) {
|
if (res < 0) {
|
||||||
ssize_t res = sock_udp_recv(sock, _listen_buf, sizeof(_listen_buf),
|
DEBUG("gcoap: parse failure: %d\n", (int)res);
|
||||||
0, &remote);
|
/* If a response, can't clear memo, but it will timeout later. */
|
||||||
if (res <= 0) {
|
return;
|
||||||
DEBUG("gcoap: udp recv failure: %d\n", (int)res);
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = coap_parse(&pdu, _listen_buf, res);
|
/* validate class and type for incoming */
|
||||||
if (res < 0) {
|
switch (coap_get_code_class(&pdu)) {
|
||||||
DEBUG("gcoap: parse failure: %d\n", (int)res);
|
/* incoming request or empty */
|
||||||
/* If a response, can't clear memo, but it will timeout later. */
|
case COAP_CLASS_REQ:
|
||||||
return;
|
if (coap_get_code_raw(&pdu) == COAP_CODE_EMPTY) {
|
||||||
}
|
/* ping request */
|
||||||
|
if (coap_get_type(&pdu) == COAP_TYPE_CON) {
|
||||||
/* validate class and type for incoming */
|
messagelayer_emptyresponse_type = COAP_TYPE_RST;
|
||||||
switch (coap_get_code_class(&pdu)) {
|
DEBUG("gcoap: Answering empty CON request with RST\n");
|
||||||
/* incoming request or empty */
|
} else if (coap_get_type(&pdu) == COAP_TYPE_ACK) {
|
||||||
case COAP_CLASS_REQ:
|
_find_req_memo(&memo, &pdu, remote, true);
|
||||||
if (coap_get_code_raw(&pdu) == COAP_CODE_EMPTY) {
|
if ((memo != NULL) && (memo->send_limit != GCOAP_SEND_LIMIT_NON)) {
|
||||||
/* ping request */
|
DEBUG("gcoap: empty ACK processed, stopping retransmissions\n");
|
||||||
if (coap_get_type(&pdu) == COAP_TYPE_CON) {
|
_cease_retransmission(memo);
|
||||||
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");
|
|
||||||
}
|
|
||||||
} else {
|
} 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) {
|
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;
|
pdu.hdr->ver_t_tkl &= 0xf0;
|
||||||
|
|
||||||
ssize_t bytes = sock_udp_send(sock, _listen_buf,
|
ssize_t bytes = sock_udp_send(sock, buf,
|
||||||
sizeof(coap_hdr_t), &remote);
|
sizeof(coap_hdr_t), remote);
|
||||||
if (bytes <= 0) {
|
if (bytes <= 0) {
|
||||||
DEBUG("gcoap: empty response failed: %d\n", (int)bytes);
|
DEBUG("gcoap: empty response failed: %d\n", (int)bytes);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user