1 /* 2 * coap_block_internal.h -- Structures, Enums & Functions that are not 3 * exposed to application programming 4 * 5 * Copyright (C) 2010-2023 Olaf Bergmann <bergmann@tzi.org> 6 * Copyright (C) 2021-2023 Jon Shallow <supjps-libcoap@jpshallow.com> 7 * 8 * SPDX-License-Identifier: BSD-2-Clause 9 * 10 * This file is part of the CoAP library libcoap. Please see README for terms 11 * of use. 12 */ 13 14 /** 15 * @file coap_block_internal.h 16 * @brief CoAP block internal information 17 */ 18 19 #ifndef COAP_BLOCK_INTERNAL_H_ 20 #define COAP_BLOCK_INTERNAL_H_ 21 22 #include "coap_internal.h" 23 #include "coap_pdu_internal.h" 24 #include "coap_resource.h" 25 26 /** 27 * @ingroup internal_api 28 * @defgroup block_internal Block Transfer 29 * Internal API for Block Transfer (RC7959) 30 * @{ 31 */ 32 33 #if COAP_Q_BLOCK_SUPPORT 34 /* Internal use only and are dropped when setting block_mode */ 35 #define COAP_BLOCK_HAS_Q_BLOCK 0x40 /* Set when Q_BLOCK supported */ 36 #define COAP_BLOCK_PROBE_Q_BLOCK 0x80 /* Set when Q_BLOCK probing */ 37 38 #define set_block_mode_probe_q(block_mode) \ 39 do { \ 40 block_mode |= COAP_BLOCK_PROBE_Q_BLOCK; \ 41 block_mode &= ~(COAP_BLOCK_TRY_Q_BLOCK | COAP_BLOCK_HAS_Q_BLOCK); \ 42 } while (0) 43 44 #define set_block_mode_has_q(block_mode) \ 45 do { \ 46 block_mode |= COAP_BLOCK_HAS_Q_BLOCK; \ 47 block_mode &= ~(COAP_BLOCK_TRY_Q_BLOCK | COAP_BLOCK_PROBE_Q_BLOCK); \ 48 } while (0) 49 50 #define set_block_mode_drop_q(block_mode) \ 51 do { \ 52 block_mode &= ~(COAP_BLOCK_TRY_Q_BLOCK |\ 53 COAP_BLOCK_PROBE_Q_BLOCK |\ 54 COAP_BLOCK_HAS_Q_BLOCK | \ 55 COAP_BLOCK_USE_M_Q_BLOCK); \ 56 } while (0) 57 58 #define COAP_SINGLE_BLOCK_OR_Q (COAP_BLOCK_SINGLE_BODY|COAP_BLOCK_HAS_Q_BLOCK) 59 #else /* ! COAP_Q_BLOCK_SUPPORT */ 60 #define COAP_SINGLE_BLOCK_OR_Q (COAP_BLOCK_SINGLE_BODY) 61 #endif /* ! COAP_Q_BLOCK_SUPPORT */ 62 63 typedef enum { 64 COAP_RECURSE_OK, 65 COAP_RECURSE_NO 66 } coap_recurse_t; 67 68 struct coap_lg_range { 69 uint32_t begin; 70 uint32_t end; 71 }; 72 73 #define COAP_RBLOCK_CNT 4 74 /** 75 * Structure to keep track of received blocks 76 */ 77 typedef struct coap_rblock_t { 78 uint32_t used; 79 uint32_t retry; 80 #if COAP_Q_BLOCK_SUPPORT 81 uint32_t processing_payload_set; 82 uint32_t latest_payload_set; 83 #endif /* COAP_Q_BLOCK_SUPPORT */ 84 struct coap_lg_range range[COAP_RBLOCK_CNT]; 85 coap_tick_t last_seen; 86 } coap_rblock_t; 87 88 /** 89 * Structure to keep track of block1 specific information 90 * (Requests) 91 */ 92 typedef struct coap_l_block1_t { 93 coap_binary_t *app_token; /**< original PDU token */ 94 uint64_t state_token; /**< state token */ 95 size_t bert_size; /**< size of last BERT block */ 96 uint32_t count; /**< the number of packets sent for payload */ 97 } coap_l_block1_t; 98 99 /** 100 * Structure to keep track of block2 specific information 101 * (Responses) 102 */ 103 typedef struct coap_l_block2_t { 104 coap_resource_t *resource; /**< associated resource */ 105 coap_string_t *query; /**< Associated query for the resource */ 106 uint64_t etag; /**< ETag value */ 107 coap_pdu_code_t request_method; /**< Method used to request this data */ 108 uint8_t rtag_set; /**< Set if RTag is in receive PDU */ 109 uint8_t rtag_length; /**< RTag length */ 110 uint8_t rtag[8]; /**< RTag for block checking */ 111 coap_time_t maxage_expire; /**< When this entry expires */ 112 } coap_l_block2_t; 113 114 /** 115 * Structure to hold large body (many blocks) transmission information 116 */ 117 struct coap_lg_xmit_t { 118 struct coap_lg_xmit_t *next; 119 uint8_t blk_size; /**< large block transmission size */ 120 uint16_t option; /**< large block transmisson CoAP option */ 121 int last_block; /**< last acknowledged block number Block1 122 last transmitted Q-Block2 */ 123 const uint8_t *data; /**< large data ptr */ 124 size_t length; /**< large data length */ 125 size_t offset; /**< large data next offset to transmit */ 126 union { 127 coap_l_block1_t b1; 128 coap_l_block2_t b2; 129 } b; 130 coap_pdu_t pdu; /**< skeletal PDU */ 131 coap_tick_t last_payload; /**< Last time MAX_PAYLOAD was sent or 0 */ 132 coap_tick_t last_sent; /**< Last time any data sent */ 133 coap_tick_t last_all_sent; /**< Last time all data sent or 0 */ 134 coap_tick_t last_obs; /**< Last time used (Observe tracking) or 0 */ 135 #if COAP_Q_BLOCK_SUPPORT 136 coap_tick_t non_timeout_random_ticks; /** Used for Q-Block */ 137 #endif /* COAP_Q_BLOCK_SUPPORT */ 138 coap_release_large_data_t release_func; /**< large data de-alloc function */ 139 void *app_ptr; /**< applicaton provided ptr for de-alloc function */ 140 }; 141 142 #if COAP_CLIENT_SUPPORT 143 /** 144 * Structure to hold large body (many blocks) client receive information 145 */ 146 struct coap_lg_crcv_t { 147 struct coap_lg_crcv_t *next; 148 uint8_t observe[3]; /**< Observe data (if observe_set) (only 24 bits) */ 149 uint8_t observe_length;/**< Length of observe data */ 150 uint8_t observe_set; /**< Set if this is an observe receive PDU */ 151 uint8_t szx; /**< size of individual blocks */ 152 uint8_t etag_set; /**< Set if ETag is in receive PDU */ 153 uint8_t etag_length; /**< ETag length */ 154 uint8_t etag[8]; /**< ETag for block checking */ 155 uint16_t content_format; /**< Content format for the set of blocks */ 156 uint8_t last_type; /**< Last request type (CON/NON) */ 157 uint8_t initial; /**< If set, has not been used yet */ 158 uint16_t block_option; /**< Block option in use */ 159 uint16_t retry_counter; /**< Retry counter (part of state token) */ 160 size_t total_len; /**< Length as indicated by SIZE2 option */ 161 coap_binary_t *body_data; /**< Used for re-assembling entire body */ 162 coap_binary_t *app_token; /**< app requesting PDU token */ 163 coap_bin_const_t **obs_token; /**< Tokens used in setting up Observe 164 (to handle large FETCH) */ 165 size_t obs_token_cnt; /**< number of tokens used to set up Observe */ 166 uint64_t state_token; /**< state token */ 167 coap_pdu_t pdu; /**< skeletal PDU */ 168 coap_rblock_t rec_blocks; /** < list of received blocks */ 169 coap_tick_t last_used; /**< Last time all data sent or 0 */ 170 }; 171 #endif /* COAP_CLIENT_SUPPORT */ 172 173 #if COAP_SERVER_SUPPORT 174 /** 175 * Structure to hold large body (many blocks) server receive information 176 */ 177 struct coap_lg_srcv_t { 178 struct coap_lg_srcv_t *next; 179 uint8_t observe[3]; /**< Observe data (if set) (only 24 bits) */ 180 uint8_t observe_length;/**< Length of observe data */ 181 uint8_t observe_set; /**< Set if this is an observe receive PDU */ 182 uint8_t rtag_set; /**< Set if RTag is in receive PDU */ 183 uint8_t rtag_length; /**< RTag length */ 184 uint8_t rtag[8]; /**< RTag for block checking */ 185 uint16_t content_format; /**< Content format for the set of blocks */ 186 uint8_t last_type; /**< Last request type (CON/NON) */ 187 uint8_t szx; /**< size of individual blocks */ 188 size_t total_len; /**< Length as indicated by SIZE1 option */ 189 coap_binary_t *body_data; /**< Used for re-assembling entire body */ 190 size_t amount_so_far; /**< Amount of data seen so far */ 191 coap_resource_t *resource; /**< associated resource */ 192 coap_str_const_t *uri_path; /** set to uri_path if unknown resource */ 193 coap_rblock_t rec_blocks; /** < list of received blocks */ 194 #if COAP_Q_BLOCK_SUPPORT 195 coap_bin_const_t *last_token; /**< last used token */ 196 #endif /* COAP_Q_BLOCK_SUPPORT */ 197 coap_mid_t last_mid; /**< Last received mid for this set of packets */ 198 coap_tick_t last_used; /**< Last time data sent or 0 */ 199 uint16_t block_option; /**< Block option in use */ 200 }; 201 #endif /* COAP_SERVER_SUPPORT */ 202 203 #if COAP_Q_BLOCK_SUPPORT 204 typedef enum { 205 COAP_SEND_SKIP_PDU, 206 COAP_SEND_INC_PDU 207 } coap_send_pdu_t; 208 #endif /* COAP_Q_BLOCK_SUPPORT */ 209 210 #if COAP_CLIENT_SUPPORT 211 coap_lg_crcv_t *coap_block_new_lg_crcv(coap_session_t *session, 212 coap_pdu_t *pdu, 213 coap_lg_xmit_t *lg_xmit); 214 215 void coap_block_delete_lg_crcv(coap_session_t *session, 216 coap_lg_crcv_t *lg_crcv); 217 218 int coap_block_check_lg_crcv_timeouts(coap_session_t *session, 219 coap_tick_t now, 220 coap_tick_t *tim_rem); 221 222 #if COAP_Q_BLOCK_SUPPORT 223 coap_mid_t coap_send_q_block1(coap_session_t *session, 224 coap_block_b_t block, 225 coap_pdu_t *request, 226 coap_send_pdu_t send_request); 227 228 coap_tick_t coap_block_check_q_block1_xmit(coap_session_t *session, 229 coap_tick_t now); 230 231 coap_mid_t coap_block_test_q_block(coap_session_t *session, coap_pdu_t *actual); 232 #endif /* COAP_Q_BLOCK_SUPPORT */ 233 234 #endif /* COAP_CLIENT_SUPPORT */ 235 236 #if COAP_Q_BLOCK_SUPPORT 237 coap_mid_t coap_send_q_blocks(coap_session_t *session, 238 coap_lg_xmit_t *lg_xmit, 239 coap_block_b_t block, 240 coap_pdu_t *pdu, 241 coap_send_pdu_t send_pdu); 242 #endif /* COAP_Q_BLOCK_SUPPORT */ 243 244 #if COAP_SERVER_SUPPORT 245 void coap_block_delete_lg_srcv(coap_session_t *session, 246 coap_lg_srcv_t *lg_srcv); 247 248 int coap_block_check_lg_srcv_timeouts(coap_session_t *session, 249 coap_tick_t now, 250 coap_tick_t *tim_rem); 251 252 #if COAP_Q_BLOCK_SUPPORT 253 coap_tick_t coap_block_check_q_block2_xmit(coap_session_t *session, 254 coap_tick_t now); 255 256 coap_mid_t coap_send_q_block2(coap_session_t *session, 257 coap_resource_t *resource, 258 const coap_string_t *query, 259 coap_pdu_code_t request_method, 260 coap_block_b_t block, 261 coap_pdu_t *response, 262 coap_send_pdu_t send_response); 263 #endif /* COAP_Q_BLOCK_SUPPORT */ 264 265 int coap_handle_request_send_block(coap_session_t *session, 266 coap_pdu_t *pdu, 267 coap_pdu_t *response, 268 coap_resource_t *resource, 269 coap_string_t *query); 270 271 int coap_handle_request_put_block(coap_context_t *context, 272 coap_session_t *session, 273 coap_pdu_t *pdu, 274 coap_pdu_t *response, 275 coap_resource_t *resource, 276 coap_string_t *uri_path, 277 coap_opt_t *observe, 278 int *added_block, 279 coap_lg_srcv_t **free_lg_srcv); 280 281 coap_lg_xmit_t *coap_find_lg_xmit_response(const coap_session_t *session, 282 const coap_pdu_t *request, 283 const coap_resource_t *resource, 284 const coap_string_t *query); 285 #endif /* COAP_SERVER_SUPPORT */ 286 287 #if COAP_CLIENT_SUPPORT 288 int coap_handle_response_send_block(coap_session_t *session, coap_pdu_t *sent, 289 coap_pdu_t *rcvd); 290 291 int coap_handle_response_get_block(coap_context_t *context, 292 coap_session_t *session, 293 coap_pdu_t *sent, 294 coap_pdu_t *rcvd, 295 coap_recurse_t recursive); 296 coap_mid_t coap_retransmit_oscore_pdu(coap_session_t *session, 297 coap_pdu_t *pdu, 298 coap_opt_t *echo); 299 #endif /* COAP_CLIENT_SUPPORT */ 300 301 void coap_block_delete_lg_xmit(coap_session_t *session, 302 coap_lg_xmit_t *lg_xmit); 303 304 int coap_block_check_lg_xmit_timeouts(coap_session_t *session, 305 coap_tick_t now, 306 coap_tick_t *tim_rem); 307 308 #if COAP_Q_BLOCK_SUPPORT 309 int coap_block_drop_resp_q_block_xmit(coap_session_t *session, 310 coap_lg_xmit_t *lg_xmit); 311 312 int coap_block_drop_resp_q_block2_crcv(coap_session_t *session, 313 coap_lg_crcv_t *lg_crcv, 314 coap_pdu_t *sent); 315 #endif /* COAP_Q_BLOCK_SUPPORT */ 316 317 /** 318 * The function checks that the code in a newly formed lg_xmit created by 319 * coap_add_data_large_response() is updated. 320 * 321 * @param session The session. 322 * @param request The request PDU to to check. 323 * @param response The response PDU to to update with response->code. 324 * @param resource The requested resource. 325 * @param query The requested query. 326 */ 327 void coap_check_code_lg_xmit(const coap_session_t *session, 328 const coap_pdu_t *request, 329 coap_pdu_t *response, 330 const coap_resource_t *resource, 331 const coap_string_t *query); 332 333 #if COAP_CLIENT_SUPPORT 334 /** 335 * The function checks if the token needs to be updated before PDU is 336 * presented to the application (only relevant to clients). 337 * 338 * @param session The session. 339 * @param pdu The PDU to to check for updating. 340 */ 341 void coap_check_update_token(coap_session_t *session, coap_pdu_t *pdu); 342 #else /* ! COAP_CLIENT_SUPPORT */ 343 #define coap_check_update_token(a,b) 344 #endif /* ! COAP_CLIENT_SUPPORT */ 345 346 /** @} */ 347 348 #endif /* COAP_BLOCK_INTERNAL_H_ */ 349