4807ada01e
Update coap_service_send and coap_resource_send to take an optional pointer argument to the newly introduced coap_transmission_parameters. Signed-off-by: Pieter De Gendt <pieter.degendt@basalte.be>
311 lines
10 KiB
C
311 lines
10 KiB
C
/*
|
|
* Copyright (c) 2023 Basalte bv
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/** @file
|
|
* @brief CoAP Service API
|
|
*
|
|
* An API for applications to respond to CoAP requests
|
|
*/
|
|
|
|
#ifndef ZEPHYR_INCLUDE_NET_COAP_SERVICE_H_
|
|
#define ZEPHYR_INCLUDE_NET_COAP_SERVICE_H_
|
|
|
|
#include <zephyr/net/coap.h>
|
|
#include <zephyr/sys/iterable_sections.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/**
|
|
* @brief CoAP Service API
|
|
* @defgroup coap_service CoAP service API
|
|
* @ingroup networking
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* @name CoAP Service configuration flags
|
|
* @anchor COAP_SERVICE_FLAGS
|
|
* @{
|
|
*/
|
|
|
|
/** Start the service on boot. */
|
|
#define COAP_SERVICE_AUTOSTART BIT(0)
|
|
|
|
/** @} */
|
|
|
|
/** @cond INTERNAL_HIDDEN */
|
|
|
|
struct coap_service_data {
|
|
int sock_fd;
|
|
struct coap_observer observers[CONFIG_COAP_SERVICE_OBSERVERS];
|
|
struct coap_pending pending[CONFIG_COAP_SERVICE_PENDING_MESSAGES];
|
|
};
|
|
|
|
struct coap_service {
|
|
const char *name;
|
|
const char *host;
|
|
uint16_t *port;
|
|
uint8_t flags;
|
|
struct coap_resource *res_begin;
|
|
struct coap_resource *res_end;
|
|
struct coap_service_data *data;
|
|
};
|
|
|
|
#define __z_coap_service_define(_name, _host, _port, _flags, _res_begin, _res_end) \
|
|
static struct coap_service_data coap_service_data_##_name = { \
|
|
.sock_fd = -1, \
|
|
}; \
|
|
const STRUCT_SECTION_ITERABLE(coap_service, _name) = { \
|
|
.name = STRINGIFY(_name), \
|
|
.host = _host, \
|
|
.port = (uint16_t *)(_port), \
|
|
.flags = _flags, \
|
|
.res_begin = (_res_begin), \
|
|
.res_end = (_res_end), \
|
|
.data = &coap_service_data_##_name, \
|
|
}
|
|
|
|
/** @endcond */
|
|
|
|
/**
|
|
* @brief Define a static CoAP resource owned by the service named @p _service .
|
|
*
|
|
* @note The handlers registered with the resource can return a CoAP response code to reply with
|
|
* an acknowledge without any payload, nothing is sent if the return value is 0 or negative.
|
|
* As seen in the example.
|
|
*
|
|
* @code{.c}
|
|
* static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios);
|
|
*
|
|
* static int led_put(struct coap_resource *resource, struct coap_packet *request,
|
|
* struct sockaddr *addr, socklen_t addr_len)
|
|
* {
|
|
* const uint8_t *payload;
|
|
* uint16_t payload_len;
|
|
*
|
|
* payload = coap_packet_get_payload(request, &payload_len);
|
|
* if (payload_len != 1) {
|
|
* return COAP_RESPONSE_CODE_BAD_REQUEST;
|
|
* }
|
|
*
|
|
* if (gpio_pin_set_dt(&led, payload[0]) < 0) {
|
|
* return COAP_RESPONSE_CODE_INTERNAL_ERROR;
|
|
* }
|
|
*
|
|
* return COAP_RESPONSE_CODE_CHANGED;
|
|
* }
|
|
*
|
|
* COAP_RESOURCE_DEFINE(my_resource, my_service, {
|
|
* .put = led_put,
|
|
* });
|
|
* @endcode
|
|
*
|
|
* @param _name Name of the resource.
|
|
* @param _service Name of the associated service.
|
|
*/
|
|
#define COAP_RESOURCE_DEFINE(_name, _service, ...) \
|
|
STRUCT_SECTION_ITERABLE_ALTERNATE(coap_resource_##_service, coap_resource, _name) \
|
|
= __VA_ARGS__
|
|
|
|
/**
|
|
* @brief Define a CoAP service with static resources.
|
|
*
|
|
* @note The @p _host parameter can be `NULL`. If not, it is used to specify an IP address either in
|
|
* IPv4 or IPv6 format a fully-qualified hostname or a virtual host, otherwise the any address is
|
|
* used.
|
|
*
|
|
* @note The @p _port parameter must be non-`NULL`. It points to a location that specifies the port
|
|
* number to use for the service. If the specified port number is zero, then an ephemeral port
|
|
* number will be used and the actual port number assigned will be written back to memory. For
|
|
* ephemeral port numbers, the memory pointed to by @p _port must be writeable.
|
|
*
|
|
* @param _name Name of the service.
|
|
* @param _host IP address or hostname associated with the service.
|
|
* @param[inout] _port Pointer to port associated with the service.
|
|
* @param _flags Configuration flags @see @ref COAP_SERVICE_FLAGS.
|
|
*/
|
|
#define COAP_SERVICE_DEFINE(_name, _host, _port, _flags) \
|
|
extern struct coap_resource _CONCAT(_coap_resource_##_name, _list_start)[]; \
|
|
extern struct coap_resource _CONCAT(_coap_resource_##_name, _list_end)[]; \
|
|
__z_coap_service_define(_name, _host, _port, _flags, \
|
|
&_CONCAT(_coap_resource_##_name, _list_start)[0], \
|
|
&_CONCAT(_coap_resource_##_name, _list_end)[0])
|
|
|
|
/**
|
|
* @brief Count the number of CoAP services.
|
|
*
|
|
* @param[out] _dst Pointer to location where result is written.
|
|
*/
|
|
#define COAP_SERVICE_COUNT(_dst) STRUCT_SECTION_COUNT(coap_service, _dst)
|
|
|
|
/**
|
|
* @brief Count CoAP service static resources.
|
|
*
|
|
* @param _service Pointer to a service.
|
|
*/
|
|
#define COAP_SERVICE_RESOURCE_COUNT(_service) ((_service)->res_end - (_service)->res_begin)
|
|
|
|
/**
|
|
* @brief Check if service has the specified resource.
|
|
*
|
|
* @param _service Pointer to a service.
|
|
* @param _resource Pointer to a resource.
|
|
*/
|
|
#define COAP_SERVICE_HAS_RESOURCE(_service, _resource) \
|
|
((_service)->res_begin <= _resource && _resource < (_service)->res_end)
|
|
|
|
/**
|
|
* @brief Iterate over all CoAP services.
|
|
*
|
|
* @param _it Name of iterator (of type @ref coap_service)
|
|
*/
|
|
#define COAP_SERVICE_FOREACH(_it) STRUCT_SECTION_FOREACH(coap_service, _it)
|
|
|
|
/**
|
|
* @brief Iterate over static CoAP resources associated with a given @p _service.
|
|
*
|
|
* @note This macro requires that @p _service is defined with @ref COAP_SERVICE_DEFINE.
|
|
*
|
|
* @param _service Name of CoAP service
|
|
* @param _it Name of iterator (of type @ref coap_resource)
|
|
*/
|
|
#define COAP_RESOURCE_FOREACH(_service, _it) \
|
|
STRUCT_SECTION_FOREACH_ALTERNATE(coap_resource_##_service, coap_resource, _it)
|
|
|
|
/**
|
|
* @brief Iterate over all static resources associated with @p _service .
|
|
*
|
|
* @note This macro is suitable for a @p _service defined with @ref COAP_SERVICE_DEFINE.
|
|
*
|
|
* @param _service Pointer to COAP service
|
|
* @param _it Name of iterator (of type @ref coap_resource)
|
|
*/
|
|
#define COAP_SERVICE_FOREACH_RESOURCE(_service, _it) \
|
|
for (struct coap_resource *_it = (_service)->res_begin; ({ \
|
|
__ASSERT(_it <= (_service)->res_end, "unexpected list end location"); \
|
|
_it < (_service)->res_end; \
|
|
}); _it++)
|
|
|
|
/**
|
|
* @brief Start the provided @p service .
|
|
*
|
|
* @note This function is suitable for a @p service defined with @ref COAP_SERVICE_DEFINE.
|
|
*
|
|
* @param service Pointer to CoAP service
|
|
* @retval 0 in case of success.
|
|
* @retval -EALREADY in case of an already running service.
|
|
* @retval -ENOTSUP in case the server has no valid host and port configuration.
|
|
*/
|
|
int coap_service_start(const struct coap_service *service);
|
|
|
|
/**
|
|
* @brief Stop the provided @p service .
|
|
*
|
|
* @note This function is suitable for a @p service defined with @ref COAP_SERVICE_DEFINE.
|
|
*
|
|
* @param service Pointer to CoAP service
|
|
* @retval 0 in case of success.
|
|
* @retval -EALREADY in case the service isn't running.
|
|
*/
|
|
int coap_service_stop(const struct coap_service *service);
|
|
|
|
/**
|
|
* @brief Query the provided @p service running state.
|
|
*
|
|
* @note This function is suitable for a @p service defined with @ref COAP_SERVICE_DEFINE.
|
|
*
|
|
* @param service Pointer to CoAP service
|
|
* @retval 1 if the service is running
|
|
* @retval 0 if the service is stopped
|
|
* @retval negative in case of an error.
|
|
*/
|
|
int coap_service_is_running(const struct coap_service *service);
|
|
|
|
/**
|
|
* @brief Send a CoAP message from the provided @p service .
|
|
*
|
|
* @note This function is suitable for a @p service defined with @ref COAP_SERVICE_DEFINE.
|
|
*
|
|
* @param service Pointer to CoAP service
|
|
* @param cpkt CoAP Packet to send
|
|
* @param addr Peer address
|
|
* @param addr_len Peer address length
|
|
* @param params Pointer to transmission parameters structure or NULL to use default values.
|
|
* @return 0 in case of success or negative in case of error.
|
|
*/
|
|
int coap_service_send(const struct coap_service *service, const struct coap_packet *cpkt,
|
|
const struct sockaddr *addr, socklen_t addr_len,
|
|
const struct coap_transmission_parameters *params);
|
|
|
|
/**
|
|
* @brief Send a CoAP message from the provided @p resource .
|
|
*
|
|
* @note This function is suitable for a @p resource defined with @ref COAP_RESOURCE_DEFINE.
|
|
*
|
|
* @param resource Pointer to CoAP resource
|
|
* @param cpkt CoAP Packet to send
|
|
* @param addr Peer address
|
|
* @param addr_len Peer address length
|
|
* @param params Pointer to transmission parameters structure or NULL to use default values.
|
|
* @return 0 in case of success or negative in case of error.
|
|
*/
|
|
int coap_resource_send(const struct coap_resource *resource, const struct coap_packet *cpkt,
|
|
const struct sockaddr *addr, socklen_t addr_len,
|
|
const struct coap_transmission_parameters *params);
|
|
|
|
/**
|
|
* @brief Parse a CoAP observe request for the provided @p resource .
|
|
*
|
|
* @note This function is suitable for a @p resource defined with @ref COAP_RESOURCE_DEFINE.
|
|
*
|
|
* If the observe option value is equal to 0, an observer will be added, if the value is equal
|
|
* to 1, an existing observer will be removed.
|
|
*
|
|
* @param resource Pointer to CoAP resource
|
|
* @param request CoAP request to parse
|
|
* @param addr Peer address
|
|
* @return the observe option value in case of success or negative in case of error.
|
|
*/
|
|
int coap_resource_parse_observe(struct coap_resource *resource, const struct coap_packet *request,
|
|
const struct sockaddr *addr);
|
|
|
|
/**
|
|
* @brief Lookup an observer by address and remove it from the @p resource .
|
|
*
|
|
* @note This function is suitable for a @p resource defined with @ref COAP_RESOURCE_DEFINE.
|
|
*
|
|
* @param resource Pointer to CoAP resource
|
|
* @param addr Peer address
|
|
* @return 0 in case of success or negative in case of error.
|
|
*/
|
|
int coap_resource_remove_observer_by_addr(struct coap_resource *resource,
|
|
const struct sockaddr *addr);
|
|
|
|
/**
|
|
* @brief Lookup an observer by token and remove it from the @p resource .
|
|
*
|
|
* @note This function is suitable for a @p resource defined with @ref COAP_RESOURCE_DEFINE.
|
|
*
|
|
* @param resource Pointer to CoAP resource
|
|
* @param token Pointer to the token
|
|
* @param token_len Length of valid bytes in the token
|
|
* @return 0 in case of success or negative in case of error.
|
|
*/
|
|
int coap_resource_remove_observer_by_token(struct coap_resource *resource,
|
|
const uint8_t *token, uint8_t token_len);
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* ZEPHYR_INCLUDE_NET_COAP_SERVICE_H_ */
|