LCOV - code coverage report
Current view: top level - zephyr/net - coap_service.h Coverage Total Hit
Test: new.info Lines: 100.0 % 19 19
Test Date: 2025-09-05 22:20:39

            Line data    Source code
       1            1 : /*
       2              :  * Copyright (c) 2023 Basalte bv
       3              :  *
       4              :  * SPDX-License-Identifier: Apache-2.0
       5              :  */
       6              : 
       7              : /** @file
       8              :  * @brief CoAP Service API
       9              :  *
      10              :  * An API for applications to respond to CoAP requests
      11              :  */
      12              : 
      13              : #ifndef ZEPHYR_INCLUDE_NET_COAP_SERVICE_H_
      14              : #define ZEPHYR_INCLUDE_NET_COAP_SERVICE_H_
      15              : 
      16              : #include <zephyr/net/coap.h>
      17              : #include <zephyr/sys/iterable_sections.h>
      18              : #include <zephyr/net/tls_credentials.h>
      19              : 
      20              : #ifdef __cplusplus
      21              : extern "C" {
      22              : #endif
      23              : 
      24              : /**
      25              :  * @brief CoAP Service API
      26              :  * @defgroup coap_service CoAP service API
      27              :  * @since 3.6
      28              :  * @version 0.1.0
      29              :  * @ingroup networking
      30              :  * @{
      31              :  */
      32              : 
      33              : /**
      34              :  * @name CoAP Service configuration flags
      35              :  * @anchor COAP_SERVICE_FLAGS
      36              :  * @{
      37              :  */
      38              : 
      39              : /** Start the service on boot. */
      40            1 : #define COAP_SERVICE_AUTOSTART          BIT(0)
      41              : 
      42              : /** @} */
      43              : 
      44              : /** @cond INTERNAL_HIDDEN */
      45              : 
      46              : struct coap_service_data {
      47              :         int sock_fd;
      48              :         struct coap_observer observers[CONFIG_COAP_SERVICE_OBSERVERS];
      49              :         struct coap_pending pending[CONFIG_COAP_SERVICE_PENDING_MESSAGES];
      50              : };
      51              : 
      52              : struct coap_service {
      53              :         const char *name;
      54              :         const char *host;
      55              :         uint16_t *port;
      56              :         uint8_t flags;
      57              :         struct coap_resource *res_begin;
      58              :         struct coap_resource *res_end;
      59              :         struct coap_service_data *data;
      60              : #if defined(CONFIG_NET_SOCKETS_ENABLE_DTLS)
      61              :         const sec_tag_t *sec_tag_list;
      62              :         size_t sec_tag_list_size;
      63              : #endif
      64              : };
      65              : 
      66              : #if defined(CONFIG_NET_SOCKETS_ENABLE_DTLS)
      67              : #define __z_coap_service_secure(_sec_tag_list, _sec_tag_list_size)                              \
      68              :                 .sec_tag_list = _sec_tag_list,                                                  \
      69              :                 .sec_tag_list_size = _sec_tag_list_size,
      70              : #else
      71              : #define __z_coap_service_secure(...)
      72              : #endif
      73              : 
      74              : #define __z_coap_service_define(_name, _host, _port, _flags, _res_begin, _res_end,              \
      75              :                                 _sec_tag_list, _sec_tag_list_size)                              \
      76              :         static struct coap_service_data _CONCAT(coap_service_data_, _name) = {                  \
      77              :                 .sock_fd = -1,                                                                  \
      78              :         };                                                                                      \
      79              :         const STRUCT_SECTION_ITERABLE(coap_service, _name) = {                                  \
      80              :                 .name = STRINGIFY(_name),                                                       \
      81              :                 .host = _host,                                                                  \
      82              :                 .port = (uint16_t *)(_port),                                                    \
      83              :                 .flags = _flags,                                                                \
      84              :                 .res_begin = (_res_begin),                                                      \
      85              :                 .res_end = (_res_end),                                                          \
      86              :                 .data = &_CONCAT(coap_service_data_, _name),                                        \
      87              :                 __z_coap_service_secure(_sec_tag_list, _sec_tag_list_size)                      \
      88              :         }
      89              : 
      90              : /** @endcond */
      91              : 
      92              : /**
      93              :  * @brief Define a static CoAP resource owned by the service named @p _service .
      94              :  *
      95              :  * @note The handlers registered with the resource can return a CoAP response code to reply with
      96              :  * an acknowledge without any payload, nothing is sent if the return value is 0 or negative.
      97              :  * As seen in the example.
      98              :  *
      99              :  * @code{.c}
     100              :  *     static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios);
     101              :  *
     102              :  *     static int led_put(struct coap_resource *resource, struct coap_packet *request,
     103              :  *                        struct sockaddr *addr, socklen_t addr_len)
     104              :  *     {
     105              :  *             const uint8_t *payload;
     106              :  *             uint16_t payload_len;
     107              :  *
     108              :  *             payload = coap_packet_get_payload(request, &payload_len);
     109              :  *             if (payload_len != 1) {
     110              :  *                     return COAP_RESPONSE_CODE_BAD_REQUEST;
     111              :  *             }
     112              :  *
     113              :  *             if (gpio_pin_set_dt(&led, payload[0]) < 0) {
     114              :  *                     return COAP_RESPONSE_CODE_INTERNAL_ERROR;
     115              :  *             }
     116              :  *
     117              :  *             return COAP_RESPONSE_CODE_CHANGED;
     118              :  *     }
     119              :  *
     120              :  *     COAP_RESOURCE_DEFINE(my_resource, my_service, {
     121              :  *             .put = led_put,
     122              :  *     });
     123              :  * @endcode
     124              :  *
     125              :  * @param _name Name of the resource.
     126              :  * @param _service Name of the associated service.
     127              :  */
     128            1 : #define COAP_RESOURCE_DEFINE(_name, _service, ...)                                              \
     129              :         STRUCT_SECTION_ITERABLE_ALTERNATE(_CONCAT(coap_resource_, _service), coap_resource,     \
     130              :                                           _name) = __VA_ARGS__
     131              : 
     132              : /**
     133              :  * @brief Define a CoAP service with static resources.
     134              :  *
     135              :  * @note The @p _host parameter can be `NULL`. If not, it is used to specify an IP address either in
     136              :  * IPv4 or IPv6 format a fully-qualified hostname or a virtual host, otherwise the any address is
     137              :  * used.
     138              :  *
     139              :  * @note The @p _port parameter must be non-`NULL`. It points to a location that specifies the port
     140              :  * number to use for the service. If the specified port number is zero, then an ephemeral port
     141              :  * number will be used and the actual port number assigned will be written back to memory. For
     142              :  * ephemeral port numbers, the memory pointed to by @p _port must be writeable.
     143              :  *
     144              :  * @param _name Name of the service.
     145              :  * @param _host IP address or hostname associated with the service.
     146              :  * @param[inout] _port Pointer to port associated with the service.
     147              :  * @param _flags Configuration flags @see @ref COAP_SERVICE_FLAGS.
     148              :  */
     149            1 : #define COAP_SERVICE_DEFINE(_name, _host, _port, _flags)                                        \
     150              :         extern struct coap_resource _CONCAT(_CONCAT(_coap_resource_, _name), _list_start)[];    \
     151              :         extern struct coap_resource _CONCAT(_CONCAT(_coap_resource_, _name), _list_end)[];      \
     152              :         __z_coap_service_define(_name, _host, _port, _flags,                                    \
     153              :                                 &_CONCAT(_CONCAT(_coap_resource_, _name), _list_start)[0],  \
     154              :                                 &_CONCAT(_CONCAT(_coap_resource_, _name), _list_end)[0],    \
     155              :                                 NULL, 0)
     156              : 
     157              : /**
     158              :  * @brief Define a CoAP secure service with static resources.
     159              :  *
     160              :  * @note The @p _host parameter can be `NULL`. If not, it is used to specify an IP address either in
     161              :  * IPv4 or IPv6 format a fully-qualified hostname or a virtual host, otherwise the any address is
     162              :  * used.
     163              :  *
     164              :  * @note The @p _port parameter must be non-`NULL`. It points to a location that specifies the port
     165              :  * number to use for the service. If the specified port number is zero, then an ephemeral port
     166              :  * number will be used and the actual port number assigned will be written back to memory. For
     167              :  * ephemeral port numbers, the memory pointed to by @p _port must be writeable.
     168              :  *
     169              :  * @note @kconfig{CONFIG_NET_SOCKETS_ENABLE_DTLS} has to be enabled for CoAP secure support.
     170              :  *
     171              :  * @param _name Name of the service.
     172              :  * @param _host IP address or hostname associated with the service.
     173              :  * @param[inout] _port Pointer to port associated with the service.
     174              :  * @param _flags Configuration flags @see @ref COAP_SERVICE_FLAGS.
     175              :  * @param _sec_tag_list DTLS security tag list used to setup a COAPS socket.
     176              :  * @param _sec_tag_list_size DTLS security tag list size used to setup a COAPS socket.
     177              :  */
     178            1 : #define COAPS_SERVICE_DEFINE(_name, _host, _port, _flags, _sec_tag_list, _sec_tag_list_size)    \
     179              :         BUILD_ASSERT(IS_ENABLED(CONFIG_NET_SOCKETS_ENABLE_DTLS),                                \
     180              :                      "DTLS is required for CoAP secure (CONFIG_NET_SOCKETS_ENABLE_DTLS)");    \
     181              :         extern struct coap_resource _CONCAT(_CONCAT(_coap_resource_, _name), _list_start)[];    \
     182              :         extern struct coap_resource _CONCAT(_CONCAT(_coap_resource_, _name), _list_end)[];      \
     183              :         __z_coap_service_define(_name, _host, _port, _flags,                                    \
     184              :                                 &_CONCAT(_CONCAT(_coap_resource_, _name), _list_start)[0],  \
     185              :                                 &_CONCAT(_CONCAT(_coap_resource_, _name), _list_end)[0],    \
     186              :                                 _sec_tag_list, _sec_tag_list_size)
     187              : 
     188              : /**
     189              :  * @brief Count the number of CoAP services.
     190              :  *
     191              :  * @param[out] _dst Pointer to location where result is written.
     192              :  */
     193            1 : #define COAP_SERVICE_COUNT(_dst) STRUCT_SECTION_COUNT(coap_service, _dst)
     194              : 
     195              : /**
     196              :  * @brief Count CoAP service static resources.
     197              :  *
     198              :  * @param _service Pointer to a service.
     199              :  */
     200            1 : #define COAP_SERVICE_RESOURCE_COUNT(_service) ((_service)->res_end - (_service)->res_begin)
     201              : 
     202              : /**
     203              :  * @brief Check if service has the specified resource.
     204              :  *
     205              :  * @param _service Pointer to a service.
     206              :  * @param _resource Pointer to a resource.
     207              :  */
     208            1 : #define COAP_SERVICE_HAS_RESOURCE(_service, _resource)                                          \
     209              :         ((_service)->res_begin <= _resource && _resource < (_service)->res_end)
     210              : 
     211              : /**
     212              :  * @brief Iterate over all CoAP services.
     213              :  *
     214              :  * @param _it Name of iterator (of type @ref coap_service)
     215              :  */
     216            1 : #define COAP_SERVICE_FOREACH(_it) STRUCT_SECTION_FOREACH(coap_service, _it)
     217              : 
     218              : /**
     219              :  * @brief Iterate over static CoAP resources associated with a given @p _service.
     220              :  *
     221              :  * @note This macro requires that @p _service is defined with @ref COAP_SERVICE_DEFINE.
     222              :  *
     223              :  * @param _service Name of CoAP service
     224              :  * @param _it Name of iterator (of type @ref coap_resource)
     225              :  */
     226            1 : #define COAP_RESOURCE_FOREACH(_service, _it)                                                    \
     227              :         STRUCT_SECTION_FOREACH_ALTERNATE(_CONCAT(coap_resource_, _service), coap_resource, _it)
     228              : 
     229              : /**
     230              :  * @brief Iterate over all static resources associated with @p _service .
     231              :  *
     232              :  * @note This macro is suitable for a @p _service defined with @ref COAP_SERVICE_DEFINE.
     233              :  *
     234              :  * @param _service Pointer to COAP service
     235              :  * @param _it Name of iterator (of type @ref coap_resource)
     236              :  */
     237            1 : #define COAP_SERVICE_FOREACH_RESOURCE(_service, _it)                                            \
     238              :         for (struct coap_resource *_it = (_service)->res_begin; ({                           \
     239              :                 __ASSERT(_it <= (_service)->res_end, "unexpected list end location");           \
     240              :                 _it < (_service)->res_end;                                                        \
     241              :         }); _it++)
     242              : 
     243              : /**
     244              :  * @brief Start the provided @p service .
     245              :  *
     246              :  * @note This function is suitable for a @p service defined with @ref COAP_SERVICE_DEFINE.
     247              :  *
     248              :  * @param service Pointer to CoAP service
     249              :  * @retval 0 in case of success.
     250              :  * @retval -EALREADY in case of an already running service.
     251              :  * @retval -ENOTSUP in case the server has no valid host and port configuration.
     252              :  */
     253            1 : int coap_service_start(const struct coap_service *service);
     254              : 
     255              : /**
     256              :  * @brief Stop the provided @p service .
     257              :  *
     258              :  * @note This function is suitable for a @p service defined with @ref COAP_SERVICE_DEFINE.
     259              :  *
     260              :  * @param service Pointer to CoAP service
     261              :  * @retval 0 in case of success.
     262              :  * @retval -EALREADY in case the service isn't running.
     263              :  */
     264            1 : int coap_service_stop(const struct coap_service *service);
     265              : 
     266              : /**
     267              :  * @brief Query the provided @p service running state.
     268              :  *
     269              :  * @note This function is suitable for a @p service defined with @ref COAP_SERVICE_DEFINE.
     270              :  *
     271              :  * @param service Pointer to CoAP service
     272              :  * @retval 1 if the service is running
     273              :  * @retval 0 if the service is stopped
     274              :  * @retval negative in case of an error.
     275              :  */
     276            1 : int coap_service_is_running(const struct coap_service *service);
     277              : 
     278              : /**
     279              :  * @brief Send a CoAP message from the provided @p service .
     280              :  *
     281              :  * @note This function is suitable for a @p service defined with @ref COAP_SERVICE_DEFINE.
     282              :  *
     283              :  * @param service Pointer to CoAP service
     284              :  * @param cpkt CoAP Packet to send
     285              :  * @param addr Peer address
     286              :  * @param addr_len Peer address length
     287              :  * @param params Pointer to transmission parameters structure or NULL to use default values.
     288              :  * @return 0 in case of success or negative in case of error.
     289              :  */
     290            1 : int coap_service_send(const struct coap_service *service, const struct coap_packet *cpkt,
     291              :                       const struct sockaddr *addr, socklen_t addr_len,
     292              :                       const struct coap_transmission_parameters *params);
     293              : 
     294              : /**
     295              :  * @brief Send a CoAP message from the provided @p resource .
     296              :  *
     297              :  * @note This function is suitable for a @p resource defined with @ref COAP_RESOURCE_DEFINE.
     298              :  *
     299              :  * @param resource Pointer to CoAP resource
     300              :  * @param cpkt CoAP Packet to send
     301              :  * @param addr Peer address
     302              :  * @param addr_len Peer address length
     303              :  * @param params Pointer to transmission parameters structure or NULL to use default values.
     304              :  * @return 0 in case of success or negative in case of error.
     305              :  */
     306            1 : int coap_resource_send(const struct coap_resource *resource, const struct coap_packet *cpkt,
     307              :                        const struct sockaddr *addr, socklen_t addr_len,
     308              :                        const struct coap_transmission_parameters *params);
     309              : 
     310              : /**
     311              :  * @brief Parse a CoAP observe request for the provided @p resource .
     312              :  *
     313              :  * @note This function is suitable for a @p resource defined with @ref COAP_RESOURCE_DEFINE.
     314              :  *
     315              :  * If the observe option value is equal to 0, an observer will be added, if the value is equal
     316              :  * to 1, an existing observer will be removed.
     317              :  *
     318              :  * @param resource Pointer to CoAP resource
     319              :  * @param request CoAP request to parse
     320              :  * @param addr Peer address
     321              :  * @return the observe option value in case of success or negative in case of error.
     322              :  */
     323            1 : int coap_resource_parse_observe(struct coap_resource *resource, const struct coap_packet *request,
     324              :                                 const struct sockaddr *addr);
     325              : 
     326              : /**
     327              :  * @brief Lookup an observer by address and remove it from the @p resource .
     328              :  *
     329              :  * @note This function is suitable for a @p resource defined with @ref COAP_RESOURCE_DEFINE.
     330              :  *
     331              :  * @param resource Pointer to CoAP resource
     332              :  * @param addr Peer address
     333              :  * @return 0 in case of success or negative in case of error.
     334              :  */
     335            1 : int coap_resource_remove_observer_by_addr(struct coap_resource *resource,
     336              :                                           const struct sockaddr *addr);
     337              : 
     338              : /**
     339              :  * @brief Lookup an observer by token and remove it from the @p resource .
     340              :  *
     341              :  * @note This function is suitable for a @p resource defined with @ref COAP_RESOURCE_DEFINE.
     342              :  *
     343              :  * @param resource Pointer to CoAP resource
     344              :  * @param token Pointer to the token
     345              :  * @param token_len Length of valid bytes in the token
     346              :  * @return 0 in case of success or negative in case of error.
     347              :  */
     348            1 : int coap_resource_remove_observer_by_token(struct coap_resource *resource,
     349              :                                            const uint8_t *token, uint8_t token_len);
     350              : 
     351              : /**
     352              :  * @}
     353              :  */
     354              : 
     355              : #ifdef __cplusplus
     356              : }
     357              : #endif
     358              : 
     359              : #endif /* ZEPHYR_INCLUDE_NET_COAP_SERVICE_H_ */
        

Generated by: LCOV version 2.0-1