Skip to content

Commit c418d21

Browse files
lylezhu2012MaureenHelm
authored andcommitted
Bluetooth: GOEP: Improve TLV triplet encoding and parsing
Add a structure `struct bt_obex_tlv` to pass/save the one TLV info. Use a array of `struct bt_obex_tlv` as the set of all TLV-triplets. Update the following functions to support the feature, including `bt_obex_add_header_app_param`, `bt_obex_add_header_auth_challenge`, and `bt_obex_add_header_auth_rsp`. Add a function `bt_obex_tlv_parse` to parse the encoded TLV-triplets. Signed-off-by: Lyle Zhu <[email protected]>
1 parent 0dfae64 commit c418d21

File tree

2 files changed

+133
-33
lines changed
  • include/zephyr/bluetooth/classic
  • subsys/bluetooth/host/classic

2 files changed

+133
-33
lines changed

include/zephyr/bluetooth/classic/obex.h

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,15 +1020,30 @@ int bt_obex_add_header_who(struct net_buf *buf, uint16_t len, const uint8_t *who
10201020
*/
10211021
int bt_obex_add_header_conn_id(struct net_buf *buf, uint32_t conn_id);
10221022

1023+
/**
1024+
* @brief Bluetooth OBEX TLV triplet.
1025+
*
1026+
* Description of different data types that can be encoded into
1027+
* TLV triplet. Used to form arrays that are passed to the
1028+
* bt_obex_add_header_app_param(), bt_obex_add_header_auth_challenge(),
1029+
* and bt_obex_add_header_auth_rsp() function.
1030+
*/
1031+
struct bt_obex_tlv {
1032+
uint8_t type;
1033+
uint8_t data_len;
1034+
const uint8_t *data;
1035+
};
1036+
10231037
/** @brief Add Header: extended application request & response information.
10241038
*
10251039
* @param buf Buffer needs to be sent.
1026-
* @param len Length of app_param.
1027-
* @param app_param Application parameter.
1040+
* @param count Number of @ref bt_obex_tlv structures in @p data.
1041+
* @param data Array of @ref bt_obex_tlv structures.
10281042
*
10291043
* @return 0 in case of success or negative value in case of error.
10301044
*/
1031-
int bt_obex_add_header_app_param(struct net_buf *buf, uint16_t len, const uint8_t *app_param);
1045+
int bt_obex_add_header_app_param(struct net_buf *buf, size_t count,
1046+
const struct bt_obex_tlv data[]);
10321047

10331048
/**
10341049
* OBEX digest-challenge tag: Nonce
@@ -1058,12 +1073,13 @@ int bt_obex_add_header_app_param(struct net_buf *buf, uint16_t len, const uint8_
10581073
/** @brief Add Header: authentication digest-challenge.
10591074
*
10601075
* @param buf Buffer needs to be sent.
1061-
* @param len Length of auth_challenge.
1062-
* @param auth Authentication challenge.
1076+
* @param count Number of @ref bt_obex_tlv structures in @p data.
1077+
* @param data Array of @ref bt_obex_tlv structures.
10631078
*
10641079
* @return 0 in case of success or negative value in case of error.
10651080
*/
1066-
int bt_obex_add_header_auth_challenge(struct net_buf *buf, uint16_t len, const uint8_t *auth);
1081+
int bt_obex_add_header_auth_challenge(struct net_buf *buf, size_t count,
1082+
const struct bt_obex_tlv data[]);
10671083

10681084
/**
10691085
* OBEX digest-Response tag: Request-digest
@@ -1086,12 +1102,12 @@ int bt_obex_add_header_auth_challenge(struct net_buf *buf, uint16_t len, const u
10861102
/** @brief Add Header: authentication digest-response.
10871103
*
10881104
* @param buf Buffer needs to be sent.
1089-
* @param len Length of authentication response.
1090-
* @param auth Authentication response.
1105+
* @param count Number of @ref bt_obex_tlv structures in @p data.
1106+
* @param data Array of @ref bt_obex_tlv structures.
10911107
*
10921108
* @return 0 in case of success or negative value in case of error.
10931109
*/
1094-
int bt_obex_add_header_auth_rsp(struct net_buf *buf, uint16_t len, const uint8_t *auth);
1110+
int bt_obex_add_header_auth_rsp(struct net_buf *buf, size_t count, const struct bt_obex_tlv data[]);
10951111

10961112
/** @brief Add Header: indicates the creator of an object.
10971113
*
@@ -1342,7 +1358,31 @@ int bt_obex_get_header_who(struct net_buf *buf, uint16_t *len, const uint8_t **w
13421358
*/
13431359
int bt_obex_get_header_conn_id(struct net_buf *buf, uint32_t *conn_id);
13441360

1361+
/** @brief Helper for parsing OBEX TLV triplet.
1362+
*
1363+
* A helper for parsing the TLV triplet structure for OBEX packets. The most common scenario is to
1364+
* call this helper on the in the callback of OBEX server and client.
1365+
* The @p data is encoded by using A Tag-Length-Value encoding scheme. Usually, it is the header
1366+
* value of the header `Application Request-Response Parameters`, `Authenticate Challenge`, and
1367+
* `Authenticate Response`. It means the @p data is the output of the
1368+
* @ref bt_obex_get_header_app_param, @ref bt_obex_get_header_auth_challenge, or
1369+
* @ref bt_obex_get_header_auth_rsp.
1370+
*
1371+
* @param len The length of the @p data.
1372+
* @param data The data as given to the callback of OBEX server and client.
1373+
* @param func Callback function which will be called for each TLV triplet that's found from the
1374+
* @p data. The callback should return true to continue parsing, or false to stop
1375+
* parsing.
1376+
* @param user_data User data to be passed to the callback.
1377+
*
1378+
* @return 0 in case of success or negative value in case of error.
1379+
*/
1380+
int bt_obex_tlv_parse(uint16_t len, const uint8_t *data,
1381+
bool (*func)(struct bt_obex_tlv *tlv, void *user_data), void *user_data);
1382+
13451383
/** @brief Get header value: extended application request & response information.
1384+
*
1385+
* The parameter can be parsed by calling @ref bt_obex_tlv_parse.
13461386
*
13471387
* @param buf Buffer needs to be sent.
13481388
* @param len Length of app_param.
@@ -1353,6 +1393,8 @@ int bt_obex_get_header_conn_id(struct net_buf *buf, uint32_t *conn_id);
13531393
int bt_obex_get_header_app_param(struct net_buf *buf, uint16_t *len, const uint8_t **app_param);
13541394

13551395
/** @brief Get header value: authentication digest-challenge.
1396+
*
1397+
* The options can be parsed by calling @ref bt_obex_tlv_parse.
13561398
*
13571399
* @param buf Buffer needs to be sent.
13581400
* @param len Length of auth_challenge.
@@ -1363,6 +1405,8 @@ int bt_obex_get_header_app_param(struct net_buf *buf, uint16_t *len, const uint8
13631405
int bt_obex_get_header_auth_challenge(struct net_buf *buf, uint16_t *len, const uint8_t **auth);
13641406

13651407
/** @brief Get header value: authentication digest-response.
1408+
*
1409+
* The options can be parsed by calling @ref bt_obex_tlv_parse.
13661410
*
13671411
* @param buf Buffer needs to be sent.
13681412
* @param len Length of authentication response.

subsys/bluetooth/host/classic/obex.c

Lines changed: 80 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2285,78 +2285,106 @@ int bt_obex_add_header_conn_id(struct net_buf *buf, uint32_t conn_id)
22852285
return 0;
22862286
}
22872287

2288-
int bt_obex_add_header_app_param(struct net_buf *buf, uint16_t len, const uint8_t *app_param)
2288+
int bt_obex_add_header_app_param(struct net_buf *buf, size_t count, const struct bt_obex_tlv data[])
22892289
{
22902290
size_t total;
2291+
uint16_t len = 0;
22912292

2292-
if (!buf || !app_param || !len) {
2293+
if (!buf || !data || !count) {
22932294
LOG_WRN("Invalid parameter");
22942295
return -EINVAL;
22952296
}
22962297

2298+
for (size_t i = 0; i < count; i++) {
2299+
if (data[i].data_len && !data[i].data) {
2300+
LOG_WRN("Invalid parameter");
2301+
return -EINVAL;
2302+
}
2303+
len += data[i].data_len + sizeof(data[i].type) + sizeof(data[i].data_len);
2304+
}
2305+
22972306
total = sizeof(uint8_t) + sizeof(len) + len;
22982307
if (net_buf_tailroom(buf) < total) {
22992308
return -ENOMEM;
23002309
}
23012310

2302-
if (!bt_obex_string_is_valid(BT_OBEX_HEADER_ID_APP_PARAM, len, app_param)) {
2303-
LOG_WRN("Invalid string");
2304-
return -EINVAL;
2305-
}
2306-
23072311
net_buf_add_u8(buf, BT_OBEX_HEADER_ID_APP_PARAM);
23082312
net_buf_add_be16(buf, (uint16_t)total);
2309-
net_buf_add_mem(buf, app_param, len);
2313+
for (size_t i = 0; i < count; i++) {
2314+
len += data[i].data_len + sizeof(data[i].type) + sizeof(data[i].data_len);
2315+
net_buf_add_u8(buf, data[i].type);
2316+
net_buf_add_u8(buf, data[i].data_len);
2317+
net_buf_add_mem(buf, data[i].data, (size_t)data[i].data_len);
2318+
}
23102319
return 0;
23112320
}
23122321

2313-
int bt_obex_add_header_auth_challenge(struct net_buf *buf, uint16_t len, const uint8_t *auth)
2322+
int bt_obex_add_header_auth_challenge(struct net_buf *buf, size_t count,
2323+
const struct bt_obex_tlv data[])
23142324
{
23152325
size_t total;
2326+
uint16_t len = 0;
23162327

2317-
if (!buf || !auth || !len) {
2328+
if (!buf || !data || !count) {
23182329
LOG_WRN("Invalid parameter");
23192330
return -EINVAL;
23202331
}
23212332

2333+
for (size_t i = 0; i < count; i++) {
2334+
if (data[i].data_len && !data[i].data) {
2335+
LOG_WRN("Invalid parameter");
2336+
return -EINVAL;
2337+
}
2338+
len += data[i].data_len + sizeof(data[i].type) + sizeof(data[i].data_len);
2339+
}
2340+
23222341
total = sizeof(uint8_t) + sizeof(len) + len;
23232342
if (net_buf_tailroom(buf) < total) {
23242343
return -ENOMEM;
23252344
}
23262345

2327-
if (!bt_obex_string_is_valid(BT_OBEX_HEADER_ID_AUTH_CHALLENGE, len, auth)) {
2328-
LOG_WRN("Invalid string");
2329-
return -EINVAL;
2330-
}
2331-
23322346
net_buf_add_u8(buf, BT_OBEX_HEADER_ID_AUTH_CHALLENGE);
23332347
net_buf_add_be16(buf, (uint16_t)total);
2334-
net_buf_add_mem(buf, auth, len);
2348+
for (size_t i = 0; i < count; i++) {
2349+
len += data[i].data_len + sizeof(data[i].type) + sizeof(data[i].data_len);
2350+
net_buf_add_u8(buf, data[i].type);
2351+
net_buf_add_u8(buf, data[i].data_len);
2352+
net_buf_add_mem(buf, data[i].data, (size_t)data[i].data_len);
2353+
}
23352354
return 0;
23362355
}
23372356

2338-
int bt_obex_add_header_auth_rsp(struct net_buf *buf, uint16_t len, const uint8_t *auth)
2357+
int bt_obex_add_header_auth_rsp(struct net_buf *buf, size_t count, const struct bt_obex_tlv data[])
23392358
{
23402359
size_t total;
2360+
uint16_t len = 0;
23412361

2342-
if (!buf || !auth || !len) {
2362+
if (!buf || !data || !count) {
23432363
LOG_WRN("Invalid parameter");
23442364
return -EINVAL;
23452365
}
23462366

2367+
for (size_t i = 0; i < count; i++) {
2368+
if (data[i].data_len && !data[i].data) {
2369+
LOG_WRN("Invalid parameter");
2370+
return -EINVAL;
2371+
}
2372+
len += data[i].data_len + sizeof(data[i].type) + sizeof(data[i].data_len);
2373+
}
2374+
23472375
total = sizeof(uint8_t) + sizeof(len) + len;
23482376
if (net_buf_tailroom(buf) < total) {
23492377
return -ENOMEM;
23502378
}
23512379

2352-
if (!bt_obex_string_is_valid(BT_OBEX_HEADER_ID_AUTH_RSP, len, auth)) {
2353-
LOG_WRN("Invalid string");
2354-
return -EINVAL;
2355-
}
2356-
23572380
net_buf_add_u8(buf, BT_OBEX_HEADER_ID_AUTH_RSP);
23582381
net_buf_add_be16(buf, (uint16_t)total);
2359-
net_buf_add_mem(buf, auth, len);
2382+
for (size_t i = 0; i < count; i++) {
2383+
len += data[i].data_len + sizeof(data[i].type) + sizeof(data[i].data_len);
2384+
net_buf_add_u8(buf, data[i].type);
2385+
net_buf_add_u8(buf, data[i].data_len);
2386+
net_buf_add_mem(buf, data[i].data, (size_t)data[i].data_len);
2387+
}
23602388
return 0;
23612389
}
23622390

@@ -3010,6 +3038,34 @@ int bt_obex_get_header_conn_id(struct net_buf *buf, uint32_t *conn_id)
30103038
return 0;
30113039
}
30123040

3041+
int bt_obex_tlv_parse(uint16_t len, const uint8_t *data,
3042+
bool (*func)(struct bt_obex_tlv *tlv, void *user_data), void *user_data)
3043+
{
3044+
uint16_t index = 0;
3045+
struct bt_obex_tlv tlv;
3046+
3047+
if (!len || !data || !func) {
3048+
LOG_WRN("Invalid parameter");
3049+
return -EINVAL;
3050+
}
3051+
3052+
while ((index + 2) <= len) {
3053+
tlv.type = data[index];
3054+
tlv.data_len = data[index + 1];
3055+
index += 2;
3056+
if ((index + tlv.data_len) > len) {
3057+
break;
3058+
}
3059+
3060+
tlv.data = &data[index];
3061+
index += tlv.data_len;
3062+
if (!func(&tlv, user_data)) {
3063+
return 0;
3064+
}
3065+
}
3066+
return 0;
3067+
}
3068+
30133069
int bt_obex_get_header_app_param(struct net_buf *buf, uint16_t *len, const uint8_t **app_param)
30143070
{
30153071
struct bt_obex_find_header_data data;

0 commit comments

Comments
 (0)