xref: /btstack/src/classic/obex_parser.h (revision f4a7fdb58b86de5021755e6288d669e308ddbf2c)
1 /*
2  * Copyright (C) 2021 BlueKitchen GmbH
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holders nor the names of
14  *    contributors may be used to endorse or promote products derived
15  *    from this software without specific prior written permission.
16  * 4. Any redistribution, use, or modification is done solely for
17  *    personal benefit and not for any commercial purpose or for
18  *    monetary gain.
19  *
20  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * Please inquire about commercial licensing options at
34  * [email protected]
35  *
36  */
37 
38 /**
39  * OBEX Parser
40  * Parser incoming arbitrarily chunked OBEX object
41  */
42 
43 #ifndef OBEX_PARSER_H
44 #define OBEX_PARSER_H
45 
46 #if defined __cplusplus
47 extern "C" {
48 #endif
49 
50 #include <stdint.h>
51 
52 typedef enum {
53     OBEX_PARSER_STATE_W4_OPCODE,
54     OBEX_PARSER_STATE_W4_RESPONSE_CODE,
55     OBEX_PARSER_STATE_W4_PACKET_LEN,
56     OBEX_PARSER_STATE_W4_PARAMS,
57     OBEX_PARSER_STATE_W4_HEADER_ID,
58     OBEX_PARSER_STATE_W4_HEADER_LEN_FIRST,
59     OBEX_PARSER_STATE_W4_HEADER_LEN_SECOND,
60     OBEX_PARSER_STATE_W4_HEADER_VALUE,
61     OBEX_PARSER_STATE_COMPLETE,
62     OBEX_PARSER_STATE_OVERRUN,
63     OBEX_PARSER_STATE_INVALID,
64 } obex_parser_state_t;
65 
66 /* API_START */
67 
68 /**
69  * Callback to process chunked data
70  * @param user_data provided in obex_parser_init
71  * @param header_id current OBEX header ID
72  * @param total_len of header
73  * @param data_offset
74  * @param data_len
75  * @param data_buffer
76  */
77 typedef void (*obex_parser_callback_t)(void * user_data, uint8_t header_id, uint16_t total_len, uint16_t data_offset, const uint8_t * data_buffer, uint16_t data_len);
78 
79 typedef enum {
80     OBEX_PARSER_OBJECT_STATE_INCOMPLETE,
81     OBEX_PARSER_OBJECT_STATE_COMPLETE,
82     OBEX_PARSER_OBJECT_STATE_OVERRUN,
83     OBEX_PARSER_OBJECT_STATE_INVALID,
84 } obex_parser_object_state_t;
85 
86 typedef enum {
87     OBEX_PARSER_HEADER_INCOMPLETE,
88     OBEX_PARSER_HEADER_COMPLETE,
89     OBEX_PARSER_HEADER_OVERRUN,
90 } obex_parser_header_state_t;
91 
92 typedef struct {
93     uint8_t  opcode;
94     uint8_t  response_code;
95     // Connect only
96     uint8_t  obex_version_number;
97     uint16_t max_packet_length;
98     // Connect + Set Path only
99     uint8_t  flags;
100 } obex_parser_operation_info_t;
101 
102 typedef struct {
103     obex_parser_callback_t callback;
104     void * user_data;
105     uint16_t packet_size;
106     uint16_t packet_pos;
107     obex_parser_state_t state;
108     uint8_t  opcode;
109     uint8_t  response_code;
110     uint16_t item_len;
111     uint16_t item_pos;
112     uint8_t  params[6]; // for connect and set path
113     uint8_t  header_id;
114 } obex_parser_t;
115 
116 /**
117  * Callback to process chunked data
118  * @param user_data provided in obex_parser_init
119  * @param header_id current OBEX header ID
120  * @param total_len of header
121  * @param data_offset
122  * @param data_len
123  * @param data_buffer
124  */
125 typedef void (*obex_app_param_parser_callback_t)(void * user_data, uint8_t tag_id, uint8_t total_len, uint8_t data_offset, const uint8_t * data_buffer, uint8_t data_len);
126 
127 typedef enum {
128     OBEX_APP_PARAM_PARSER_PARAMS_STATE_INCOMPLETE,
129     OBEX_APP_PARAM_PARSER_PARAMS_STATE_COMPLETE,
130     OBEX_APP_PARAM_PARSER_PARAMS_STATE_OVERRUN,
131     OBEX_APP_PARAM_PARSER_PARAMS_STATE_INVALID,
132 } obex_app_param_parser_params_state_t;
133 
134 typedef enum {
135     OBEX_APP_PARAM_PARSER_TAG_INCOMPLETE,
136     OBEX_APP_PARAM_PARSER_TAG_COMPLETE,
137     OBEX_APP_PARAM_PARSER_TAG_OVERRUN,
138 } obex_app_param_parser_tag_state_t;
139 
140 typedef enum {
141     OBEX_APP_PARAM_PARSER_STATE_W4_TYPE = 0,
142     OBEX_APP_PARAM_PARSER_STATE_W4_LEN,
143     OBEX_APP_PARAM_PARSER_STATE_W4_VALUE,
144     OBEX_APP_PARAM_PARSER_STATE_COMPLETE,
145     OBEX_APP_PARAM_PARSER_STATE_INVALID,
146     OBEX_APP_PARAM_PARSER_STATE_OVERRUN,
147 } obex_app_param_parser_state_t;
148 
149 typedef struct {
150     obex_app_param_parser_callback_t callback;
151     obex_app_param_parser_state_t state;
152     void * user_data;
153     uint16_t param_size;
154     uint16_t param_pos;
155     uint16_t tag_len;
156     uint16_t tag_pos;
157     uint8_t  tag_id;
158 } obex_app_param_parser_t;
159 
160 /**
161  * Initialize OBEX Parser for next OBEX request
162  * @param obex_parser
163  * @param function to call for field data
164  * @param user_data provided to callback function
165  */
166 void obex_parser_init_for_request(obex_parser_t * obex_parser, obex_parser_callback_t obex_parser_callback, void * user_data);
167 
168 /**
169  * Initialize OBEX Parser for next OBEX response
170  * @param obex_parser
171  * @param opcode of request - needed as responses with additional fields like connect and set path
172  * @param function to call for field data
173  * @param user_data provided to callback function
174  */
175 void obex_parser_init_for_response(obex_parser_t * obex_parser, uint8_t opcode, obex_parser_callback_t obex_parser_callback, void * user_data);
176 
177 /**
178  * Process OBEX data
179  * @param obex_parser
180  * @param data_len
181  * @param data_buffer
182  * @return OBEX_PARSER_OBJECT_STATE_COMPLETE if packet has been completely parsed
183  */
184 obex_parser_object_state_t obex_parser_process_data(obex_parser_t *obex_parser, const uint8_t *data_buffer, uint16_t data_len);
185 
186 /**
187  * Get operation info for request/response packets
188  * @param obex_parser
189  * @return
190  */
191 void obex_parser_get_operation_info(obex_parser_t * obex_parser, obex_parser_operation_info_t * obex_operation_info);
192 
193 /**
194  * Helper to collect header chunks in fixed-size header buffer
195  * @param header_buffer
196  * @param buffer_size of header_buffer
197  * @param total_len of header value
198  * @param data_offset of chunk to store
199  * @param data_buffer
200  * @param data_len chunk length
201  * @return OBEX_PARSER_HEADER_COMPLETE when header value complete
202  */
203 obex_parser_header_state_t obex_parser_header_store(uint8_t * header_buffer, uint16_t buffer_size, uint16_t total_len,
204                                                     uint16_t data_offset, const uint8_t * data_buffer, uint16_t data_len);
205 
206 /**
207  * Initialize OBEX Application Param Parser
208  * @param parser
209  * @param function to call for tag data
210  * @param param_size of OBEX_HEADER_APPLICATION_PARAMETERS header
211  * @param user_data provided to callback function
212  */
213 void obex_app_param_parser_init(obex_app_param_parser_t * parser, obex_app_param_parser_callback_t callback, uint16_t param_size, void * user_data);
214 
215 /**
216  * Process OBEX App Param data
217  * @param parser
218  * @param data_len
219  * @param data_buffer
220  * @return OBEX_APP_PARAM_PARSER_PARAMS_STATE_COMPLETE if packet has been completely parsed
221  */
222 obex_app_param_parser_params_state_t obex_app_param_parser_process_data(obex_app_param_parser_t *parser, const uint8_t *data_buffer, uint16_t data_len);
223 
224 /**
225  * Helper to collect tag chunks in fixed-size data buffer
226  * @param tag_buffer
227  * @param buffer_size of data buffer
228  * @param total_len of tag value
229  * @param data_offset of chunk to store
230  * @param data_buffer
231  * @param data_len chunk length
232  * @return OBEX_APP_PARAM_PARSER_TAG_COMPLETE when tag complete
233  */
234 
235 obex_app_param_parser_tag_state_t obex_app_param_parser_tag_store(uint8_t * tag_buffer, uint8_t buffer_size, uint8_t total_len,
236                                                                   uint8_t data_offset, const uint8_t * data_buffer, uint8_t data_len);
237 
238 
239 /* API_END */
240 
241 #if defined __cplusplus
242 }
243 #endif
244 #endif
245