1 /*
2  * coap_block_internal.h -- Structures, Enums & Functions that are not
3  * exposed to application programming
4  *
5  * Copyright (C) 2010-2021 Olaf Bergmann <bergmann@tzi.org>
6  * Copyright (C) 2021      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_pdu_internal.h"
23 #include "resource.h"
24 
25 /**
26  * @defgroup block_internal Block (Internal)
27  * Structures, Enums and Functions that are not exposed to applications
28  * @{
29  */
30 
31 typedef enum {
32   COAP_RECURSE_OK,
33   COAP_RECURSE_NO
34 } coap_recurse_t;
35 
36 struct coap_lg_range {
37   uint32_t begin;
38   uint32_t end;
39 };
40 
41 #define COAP_RBLOCK_CNT 4
42 /**
43  * Structure to keep track of received blocks
44  */
45 typedef struct coap_rblock_t {
46   uint32_t used;
47   uint32_t retry;
48   struct coap_lg_range range[COAP_RBLOCK_CNT];
49   coap_tick_t last_seen;
50 } coap_rblock_t;
51 
52 /**
53  * Structure to keep track of block1 specific information
54  * (Requests)
55  */
56 typedef struct coap_l_block1_t {
57   coap_binary_t *app_token; /**< original PDU token */
58   uint8_t token[8];      /**< last used token */
59   size_t token_length;   /**< length of token */
60   uint32_t count;        /**< the number of packets sent for payload */
61 } coap_l_block1_t;
62 
63 /**
64  * Structure to keep track of block2 specific information
65  * (Responses)
66  */
67 typedef struct coap_l_block2_t {
68   coap_resource_t *resource; /**< associated resource */
69   coap_string_t *query;  /**< Associated query for the resource */
70   uint64_t etag;         /**< ETag value */
71   coap_time_t maxage_expire; /**< When this entry expires */
72 } coap_l_block2_t;
73 
74 /**
75  * Structure to hold large body (many blocks) transmission information
76  */
77 struct coap_lg_xmit_t {
78   struct coap_lg_xmit_t *next;
79   uint8_t blk_size;      /**< large block transmission size */
80   uint16_t option;       /**< large block transmisson CoAP option */
81   int last_block;        /**< last acknowledged block number */
82   const uint8_t *data;   /**< large data ptr */
83   size_t length;         /**< large data length */
84   size_t offset;         /**< large data next offset to transmit */
85   union {
86     coap_l_block1_t b1;
87     coap_l_block2_t b2;
88   } b;
89   coap_pdu_t pdu;        /**< skeletal PDU */
90   coap_tick_t last_payload; /**< Last time MAX_PAYLOAD was sent or 0 */
91   coap_tick_t last_used; /**< Last time all data sent or 0 */
92   coap_release_large_data_t release_func; /**< large data de-alloc function */
93   void *app_ptr;         /**< applicaton provided ptr for de-alloc function */
94 };
95 
96 /**
97  * Structure to hold large body (many blocks) client receive information
98  */
99 struct coap_lg_crcv_t {
100   struct coap_lg_crcv_t *next;
101   uint8_t observe[3];    /**< Observe data (if set) (only 24 bits) */
102   uint8_t observe_length;/**< Length of observe data */
103   uint8_t observe_set;   /**< Set if this is an observe receive PDU */
104   uint8_t etag_set;      /**< Set if ETag is in receive PDU */
105   uint8_t etag_length;   /**< ETag length */
106   uint8_t etag[8];       /**< ETag for block checking */
107   uint16_t content_format; /**< Content format for the set of blocks */
108   uint8_t last_type;     /**< Last request type (CON/NON) */
109   uint8_t initial;       /**< If set, has not been used yet */
110   uint8_t szx;           /**< size of individual blocks */
111   size_t total_len;      /**< Length as indicated by SIZE2 option */
112   coap_binary_t *body_data; /**< Used for re-assembling entire body */
113   coap_binary_t *app_token; /**< app requesting PDU token */
114   uint8_t base_token[8]; /**< established base PDU token */
115   size_t base_token_length; /**< length of token */
116   uint8_t token[8];      /**< last used token */
117   size_t token_length;   /**< length of token */
118   coap_pdu_t pdu;        /**< skeletal PDU */
119   coap_rblock_t rec_blocks; /** < list of received blocks */
120   coap_tick_t last_used; /**< Last time all data sent or 0 */
121   uint16_t block_option; /**< Block option in use */
122 };
123 
124 /**
125  * Structure to hold large body (many blocks) server receive information
126  */
127 struct coap_lg_srcv_t {
128   struct coap_lg_srcv_t *next;
129   uint8_t observe[3];    /**< Observe data (if set) (only 24 bits) */
130   uint8_t observe_length;/**< Length of observe data */
131   uint8_t observe_set;   /**< Set if this is an observe receive PDU */
132   uint8_t rtag_set;      /**< Set if RTag is in receive PDU */
133   uint8_t rtag_length;   /**< RTag length */
134   uint8_t rtag[8];       /**< RTag for block checking */
135   uint16_t content_format; /**< Content format for the set of blocks */
136   uint8_t last_type;     /**< Last request type (CON/NON) */
137   uint8_t szx;           /**< size of individual blocks */
138   size_t total_len;      /**< Length as indicated by SIZE1 option */
139   coap_binary_t *body_data; /**< Used for re-assembling entire body */
140   size_t amount_so_far;  /**< Amount of data seen so far */
141   coap_resource_t *resource; /**< associated resource */
142   coap_str_const_t *uri_path; /** set to uri_path if unknown resource */
143   coap_rblock_t rec_blocks; /** < list of received blocks */
144   uint8_t last_token[8]; /**< last used token */
145   size_t last_token_length; /**< length of token */
146   coap_mid_t last_mid;   /**< Last received mid for this set of packets */
147   coap_tick_t last_used; /**< Last time data sent or 0 */
148   uint16_t block_option; /**< Block option in use */
149 };
150 
151 coap_lg_crcv_t * coap_block_new_lg_crcv(coap_session_t *session,
152                                         coap_pdu_t *pdu);
153 
154 void coap_block_delete_lg_crcv(coap_session_t *session,
155                                coap_lg_crcv_t *lg_crcv);
156 
157 coap_tick_t coap_block_check_lg_crcv_timeouts(coap_session_t *session,
158                                               coap_tick_t now);
159 
160 void coap_block_delete_lg_srcv(coap_session_t *session,
161                                coap_lg_srcv_t *lg_srcv);
162 
163 coap_tick_t coap_block_check_lg_srcv_timeouts(coap_session_t *session,
164                                               coap_tick_t now);
165 
166 int coap_handle_request_send_block(coap_session_t *session,
167                                    coap_pdu_t *pdu,
168                                    coap_pdu_t *response,
169                                    coap_resource_t *resource,
170                                    coap_string_t *query);
171 
172 int coap_handle_request_put_block(coap_context_t *context,
173                                   coap_session_t *session,
174                                   coap_pdu_t *pdu,
175                                   coap_pdu_t *response,
176                                   coap_resource_t *resource,
177                                   coap_string_t *uri_path,
178                                   coap_opt_t *observe,
179                                   coap_string_t *query,
180                                   coap_method_handler_t h,
181                                   int *added_block);
182 
183 int coap_handle_response_send_block(coap_session_t *session, coap_pdu_t *rcvd);
184 
185 int coap_handle_response_get_block(coap_context_t *context,
186                                    coap_session_t *session,
187                                    coap_pdu_t *sent,
188                                    coap_pdu_t *rcvd,
189                                    coap_recurse_t recursive);
190 
191 void coap_block_delete_lg_xmit(coap_session_t *session,
192                                coap_lg_xmit_t *lg_xmit);
193 
194 /**
195  * The function that does all the work for the coap_add_data_large*()
196  * functions.
197  *
198  * @param session  The session to associate the data with.
199  * @param pdu      The PDU to associate the data with.
200  * @param resource The resource to associate the data with (BLOCK2).
201  * @param query    The query to associate the data with (BLOCK2).
202  * @param maxage   The maxmimum life of the data. If @c -1, then there
203  *                 is no maxage (BLOCK2).
204  * @param etag     ETag to use if not 0 (BLOCK2).
205  * @param length   The length of data to transmit.
206  * @param data     The data to transmit.
207  * @param release_func The function to call to de-allocate @p data or NULL if
208  *                 the function is not required.
209  * @param app_ptr  A Pointer that the application can provide for when
210  *                 release_func() is called.
211  *
212  * @return @c 1 if transmission initiation is successful, else @c 0.
213  */
214 int coap_add_data_large_internal(coap_session_t *session,
215                         coap_pdu_t *pdu,
216                         coap_resource_t *resource,
217                         const coap_string_t *query,
218                         int maxage,
219                         uint64_t etag,
220                         size_t length,
221                         const uint8_t *data,
222                         coap_release_large_data_t release_func,
223                         void *app_ptr);
224 
225 /**
226  * The function checks that the code in a newly formed lg_xmit created by
227  * coap_add_data_large_response() is updated.
228  *
229  * @param session  The session
230  * @param response The response PDU to to check
231  * @param resource The requested resource
232  * @param query    The requested query
233  */
234 void coap_check_code_lg_xmit(coap_session_t *session, coap_pdu_t *response,
235                              coap_resource_t *resource, coap_string_t *query);
236 
237 /** @} */
238 
239 #endif /* COAP_BLOCK_INTERNAL_H_ */
240