1 /** @file 2 * @brief CoAP client API 3 * 4 * An API for applications to do CoAP requests 5 */ 6 7 /* 8 * Copyright (c) 2023 Nordic Semiconductor ASA 9 * 10 * SPDX-License-Identifier: Apache-2.0 11 */ 12 #ifndef ZEPHYR_INCLUDE_NET_COAP_CLIENT_H_ 13 #define ZEPHYR_INCLUDE_NET_COAP_CLIENT_H_ 14 15 /** 16 * @brief CoAP client API 17 * @defgroup coap_client CoAP client API 18 * @since 3.4 19 * @version 0.1.0 20 * @ingroup networking 21 * @{ 22 */ 23 24 #include <zephyr/net/coap.h> 25 #include <zephyr/kernel.h> 26 27 #ifdef __cplusplus 28 extern "C" { 29 #endif 30 31 /** Maximum size of a CoAP message */ 32 #define MAX_COAP_MSG_LEN (CONFIG_COAP_CLIENT_MESSAGE_HEADER_SIZE + \ 33 CONFIG_COAP_CLIENT_MESSAGE_SIZE) 34 35 /** 36 * @typedef coap_client_response_cb_t 37 * @brief Callback for CoAP request. 38 * 39 * This callback is called for responses to CoAP client requests. 40 * It is used to indicate errors, response codes from server or to deliver payload. 41 * Blockwise transfers cause this callback to be called sequentially with increasing payload offset 42 * and only partial content in buffer pointed by payload parameter. 43 * 44 * @param result_code Result code of the response. Negative if there was a failure in send. 45 * @ref coap_response_code for positive. 46 * @param offset Payload offset from the beginning of a blockwise transfer. 47 * @param payload Buffer containing the payload from the response. NULL for empty payload. 48 * @param len Size of the payload. 49 * @param last_block Indicates the last block of the response. 50 * @param user_data User provided context. 51 */ 52 typedef void (*coap_client_response_cb_t)(int16_t result_code, 53 size_t offset, const uint8_t *payload, size_t len, 54 bool last_block, void *user_data); 55 56 /** 57 * @brief Representation of a CoAP client request. 58 */ 59 struct coap_client_request { 60 enum coap_method method; /**< Method of the request */ 61 bool confirmable; /**< CoAP Confirmable/Non-confirmable message */ 62 const char *path; /**< Path of the requested resource */ 63 enum coap_content_format fmt; /**< Content format to be used */ 64 const uint8_t *payload; /**< User allocated buffer for send request */ 65 size_t len; /**< Length of the payload */ 66 coap_client_response_cb_t cb; /**< Callback when response received */ 67 const struct coap_client_option *options; /**< Extra options to be added to request */ 68 uint8_t num_options; /**< Number of extra options */ 69 void *user_data; /**< User provided context */ 70 }; 71 72 /** 73 * @brief Representation of extra options for the CoAP client request 74 */ 75 struct coap_client_option { 76 /** Option code */ 77 uint16_t code; 78 #if defined(CONFIG_COAP_EXTENDED_OPTIONS_LEN) 79 /** Option len */ 80 uint16_t len; 81 /** Buffer for the length */ 82 uint8_t value[CONFIG_COAP_EXTENDED_OPTIONS_LEN_VALUE]; 83 #else 84 /** Option len */ 85 uint8_t len; 86 /** Buffer for the length */ 87 uint8_t value[12]; 88 #endif 89 }; 90 91 /** @cond INTERNAL_HIDDEN */ 92 struct coap_client_internal_request { 93 uint8_t request_token[COAP_TOKEN_MAX_LEN]; 94 uint32_t offset; 95 uint16_t last_id; 96 uint8_t request_tkl; 97 bool request_ongoing; 98 atomic_t in_callback; 99 struct coap_block_context recv_blk_ctx; 100 struct coap_block_context send_blk_ctx; 101 struct coap_pending pending; 102 struct coap_client_request coap_request; 103 struct coap_packet request; 104 uint8_t request_tag[COAP_TOKEN_MAX_LEN]; 105 106 /* For GETs with observe option set */ 107 bool is_observe; 108 int last_response_id; 109 }; 110 111 struct coap_client { 112 int fd; 113 struct sockaddr address; 114 socklen_t socklen; 115 struct k_mutex lock; 116 uint8_t send_buf[MAX_COAP_MSG_LEN]; 117 uint8_t recv_buf[MAX_COAP_MSG_LEN]; 118 struct coap_client_internal_request requests[CONFIG_COAP_CLIENT_MAX_REQUESTS]; 119 struct coap_option echo_option; 120 bool send_echo; 121 }; 122 /** @endcond */ 123 124 /** 125 * @brief Initialize the CoAP client. 126 * 127 * @param[in] client Client instance. 128 * @param[in] info Name for the receiving thread of the client. Setting this NULL will result as 129 * default name of "coap_client". 130 * 131 * @return int Zero on success, otherwise a negative error code. 132 */ 133 int coap_client_init(struct coap_client *client, const char *info); 134 135 /** 136 * @brief Send CoAP request 137 * 138 * Operation is handled asynchronously using a background thread. 139 * If the socket isn't connected to a destination address, user must provide a destination address, 140 * otherwise the address should be set as NULL. 141 * Once the callback is called with last block set as true, socket can be closed or 142 * used for another query. 143 * 144 * @param client Client instance. 145 * @param sock Open socket file descriptor. 146 * @param addr the destination address of the request, NULL if socket is already connected. 147 * @param req CoAP request structure 148 * @param params Pointer to transmission parameters structure or NULL to use default values. 149 * @return zero when operation started successfully or negative error code otherwise. 150 */ 151 152 int coap_client_req(struct coap_client *client, int sock, const struct sockaddr *addr, 153 struct coap_client_request *req, struct coap_transmission_parameters *params); 154 155 /** 156 * @brief Cancel all current requests. 157 * 158 * This is intended for canceling long-running requests (e.g. GETs with the OBSERVE option set) 159 * which has gone stale for some reason. 160 * The function should also be called before the corresponding client socket is closed, 161 * to prevent the socket from being monitored by the internal polling thread. 162 * 163 * @param client Client instance. 164 */ 165 void coap_client_cancel_requests(struct coap_client *client); 166 167 /** 168 * @brief Cancel matching requests. 169 * 170 * This function cancels all CoAP client request that matches the given request. 171 * The request is matched based on the method, path, callback and user_data, if provided. 172 * Any field set to NULL is considered a wildcard. 173 * 174 * (struct coap_client_request){0} cancels all requests. 175 * (struct coap_client_request){.method = COAP_METHOD_GET} cancels all GET requests. 176 * 177 * @param client Pointer to the CoAP client instance. 178 * @param req Pointer to the CoAP client request to be canceled. 179 */ 180 void coap_client_cancel_request(struct coap_client *client, struct coap_client_request *req); 181 182 /** 183 * @brief Initialise a Block2 option to be added to a request 184 * 185 * If the application expects a request to require a blockwise transfer, it may pre-emptively 186 * suggest a maximum block size to the server - see RFC7959 Figure 3: Block-Wise GET with Early 187 * Negotiation. 188 * 189 * This helper function returns a Block2 option to send with the initial request. 190 * 191 * @return CoAP client initial Block2 option structure 192 */ 193 struct coap_client_option coap_client_option_initial_block2(void); 194 195 /** 196 * @brief Check if client has ongoing exchange. 197 * 198 * @note Function not only considers ongoing requests, but also lifetime of completed requests 199 * (which provides graceful duplicates handling). 200 * 201 * @note For socket handling. 202 * Function does no consider a socket POLL that has started before this call, 203 * therefore it is recommended to wait out POLL timeout before closing socket 204 * (e.g. call coap_client_cancel_requests() which applies delay for timeout). 205 * 206 * @param client Pointer to the CoAP client instance. 207 * 208 * @return true if there is an ongoing exchange, false otherwise. 209 */ 210 bool coap_client_has_ongoing_exchange(struct coap_client *client); 211 212 #ifdef __cplusplus 213 } 214 #endif 215 216 /** 217 * @} 218 */ 219 220 #endif /* ZEPHYR_INCLUDE_NET_COAP_CLIENT_H_ */ 221