xref: /btstack/src/classic/obex_parser.h (revision ac9a0d84d5f7a715f496fcd8d0dd3b859de2f81a)
1*ac9a0d84SMatthias Ringwald /*
2*ac9a0d84SMatthias Ringwald  * Copyright (C) 2021 BlueKitchen GmbH
3*ac9a0d84SMatthias Ringwald  *
4*ac9a0d84SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5*ac9a0d84SMatthias Ringwald  * modification, are permitted provided that the following conditions
6*ac9a0d84SMatthias Ringwald  * are met:
7*ac9a0d84SMatthias Ringwald  *
8*ac9a0d84SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9*ac9a0d84SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10*ac9a0d84SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11*ac9a0d84SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12*ac9a0d84SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13*ac9a0d84SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14*ac9a0d84SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15*ac9a0d84SMatthias Ringwald  *    from this software without specific prior written permission.
16*ac9a0d84SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
17*ac9a0d84SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
18*ac9a0d84SMatthias Ringwald  *    monetary gain.
19*ac9a0d84SMatthias Ringwald  *
20*ac9a0d84SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21*ac9a0d84SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*ac9a0d84SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23*ac9a0d84SMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24*ac9a0d84SMatthias Ringwald  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25*ac9a0d84SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26*ac9a0d84SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27*ac9a0d84SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28*ac9a0d84SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29*ac9a0d84SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30*ac9a0d84SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*ac9a0d84SMatthias Ringwald  * SUCH DAMAGE.
32*ac9a0d84SMatthias Ringwald  *
33*ac9a0d84SMatthias Ringwald  * Please inquire about commercial licensing options at
34*ac9a0d84SMatthias Ringwald  * [email protected]
35*ac9a0d84SMatthias Ringwald  *
36*ac9a0d84SMatthias Ringwald  */
37*ac9a0d84SMatthias Ringwald 
38*ac9a0d84SMatthias Ringwald /**
39*ac9a0d84SMatthias Ringwald  * OBEX Parser
40*ac9a0d84SMatthias Ringwald  * Parser incoming arbitrarily chunked OBEX object
41*ac9a0d84SMatthias Ringwald  */
42*ac9a0d84SMatthias Ringwald 
43*ac9a0d84SMatthias Ringwald #ifndef OBEX_PARSER_H
44*ac9a0d84SMatthias Ringwald #define OBEX_PARSER_H
45*ac9a0d84SMatthias Ringwald 
46*ac9a0d84SMatthias Ringwald #if defined __cplusplus
47*ac9a0d84SMatthias Ringwald extern "C" {
48*ac9a0d84SMatthias Ringwald #endif
49*ac9a0d84SMatthias Ringwald 
50*ac9a0d84SMatthias Ringwald #include <stdint.h>
51*ac9a0d84SMatthias Ringwald 
52*ac9a0d84SMatthias Ringwald typedef enum {
53*ac9a0d84SMatthias Ringwald     OBEX_PARSER_STATE_W4_OPCODE,
54*ac9a0d84SMatthias Ringwald     OBEX_PARSER_STATE_W4_RESPONSE_CODE,
55*ac9a0d84SMatthias Ringwald     OBEX_PARSER_STATE_W4_PACKET_LEN,
56*ac9a0d84SMatthias Ringwald     OBEX_PARSER_STATE_W4_PARAMS,
57*ac9a0d84SMatthias Ringwald     OBEX_PARSER_STATE_W4_HEADER_ID,
58*ac9a0d84SMatthias Ringwald     OBEX_PARSER_STATE_W4_HEADER_LEN_FIRST,
59*ac9a0d84SMatthias Ringwald     OBEX_PARSER_STATE_W4_HEADER_LEN_SECOND,
60*ac9a0d84SMatthias Ringwald     OBEX_PARSER_STATE_W4_HEADER_VALUE,
61*ac9a0d84SMatthias Ringwald     OBEX_PARSER_STATE_COMPLETE,
62*ac9a0d84SMatthias Ringwald     OBEX_PARSER_STATE_OVERRUN,
63*ac9a0d84SMatthias Ringwald     OBEX_PARSER_STATE_INVALID,
64*ac9a0d84SMatthias Ringwald } obex_parser_state_t;
65*ac9a0d84SMatthias Ringwald 
66*ac9a0d84SMatthias Ringwald /* API_START */
67*ac9a0d84SMatthias Ringwald 
68*ac9a0d84SMatthias Ringwald /**
69*ac9a0d84SMatthias Ringwald  * Callback to process chunked data
70*ac9a0d84SMatthias Ringwald  * @param user_data provided in obex_parser_init
71*ac9a0d84SMatthias Ringwald  * @param header_id current OBEX header ID
72*ac9a0d84SMatthias Ringwald  * @param total_len of header
73*ac9a0d84SMatthias Ringwald  * @param data_offset
74*ac9a0d84SMatthias Ringwald  * @param data_len
75*ac9a0d84SMatthias Ringwald  * @param data_buffer
76*ac9a0d84SMatthias Ringwald  */
77*ac9a0d84SMatthias Ringwald 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*ac9a0d84SMatthias Ringwald 
79*ac9a0d84SMatthias Ringwald typedef enum {
80*ac9a0d84SMatthias Ringwald     OBEX_PARSER_OBJECT_STATE_INCOMPLETE,
81*ac9a0d84SMatthias Ringwald     OBEX_PARSER_OBJECT_STATE_COMPLETE,
82*ac9a0d84SMatthias Ringwald     OBEX_PARSER_OBJECT_STATE_OVERRUN,
83*ac9a0d84SMatthias Ringwald     OBEX_PARSER_OBJECT_STATE_INVALID,
84*ac9a0d84SMatthias Ringwald } obex_parser_object_state_t;
85*ac9a0d84SMatthias Ringwald 
86*ac9a0d84SMatthias Ringwald typedef enum {
87*ac9a0d84SMatthias Ringwald     OBEX_PARSER_HEADER_INCOMPLETE,
88*ac9a0d84SMatthias Ringwald     OBEX_PARSER_HEADER_COMPLETE,
89*ac9a0d84SMatthias Ringwald     OBEX_PARSER_HEADER_OVERRUN,
90*ac9a0d84SMatthias Ringwald } obex_parser_header_state_t;
91*ac9a0d84SMatthias Ringwald 
92*ac9a0d84SMatthias Ringwald typedef struct {
93*ac9a0d84SMatthias Ringwald     uint8_t  opcode;
94*ac9a0d84SMatthias Ringwald     uint8_t  response_code;
95*ac9a0d84SMatthias Ringwald     // Connect only
96*ac9a0d84SMatthias Ringwald     uint8_t  obex_version_number;
97*ac9a0d84SMatthias Ringwald     uint16_t max_packet_length;
98*ac9a0d84SMatthias Ringwald     // Connect + Set Path only
99*ac9a0d84SMatthias Ringwald     uint8_t  flags;
100*ac9a0d84SMatthias Ringwald } obex_parser_operation_info_t;
101*ac9a0d84SMatthias Ringwald 
102*ac9a0d84SMatthias Ringwald typedef struct {
103*ac9a0d84SMatthias Ringwald     obex_parser_callback_t callback;
104*ac9a0d84SMatthias Ringwald     void * user_data;
105*ac9a0d84SMatthias Ringwald     uint16_t packet_size;
106*ac9a0d84SMatthias Ringwald     uint16_t packet_pos;
107*ac9a0d84SMatthias Ringwald     obex_parser_state_t state;
108*ac9a0d84SMatthias Ringwald     uint8_t  opcode;
109*ac9a0d84SMatthias Ringwald     uint8_t  response_code;
110*ac9a0d84SMatthias Ringwald     uint16_t item_len;
111*ac9a0d84SMatthias Ringwald     uint16_t item_pos;
112*ac9a0d84SMatthias Ringwald     uint8_t  params[6]; // for connect and set path
113*ac9a0d84SMatthias Ringwald     uint8_t  header_id;
114*ac9a0d84SMatthias Ringwald } obex_parser_t;
115*ac9a0d84SMatthias Ringwald 
116*ac9a0d84SMatthias Ringwald /**
117*ac9a0d84SMatthias Ringwald  * Initialize OBEX Parser for next OBEX request
118*ac9a0d84SMatthias Ringwald  * @param obex_parser
119*ac9a0d84SMatthias Ringwald  * @param function to call for fields that are not registered
120*ac9a0d84SMatthias Ringwald  * @param user_data provided to callback function
121*ac9a0d84SMatthias Ringwald  */
122*ac9a0d84SMatthias Ringwald void obex_parser_init_for_request(obex_parser_t * obex_parser, obex_parser_callback_t obex_parser_callback, void * user_data);
123*ac9a0d84SMatthias Ringwald 
124*ac9a0d84SMatthias Ringwald /**
125*ac9a0d84SMatthias Ringwald  * Initialize OBEX Parser for next OBEX response
126*ac9a0d84SMatthias Ringwald  * @param obex_parser
127*ac9a0d84SMatthias Ringwald  * @param opcode of request - needed as responses with additional fields like connect and set path
128*ac9a0d84SMatthias Ringwald  * @param function to call for fields that are not registered
129*ac9a0d84SMatthias Ringwald  * @param user_data provided to callback function
130*ac9a0d84SMatthias Ringwald  */
131*ac9a0d84SMatthias Ringwald void obex_parser_init_for_response(obex_parser_t * obex_parser, uint8_t opcode, obex_parser_callback_t obex_parser_callback, void * user_data);
132*ac9a0d84SMatthias Ringwald 
133*ac9a0d84SMatthias Ringwald /**
134*ac9a0d84SMatthias Ringwald  * Process OBEX data
135*ac9a0d84SMatthias Ringwald  * @param obex_parser
136*ac9a0d84SMatthias Ringwald  * @param data_len
137*ac9a0d84SMatthias Ringwald  * @param data_buffer
138*ac9a0d84SMatthias Ringwald  * @return OBEX_PARSER_OBJECT_STATE_COMPLETE if packet has been completely parsed
139*ac9a0d84SMatthias Ringwald  */
140*ac9a0d84SMatthias Ringwald obex_parser_object_state_t obex_parser_process_data(obex_parser_t *obex_parser, const uint8_t *data_buffer, uint16_t data_len);
141*ac9a0d84SMatthias Ringwald 
142*ac9a0d84SMatthias Ringwald /**
143*ac9a0d84SMatthias Ringwald  * Get operation info for request/response packets
144*ac9a0d84SMatthias Ringwald  * @param obex_parser
145*ac9a0d84SMatthias Ringwald  * @return
146*ac9a0d84SMatthias Ringwald  */
147*ac9a0d84SMatthias Ringwald void obex_parser_get_operation_info(obex_parser_t * obex_parser, obex_parser_operation_info_t * obex_operation_info);
148*ac9a0d84SMatthias Ringwald 
149*ac9a0d84SMatthias Ringwald /**
150*ac9a0d84SMatthias Ringwald  * Helper to collect header chunks in fixed-size header buffer
151*ac9a0d84SMatthias Ringwald  * @param header_buffer
152*ac9a0d84SMatthias Ringwald  * @param buffer_size of header_buffer
153*ac9a0d84SMatthias Ringwald  * @param total_len of header value
154*ac9a0d84SMatthias Ringwald  * @param data_offset of chunkc to store
155*ac9a0d84SMatthias Ringwald  * @param data_buffer
156*ac9a0d84SMatthias Ringwald  * @param data_len chunk length
157*ac9a0d84SMatthias Ringwald  * @return OBEX_PARSER_HEADER_COMPLETE when header value complete
158*ac9a0d84SMatthias Ringwald  */
159*ac9a0d84SMatthias Ringwald obex_parser_header_state_t obex_parser_header_store(uint8_t * header_buffer, uint16_t buffer_size, uint16_t total_len,
160*ac9a0d84SMatthias Ringwald                                                     uint16_t data_offset, const uint8_t * data_buffer, uint16_t data_len);
161*ac9a0d84SMatthias Ringwald 
162*ac9a0d84SMatthias Ringwald 
163*ac9a0d84SMatthias Ringwald /* API_END */
164*ac9a0d84SMatthias Ringwald 
165*ac9a0d84SMatthias Ringwald #if defined __cplusplus
166*ac9a0d84SMatthias Ringwald }
167*ac9a0d84SMatthias Ringwald #endif
168*ac9a0d84SMatthias Ringwald #endif
169