• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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