diff --git a/sys/include/net/gcoap.h b/sys/include/net/gcoap.h index 98d22adf25..389e8305dc 100644 --- a/sys/include/net/gcoap.h +++ b/sys/include/net/gcoap.h @@ -435,7 +435,6 @@ typedef void (*gcoap_resp_handler_t)(unsigned req_state, coap_pkt_t* pdu, * @brief Extends request memo for resending a confirmable request. */ typedef struct { - sock_udp_ep_t remote_ep; /**< Remote endpoint */ uint8_t *pdu_buf; /**< Buffer containing the PDU */ size_t pdu_len; /**< Length of pdu_buf */ } gcoap_resend_t; @@ -453,6 +452,7 @@ typedef struct { gcoap_resend_t data; /**< Endpoint and PDU buffer, for resend */ } msg; /**< Request message data; if confirmable, supports resending message */ + sock_udp_ep_t remote_ep; /**< Remote endpoint */ gcoap_resp_handler_t resp_handler; /**< Callback for the response */ xtimer_t response_timer; /**< Limits wait for response */ msg_t timeout_msg; /**< For response timer */ diff --git a/sys/net/application_layer/gcoap/gcoap.c b/sys/net/application_layer/gcoap/gcoap.c index ff2c3f93e3..3aad476b57 100644 --- a/sys/net/application_layer/gcoap/gcoap.c +++ b/sys/net/application_layer/gcoap/gcoap.c @@ -35,7 +35,9 @@ static size_t _handle_req(coap_pkt_t *pdu, uint8_t *buf, size_t len, sock_udp_ep_t *remote); static ssize_t _finish_pdu(coap_pkt_t *pdu, uint8_t *buf, size_t len); static void _expire_request(gcoap_request_memo_t *memo); -static void _find_req_memo(gcoap_request_memo_t **memo_ptr, coap_pkt_t *pdu); +static bool _endpoints_equal(const sock_udp_ep_t *ep1, const sock_udp_ep_t *ep2); +static void _find_req_memo(gcoap_request_memo_t **memo_ptr, coap_pkt_t *pdu, + const sock_udp_ep_t *remote); static void _find_resource(coap_pkt_t *pdu, coap_resource_t **resource_ptr, gcoap_listener_t **listener_ptr); static int _find_observer(sock_udp_ep_t **observer, sock_udp_ep_t *remote); @@ -155,7 +157,7 @@ static void _listen(sock_udp_t *sock) /* incoming response */ else { - _find_req_memo(&memo, &pdu); + _find_req_memo(&memo, &pdu, &remote); if (memo) { xtimer_remove(&memo->response_timer); memo->state = GCOAP_MEMO_RESP; @@ -328,12 +330,14 @@ static ssize_t _finish_pdu(coap_pkt_t *pdu, uint8_t *buf, size_t len) /* * Finds the memo for an outstanding request within the _coap_state.open_reqs - * array. Matches on token. + * array. Matches on remote endpoint and token. * * memo_ptr[out] -- Registered request memo, or NULL if not found * src_pdu[in] -- PDU for token to match + * remote[in] -- Remote endpoint to match */ -static void _find_req_memo(gcoap_request_memo_t **memo_ptr, coap_pkt_t *src_pdu) +static void _find_req_memo(gcoap_request_memo_t **memo_ptr, coap_pkt_t *src_pdu, + const sock_udp_ep_t *remote) { *memo_ptr = NULL; /* no need to initialize struct; we only care about buffer contents below */ @@ -355,7 +359,8 @@ static void _find_req_memo(gcoap_request_memo_t **memo_ptr, coap_pkt_t *src_pdu) if (coap_get_token_len(memo_pdu) == cmplen) { memo_pdu->token = &memo_pdu->hdr->data[0]; - if (memcmp(src_pdu->token, memo_pdu->token, cmplen) == 0) { + if ((memcmp(src_pdu->token, memo_pdu->token, cmplen) == 0) + && _endpoints_equal(&memo->remote_ep, remote)) { *memo_ptr = memo; break; } @@ -461,6 +466,24 @@ static ssize_t _write_options(coap_pkt_t *pdu, uint8_t *buf, size_t len) return bufpos - buf; } +static bool _endpoints_equal(const sock_udp_ep_t *ep1, const sock_udp_ep_t *ep2) +{ + if (ep1->family != ep2->family) { + return false; + } + if (ep1->port != ep2->port) { + return false; + } + + switch (ep1->family) { + case AF_INET6: + return memcmp(&ep1->addr.ipv6[0], &ep2->addr.ipv6[0], 16) == 0; + case AF_INET: + return ep1->addr.ipv4_u32 == ep2->addr.ipv4_u32; + } + return false; +} + /* * Find registered observer for a remote address and port. * @@ -475,23 +498,11 @@ static int _find_observer(sock_udp_ep_t **observer, sock_udp_ep_t *remote) int empty_slot = -1; *observer = NULL; for (unsigned i = 0; i < GCOAP_OBS_CLIENTS_MAX; i++) { - unsigned cmplen = 0; if (_coap_state.observers[i].family == AF_UNSPEC) { - cmplen = 0; empty_slot = i; } - else if (_coap_state.observers[i].family == AF_INET6) { - cmplen = 16; - } - else { - cmplen = 4; - } - if (cmplen && - memcmp(&_coap_state.observers[i].addr.ipv6[0], &remote->addr.ipv6[0], - cmplen) == 0 - && _coap_state.observers[i].port == remote->port) { - + else if (_endpoints_equal(&_coap_state.observers[i], remote)) { *observer = &_coap_state.observers[i]; break; } @@ -688,6 +699,7 @@ size_t gcoap_req_send2(const uint8_t *buf, size_t len, if (memo) { memo->send_limit = GCOAP_SEND_LIMIT_NON; memcpy(&memo->msg.hdr_buf[0], buf, GCOAP_HEADER_MAXLEN); + memcpy(&memo->remote_ep, remote, sizeof(sock_udp_ep_t)); memo->resp_handler = resp_handler; size_t res = sock_udp_send(&_sock, buf, len, remote);