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 cpkt Packet received
|
||||||
* @param resources Array of known resources
|
* @param resources Array of known resources
|
||||||
|
* @param resources_len Number of resources in the array
|
||||||
* @param options Parsed options from coap_packet_parse()
|
* @param options Parsed options from coap_packet_parse()
|
||||||
* @param opt_num Number of options
|
* @param opt_num Number of options
|
||||||
* @param addr Peer address
|
* @param addr Peer address
|
||||||
* @param addr_len Peer address length
|
* @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 -ENOTSUP in case of invalid request code.
|
||||||
* @retval -EPERM in case resource handler is not implemented.
|
* @retval -EPERM in case resource handler is not implemented.
|
||||||
* @retval -ENOENT in case the resource is not found.
|
* @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
|
* 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 \
|
#define COAP_WELL_KNOWN_CORE_PATH \
|
||||||
((const char * const[]) { ".well-known", "core", NULL })
|
((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,
|
int coap_well_known_core_get(struct coap_resource *resource,
|
||||||
struct coap_packet *request,
|
const struct coap_packet *request,
|
||||||
struct coap_packet *response,
|
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
|
* 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);
|
return !(code & ~COAP_REQUEST_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
int coap_handle_request(struct coap_packet *cpkt,
|
int coap_handle_request_len(struct coap_packet *cpkt,
|
||||||
struct coap_resource *resources,
|
struct coap_resource *resources,
|
||||||
struct coap_option *options,
|
size_t resources_len,
|
||||||
uint8_t opt_num,
|
struct coap_option *options,
|
||||||
struct sockaddr *addr, socklen_t addr_len)
|
uint8_t opt_num,
|
||||||
|
struct sockaddr *addr, socklen_t addr_len)
|
||||||
{
|
{
|
||||||
struct coap_resource *resource;
|
|
||||||
|
|
||||||
if (!is_request(cpkt)) {
|
if (!is_request(cpkt)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: deal with hierarchical resources */
|
/* 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;
|
coap_method_t method;
|
||||||
uint8_t code;
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
code = coap_header_get_code(cpkt);
|
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;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1177,13 +1176,29 @@ int coap_handle_request(struct coap_packet *cpkt,
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
}
|
}
|
||||||
|
|
||||||
return method(resource, cpkt, addr, addr_len);
|
return method(&resources[i], cpkt, addr, addr_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
NET_DBG("%d", __LINE__);
|
|
||||||
return -ENOENT;
|
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,
|
int coap_block_transfer_init(struct coap_block_context *ctx,
|
||||||
enum coap_block_size block_size,
|
enum coap_block_size block_size,
|
||||||
size_t total_size)
|
size_t total_size)
|
||||||
|
|
|
@ -432,10 +432,11 @@ int clear_more_flag(struct coap_packet *cpkt)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int coap_well_known_core_get(struct coap_resource *resource,
|
int coap_well_known_core_get_len(struct coap_resource *resources,
|
||||||
struct coap_packet *request,
|
size_t resources_len,
|
||||||
struct coap_packet *response,
|
struct coap_packet *request,
|
||||||
uint8_t *data, uint16_t len)
|
struct coap_packet *response,
|
||||||
|
uint8_t *data, uint16_t len)
|
||||||
{
|
{
|
||||||
static struct coap_block_context ctx;
|
static struct coap_block_context ctx;
|
||||||
struct coap_option query;
|
struct coap_option query;
|
||||||
|
@ -446,9 +447,9 @@ int coap_well_known_core_get(struct coap_resource *resource,
|
||||||
uint16_t id;
|
uint16_t id;
|
||||||
uint8_t tkl;
|
uint8_t tkl;
|
||||||
int r;
|
int r;
|
||||||
bool more = false;
|
bool more = false, first = true;
|
||||||
|
|
||||||
if (!resource || !request || !response || !data || !len) {
|
if (!resources || !request || !response || !data || !len) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,29 +506,31 @@ int coap_well_known_core_get(struct coap_resource *resource,
|
||||||
offset = 0;
|
offset = 0;
|
||||||
remaining = coap_block_size_to_bytes(ctx.block_size);
|
remaining = coap_block_size_to_bytes(ctx.block_size);
|
||||||
|
|
||||||
while (resource++ && resource->path) {
|
for (size_t i = 0; i < resources_len; ++i) {
|
||||||
if (!remaining) {
|
if (!remaining) {
|
||||||
more = true;
|
more = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!match_queries_resource(resource, &query, num_queries)) {
|
if (!match_queries_resource(&resources[i], &query, num_queries)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = format_resource(resource, response, &remaining, &offset,
|
if (first) {
|
||||||
ctx.current, &more);
|
first = false;
|
||||||
if (r < 0) {
|
} else {
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((resource + 1) && (resource + 1)->path) {
|
|
||||||
r = append_to_coap_pkt(response, ",", 1, &remaining,
|
r = append_to_coap_pkt(response, ",", 1, &remaining,
|
||||||
&offset, ctx.current);
|
&offset, ctx.current);
|
||||||
if (!r) {
|
if (!r) {
|
||||||
goto end;
|
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
|
/* 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);
|
return format_attributes(attributes, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
int coap_well_known_core_get(struct coap_resource *resource,
|
int coap_well_known_core_get_len(struct coap_resource *resources,
|
||||||
struct coap_packet *request,
|
size_t resources_len,
|
||||||
struct coap_packet *response,
|
const struct coap_packet *request,
|
||||||
uint8_t *data, uint16_t len)
|
struct coap_packet *response,
|
||||||
|
uint8_t *data, uint16_t data_len)
|
||||||
{
|
{
|
||||||
struct coap_option query;
|
struct coap_option query;
|
||||||
uint8_t token[COAP_TOKEN_MAX_LEN];
|
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 tkl;
|
||||||
uint8_t num_queries;
|
uint8_t num_queries;
|
||||||
int r;
|
int r;
|
||||||
|
bool first = true;
|
||||||
|
|
||||||
if (!resource || !request || !response || !data || !len) {
|
if (!resources || !request || !response || !data || !data_len) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -660,7 +665,7 @@ int coap_well_known_core_get(struct coap_resource *resource,
|
||||||
|
|
||||||
num_queries = r;
|
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);
|
tkl, token, COAP_RESPONSE_CODE_CONTENT, id);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
return r;
|
return r;
|
||||||
|
@ -677,28 +682,50 @@ int coap_well_known_core_get(struct coap_resource *resource,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (resource++ && resource->path) {
|
for (size_t i = 0; i < resources_len; ++i) {
|
||||||
if (!match_queries_resource(resource, &query, num_queries)) {
|
if (!match_queries_resource(&resources[i], &query, num_queries)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = format_resource(resource, response);
|
if (first) {
|
||||||
if (r < 0) {
|
first = false;
|
||||||
return r;
|
} else {
|
||||||
}
|
|
||||||
|
|
||||||
if ((resource + 1)->path) {
|
|
||||||
r = append_u8(response, (uint8_t) ',');
|
r = append_u8(response, (uint8_t) ',');
|
||||||
if (!r) {
|
if (!r) {
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r = format_resource(&resources[i], response);
|
||||||
|
if (r < 0) {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#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 */
|
/* Exposing some of the APIs to CoAP unit tests in tests/net/lib/coap */
|
||||||
#if defined(CONFIG_COAP_TEST_API_ENABLE)
|
#if defined(CONFIG_COAP_TEST_API_ENABLE)
|
||||||
bool _coap_match_path_uri(const char * const *path,
|
bool _coap_match_path_uri(const char * const *path,
|
||||||
|
|
Loading…
Reference in a new issue