net: lib: coap: Add resources length based variants
Add length variant for the well known core resource and parsing. Signed-off-by: Pieter De Gendt <pieter.degendt@basalte.be>
This commit is contained in:
parent
1158c5dc01
commit
bea29cf631
|
@ -583,12 +583,36 @@ int coap_packet_append_payload(struct coap_packet *cpkt, const uint8_t *payload,
|
|||
*
|
||||
* @param cpkt Packet received
|
||||
* @param resources Array of known resources
|
||||
* @param resources_len Number of resources in the array
|
||||
* @param options Parsed options from coap_packet_parse()
|
||||
* @param opt_num Number of options
|
||||
* @param addr Peer address
|
||||
* @param addr_len Peer address length
|
||||
*
|
||||
* @retval 0 in case of success.
|
||||
* @retval >= 0 in case of success.
|
||||
* @retval -ENOTSUP in case of invalid request code.
|
||||
* @retval -EPERM in case resource handler is not implemented.
|
||||
* @retval -ENOENT in case the resource is not found.
|
||||
*/
|
||||
int coap_handle_request_len(struct coap_packet *cpkt,
|
||||
struct coap_resource *resources,
|
||||
size_t resources_len,
|
||||
struct coap_option *options,
|
||||
uint8_t opt_num,
|
||||
struct sockaddr *addr, socklen_t addr_len);
|
||||
|
||||
/**
|
||||
* @brief When a request is received, call the appropriate methods of
|
||||
* the matching resources.
|
||||
*
|
||||
* @param cpkt Packet received
|
||||
* @param resources Array of known resources (terminated with empty resource)
|
||||
* @param options Parsed options from coap_packet_parse()
|
||||
* @param opt_num Number of options
|
||||
* @param addr Peer address
|
||||
* @param addr_len Peer address length
|
||||
*
|
||||
* @retval >= 0 in case of success.
|
||||
* @retval -ENOTSUP in case of invalid request code.
|
||||
* @retval -EPERM in case resource handler is not implemented.
|
||||
* @retval -ENOENT in case the resource is not found.
|
||||
|
|
|
@ -24,15 +24,45 @@ extern "C" {
|
|||
|
||||
/**
|
||||
* This resource should be added before all other resources that should be
|
||||
* included in the responses of the .well-known/core resource.
|
||||
* included in the responses of the .well-known/core resource if is to be used with
|
||||
* coap_well_known_core_get.
|
||||
*/
|
||||
#define COAP_WELL_KNOWN_CORE_PATH \
|
||||
((const char * const[]) { ".well-known", "core", NULL })
|
||||
|
||||
/**
|
||||
* @brief Build a CoAP response for a .well-known/core CoAP request.
|
||||
*
|
||||
* @param resource Array of known resources, terminated with an empty resource
|
||||
* @param request A pointer to the .well-known/core CoAP request
|
||||
* @param response A pointer to a CoAP response, will be initialized
|
||||
* @param data A data pointer to be used to build the CoAP response
|
||||
* @param data_len The maximum length of the data buffer
|
||||
*
|
||||
* @return 0 in case of success or negative in case of error.
|
||||
*/
|
||||
int coap_well_known_core_get(struct coap_resource *resource,
|
||||
struct coap_packet *request,
|
||||
const struct coap_packet *request,
|
||||
struct coap_packet *response,
|
||||
uint8_t *data, uint16_t len);
|
||||
uint8_t *data, uint16_t data_len);
|
||||
|
||||
/**
|
||||
* @brief Build a CoAP response for a .well-known/core CoAP request.
|
||||
*
|
||||
* @param resources Array of known resources
|
||||
* @param resources_len Number of resources in the array
|
||||
* @param request A pointer to the .well-known/core CoAP request
|
||||
* @param response A pointer to a CoAP response, will be initialized
|
||||
* @param data A data pointer to be used to build the CoAP response
|
||||
* @param data_len The maximum length of the data buffer
|
||||
*
|
||||
* @return 0 in case of success or negative in case of error.
|
||||
*/
|
||||
int coap_well_known_core_get_len(struct coap_resource *resources,
|
||||
size_t resources_len,
|
||||
const struct coap_packet *request,
|
||||
struct coap_packet *response,
|
||||
uint8_t *data, uint16_t data_len);
|
||||
|
||||
/**
|
||||
* In case you want to add attributes to the resources included in the
|
||||
|
|
|
@ -1147,29 +1147,28 @@ static bool is_request(const struct coap_packet *cpkt)
|
|||
return !(code & ~COAP_REQUEST_MASK);
|
||||
}
|
||||
|
||||
int coap_handle_request(struct coap_packet *cpkt,
|
||||
struct coap_resource *resources,
|
||||
struct coap_option *options,
|
||||
uint8_t opt_num,
|
||||
struct sockaddr *addr, socklen_t addr_len)
|
||||
int coap_handle_request_len(struct coap_packet *cpkt,
|
||||
struct coap_resource *resources,
|
||||
size_t resources_len,
|
||||
struct coap_option *options,
|
||||
uint8_t opt_num,
|
||||
struct sockaddr *addr, socklen_t addr_len)
|
||||
{
|
||||
struct coap_resource *resource;
|
||||
|
||||
if (!is_request(cpkt)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME: deal with hierarchical resources */
|
||||
for (resource = resources; resource && resource->path; resource++) {
|
||||
for (size_t i = 0; i < resources_len; i++) {
|
||||
coap_method_t method;
|
||||
uint8_t code;
|
||||
|
||||
if (!uri_path_eq(cpkt, resource->path, options, opt_num)) {
|
||||
if (!uri_path_eq(cpkt, resources[i].path, options, opt_num)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
code = coap_header_get_code(cpkt);
|
||||
if (method_from_code(resource, code, &method) < 0) {
|
||||
if (method_from_code(&resources[i], code, &method) < 0) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
|
@ -1177,13 +1176,29 @@ int coap_handle_request(struct coap_packet *cpkt,
|
|||
return -EPERM;
|
||||
}
|
||||
|
||||
return method(resource, cpkt, addr, addr_len);
|
||||
return method(&resources[i], cpkt, addr, addr_len);
|
||||
}
|
||||
|
||||
NET_DBG("%d", __LINE__);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
int coap_handle_request(struct coap_packet *cpkt,
|
||||
struct coap_resource *resources,
|
||||
struct coap_option *options,
|
||||
uint8_t opt_num,
|
||||
struct sockaddr *addr, socklen_t addr_len)
|
||||
{
|
||||
size_t resources_len = 0;
|
||||
struct coap_resource *resource;
|
||||
|
||||
for (resource = resources; resource && resource->path; resource++) {
|
||||
resources_len++;
|
||||
}
|
||||
|
||||
return coap_handle_request_len(cpkt, resources, resources_len, options, opt_num, addr,
|
||||
addr_len);
|
||||
}
|
||||
|
||||
int coap_block_transfer_init(struct coap_block_context *ctx,
|
||||
enum coap_block_size block_size,
|
||||
size_t total_size)
|
||||
|
|
|
@ -432,10 +432,11 @@ int clear_more_flag(struct coap_packet *cpkt)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int coap_well_known_core_get(struct coap_resource *resource,
|
||||
struct coap_packet *request,
|
||||
struct coap_packet *response,
|
||||
uint8_t *data, uint16_t len)
|
||||
int coap_well_known_core_get_len(struct coap_resource *resources,
|
||||
size_t resources_len,
|
||||
struct coap_packet *request,
|
||||
struct coap_packet *response,
|
||||
uint8_t *data, uint16_t len)
|
||||
{
|
||||
static struct coap_block_context ctx;
|
||||
struct coap_option query;
|
||||
|
@ -446,9 +447,9 @@ int coap_well_known_core_get(struct coap_resource *resource,
|
|||
uint16_t id;
|
||||
uint8_t tkl;
|
||||
int r;
|
||||
bool more = false;
|
||||
bool more = false, first = true;
|
||||
|
||||
if (!resource || !request || !response || !data || !len) {
|
||||
if (!resources || !request || !response || !data || !len) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -505,29 +506,31 @@ int coap_well_known_core_get(struct coap_resource *resource,
|
|||
offset = 0;
|
||||
remaining = coap_block_size_to_bytes(ctx.block_size);
|
||||
|
||||
while (resource++ && resource->path) {
|
||||
for (size_t i = 0; i < resources_len; ++i) {
|
||||
if (!remaining) {
|
||||
more = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!match_queries_resource(resource, &query, num_queries)) {
|
||||
if (!match_queries_resource(&resources[i], &query, num_queries)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
r = format_resource(resource, response, &remaining, &offset,
|
||||
ctx.current, &more);
|
||||
if (r < 0) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ((resource + 1) && (resource + 1)->path) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
r = append_to_coap_pkt(response, ",", 1, &remaining,
|
||||
&offset, ctx.current);
|
||||
if (!r) {
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
r = format_resource(&resources[i], response, &remaining, &offset,
|
||||
ctx.current, &more);
|
||||
if (r < 0) {
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
/* Offset is the total size now, but block2 option is already
|
||||
|
@ -631,10 +634,11 @@ static int format_resource(const struct coap_resource *resource,
|
|||
return format_attributes(attributes, response);
|
||||
}
|
||||
|
||||
int coap_well_known_core_get(struct coap_resource *resource,
|
||||
struct coap_packet *request,
|
||||
struct coap_packet *response,
|
||||
uint8_t *data, uint16_t len)
|
||||
int coap_well_known_core_get_len(struct coap_resource *resources,
|
||||
size_t resources_len,
|
||||
const struct coap_packet *request,
|
||||
struct coap_packet *response,
|
||||
uint8_t *data, uint16_t data_len)
|
||||
{
|
||||
struct coap_option query;
|
||||
uint8_t token[COAP_TOKEN_MAX_LEN];
|
||||
|
@ -642,8 +646,9 @@ int coap_well_known_core_get(struct coap_resource *resource,
|
|||
uint8_t tkl;
|
||||
uint8_t num_queries;
|
||||
int r;
|
||||
bool first = true;
|
||||
|
||||
if (!resource || !request || !response || !data || !len) {
|
||||
if (!resources || !request || !response || !data || !data_len) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -660,7 +665,7 @@ int coap_well_known_core_get(struct coap_resource *resource,
|
|||
|
||||
num_queries = r;
|
||||
|
||||
r = coap_packet_init(response, data, len, COAP_VERSION_1, COAP_TYPE_ACK,
|
||||
r = coap_packet_init(response, data, data_len, COAP_VERSION_1, COAP_TYPE_ACK,
|
||||
tkl, token, COAP_RESPONSE_CODE_CONTENT, id);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
|
@ -677,28 +682,50 @@ int coap_well_known_core_get(struct coap_resource *resource,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
while (resource++ && resource->path) {
|
||||
if (!match_queries_resource(resource, &query, num_queries)) {
|
||||
for (size_t i = 0; i < resources_len; ++i) {
|
||||
if (!match_queries_resource(&resources[i], &query, num_queries)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
r = format_resource(resource, response);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
if ((resource + 1)->path) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
r = append_u8(response, (uint8_t) ',');
|
||||
if (!r) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
r = format_resource(&resources[i], response);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int coap_well_known_core_get(struct coap_resource *resource,
|
||||
const struct coap_packet *request,
|
||||
struct coap_packet *response,
|
||||
uint8_t *data, uint16_t data_len)
|
||||
{
|
||||
struct coap_resource *resources = resource + 1;
|
||||
size_t resources_len = 0;
|
||||
|
||||
if (resource == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
while (resources[resources_len].path) {
|
||||
resources_len++;
|
||||
}
|
||||
|
||||
return coap_well_known_core_get_len(resources, resources_len, request, response, data,
|
||||
data_len);
|
||||
}
|
||||
|
||||
/* Exposing some of the APIs to CoAP unit tests in tests/net/lib/coap */
|
||||
#if defined(CONFIG_COAP_TEST_API_ENABLE)
|
||||
bool _coap_match_path_uri(const char * const *path,
|
||||
|
|
Loading…
Reference in a new issue