diff --git a/sys/net/application_layer/gcoap/gcoap.c b/sys/net/application_layer/gcoap/gcoap.c index 2487c44d5c3409bd8f006ab9c8294d229101d521..c3c6e1105c1992534b10db15f6c45bcf5199f0f1 100644 --- a/sys/net/application_layer/gcoap/gcoap.c +++ b/sys/net/application_layer/gcoap/gcoap.c @@ -30,6 +30,11 @@ #define ENABLE_DEBUG (0) #include "debug.h" +/* Return values used by the _find_resource function. */ +#define GCOAP_RESOURCE_FOUND 0 +#define GCOAP_RESOURCE_WRONG_METHOD -1 +#define GCOAP_RESOURCE_NO_PATH -2 + /* Internal functions */ static void *_event_loop(void *arg); static void _listen(sock_udp_t *sock); @@ -42,7 +47,7 @@ static void _expire_request(gcoap_request_memo_t *memo); 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, +static int _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); static int _find_obs_memo(gcoap_observe_memo_t **memo, sock_udp_ep_t *remote, @@ -260,19 +265,21 @@ static void _listen(sock_udp_t *sock) static size_t _handle_req(coap_pkt_t *pdu, uint8_t *buf, size_t len, sock_udp_ep_t *remote) { - coap_resource_t *resource; - gcoap_listener_t *listener; + coap_resource_t *resource = NULL; + gcoap_listener_t *listener = NULL; sock_udp_ep_t *observer = NULL; gcoap_observe_memo_t *memo = NULL; gcoap_observe_memo_t *resource_memo = NULL; - _find_resource(pdu, &resource, &listener); - if (resource == NULL) { - return gcoap_response(pdu, buf, len, COAP_CODE_PATH_NOT_FOUND); - } - else { - /* used below to ensure a memo not already recorded for the resource */ - _find_obs_memo_resource(&resource_memo, resource); + switch (_find_resource(pdu, &resource, &listener)) { + case GCOAP_RESOURCE_WRONG_METHOD: + return gcoap_response(pdu, buf, len, COAP_CODE_METHOD_NOT_ALLOWED); + case GCOAP_RESOURCE_NO_PATH: + return gcoap_response(pdu, buf, len, COAP_CODE_PATH_NOT_FOUND); + case GCOAP_RESOURCE_FOUND: + /* used below to ensure a memo not already recorded for the resource */ + _find_obs_memo_resource(&resource_memo, resource); + break; } if (coap_get_observe(pdu) == COAP_OBS_REGISTER) { @@ -349,10 +356,15 @@ static size_t _handle_req(coap_pkt_t *pdu, uint8_t *buf, size_t len, * * param[out] resource_ptr -- found resource * param[out] listener_ptr -- listener for found resource + * return `GCOAP_RESOURCE_FOUND` if the resource was found, + * `GCOAP_RESOURCE_WRONG_METHOD` if a resource was found but the method + * code didn't match and `GCOAP_RESOURCE_NO_PATH` if no matching + * resource was found. */ -static void _find_resource(coap_pkt_t *pdu, coap_resource_t **resource_ptr, +static int _find_resource(coap_pkt_t *pdu, coap_resource_t **resource_ptr, gcoap_listener_t **listener_ptr) { + int ret = GCOAP_RESOURCE_NO_PATH; unsigned method_flag = coap_method2flag(coap_get_code_detail(pdu)); /* Find path for CoAP msg among listener resources and execute callback. */ @@ -363,9 +375,6 @@ static void _find_resource(coap_pkt_t *pdu, coap_resource_t **resource_ptr, if (i) { resource++; } - if (! (resource->methods & method_flag)) { - continue; - } int res = strcmp((char *)&pdu->url[0], resource->path); if (res > 0) { @@ -376,16 +385,20 @@ static void _find_resource(coap_pkt_t *pdu, coap_resource_t **resource_ptr, break; } else { + if (! (resource->methods & method_flag)) { + ret = GCOAP_RESOURCE_WRONG_METHOD; + continue; + } + *resource_ptr = resource; *listener_ptr = listener; - return; + return GCOAP_RESOURCE_FOUND; } } listener = listener->next; } - /* resource not found */ - *resource_ptr = NULL; - *listener_ptr = NULL; + + return ret; } /*