Skip to content

Commit fc6fe95

Browse files
lylezhu2012kartben
authored andcommitted
Bluetooth: SDP: Notify partial records if RX buf is full
In current implementation, if the response total data length is more than the receiving buffer size, the request cannot be completed properly. Improve the SDP client with the following changes, o Notify the received completed SDP records if the case occurs, and then start the continuing SDP discovery, o Stop the SDP discovery if the hold SDP record cannot be saved to the receiving buffer, o Stop the SDP discovery if the `BT_SDP_DISCOVER_UUID_STOP` is returned by upper layer. Signed-off-by: Lyle Zhu <[email protected]>
1 parent aca9345 commit fc6fe95

File tree

1 file changed

+73
-5
lines changed
  • subsys/bluetooth/host/classic

1 file changed

+73
-5
lines changed

subsys/bluetooth/host/classic/sdp.c

Lines changed: 73 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2051,10 +2051,11 @@ static uint16_t get_record_len(struct bt_sdp_client *session)
20512051
enum uuid_state {
20522052
UUID_NOT_RESOLVED,
20532053
UUID_RESOLVED,
2054+
UUID_PARTIAL_RESOLVED,
20542055
};
20552056

2056-
static void sdp_client_notify_result(struct bt_sdp_client *session,
2057-
enum uuid_state state)
2057+
static int sdp_client_notify_result(struct bt_sdp_client *session,
2058+
enum uuid_state state)
20582059
{
20592060
struct bt_conn *conn = session->chan.chan.conn;
20602061
struct bt_sdp_client_result result;
@@ -2065,17 +2066,61 @@ static void sdp_client_notify_result(struct bt_sdp_client *session,
20652066
result.resp_buf = NULL;
20662067
result.next_record_hint = false;
20672068
session->param->func(conn, &result, session->param);
2068-
return;
2069+
return 0;
20692070
}
20702071

20712072
while (session->rec_buf->len) {
20722073
struct net_buf_simple_state buf_state;
20732074

2075+
net_buf_simple_save(&session->rec_buf->b, &buf_state);
20742076
rec_len = get_record_len(session);
20752077
/* tell the user about multi record resolution */
20762078
if (session->rec_buf->len > rec_len) {
20772079
result.next_record_hint = true;
20782080
} else {
2081+
if (state == UUID_PARTIAL_RESOLVED) {
2082+
struct net_buf *buf;
2083+
uint8_t *src, *dst;
2084+
uint16_t len;
2085+
2086+
net_buf_simple_restore(&session->rec_buf->b, &buf_state);
2087+
/* Partial resolution, continue processing */
2088+
src = session->rec_buf->data;
2089+
len = session->rec_buf->len;
2090+
2091+
/* The allocated buffer is full. Try to allocate a new buffer from
2092+
* the same pool. Use allocated buffer to continue the SDP
2093+
* discovery if the new buffer allocated. Otherwise, use the
2094+
* current allocated to continue the SDP discovery.
2095+
*/
2096+
buf = net_buf_alloc(session->param->pool, K_NO_WAIT);
2097+
if (buf != NULL) {
2098+
if (net_buf_tailroom(buf) < len) {
2099+
LOG_ERR("No more buffer space for SDP discover. "
2100+
"Need to increase buffer size of the "
2101+
"receiving pool.");
2102+
net_buf_unref(buf);
2103+
return -ENOMEM;
2104+
}
2105+
net_buf_add_mem(buf, src, len);
2106+
net_buf_unref(session->rec_buf);
2107+
session->rec_buf = buf;
2108+
LOG_DBG("Continue discovery with new buf %p", buf);
2109+
return 0;
2110+
}
2111+
2112+
net_buf_reset(session->rec_buf);
2113+
dst = net_buf_add(session->rec_buf, len);
2114+
if (dst == src) {
2115+
LOG_ERR("No more buffer space for SDP discover. Need to "
2116+
"increase buffer size of the receiving pool.");
2117+
return -ENOMEM;
2118+
}
2119+
2120+
memmove(dst, src, len);
2121+
LOG_DBG("Continue discovery with current buf");
2122+
return 0;
2123+
}
20792124
result.next_record_hint = false;
20802125
}
20812126

@@ -2100,9 +2145,11 @@ static void sdp_client_notify_result(struct bt_sdp_client *session,
21002145
*/
21012146
net_buf_pull(session->rec_buf, rec_len);
21022147
if (user_ret == BT_SDP_DISCOVER_UUID_STOP) {
2103-
break;
2148+
return -ECANCELED;
21042149
}
21052150
}
2151+
2152+
return 0;
21062153
}
21072154

21082155
static int sdp_client_discover(struct bt_sdp_client *session)
@@ -2264,6 +2311,11 @@ static int sdp_client_receive_ss(struct bt_sdp_client *session, struct net_buf *
22642311
return 0;
22652312
}
22662313

2314+
static int sdp_client_ssa_sa_notify(struct bt_sdp_client *session)
2315+
{
2316+
return sdp_client_notify_result(session, UUID_PARTIAL_RESOLVED);
2317+
}
2318+
22672319
static int sdp_client_receive_ssa_sa(struct bt_sdp_client *session, struct net_buf *buf)
22682320
{
22692321
struct bt_sdp_pdu_cstate *cstate;
@@ -2284,7 +2336,7 @@ static int sdp_client_receive_ssa_sa(struct bt_sdp_client *session, struct net_b
22842336
return -EINVAL;
22852337
}
22862338
/* Check valid range of attributes length */
2287-
if (((session->cstate.length == 0) && (frame_len < 2)) || (frame_len == 0)) {
2339+
if ((session->cstate.length == 0) && (frame_len < 2)) {
22882340
LOG_ERR("Invalid attributes data length");
22892341
return -EINVAL;
22902342
}
@@ -2302,6 +2354,22 @@ static int sdp_client_receive_ssa_sa(struct bt_sdp_client *session, struct net_b
23022354
return -EINVAL;
23032355
}
23042356

2357+
/* No more data found for given UUID and Continuation State length is not zero.
2358+
* It means the remaining tailroom of the RX buffer is not enough to store the data.
2359+
* Try to notify the received data, and request the next portion of data by sending a
2360+
* continuation request.
2361+
*/
2362+
if (frame_len == 0 && cstate->length != 0) {
2363+
/* Notify current received data */
2364+
int err;
2365+
2366+
err = sdp_client_ssa_sa_notify(session);
2367+
if (err != 0) {
2368+
LOG_ERR("Failed to notify received data: %d", err);
2369+
return err;
2370+
}
2371+
}
2372+
23052373
/*
23062374
* No record found for given UUID. The check catches case when
23072375
* current response frame has Continuation State shortest and

0 commit comments

Comments
 (0)