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, uint8_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