aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Yi <byi@google.com>2021-11-02 21:07:56 -0700
committerBill Yi <byi@google.com>2021-11-02 21:07:56 -0700
commit397efaab3e1580e9b7a206f2223d604f72071032 (patch)
tree7484eb8fee612db008301ae5d5cebbeac9989a75
parent732295891a70c731883dca07f68991709151a8d1 (diff)
parent54801d7a309c022b11ecf97fe04b63dd082b14f5 (diff)
downloadbt-397efaab3e1580e9b7a206f2223d604f72071032.tar.gz
Merge SP1A.211105.004 to aosp-master - DO NOT MERGE
Merged-In: I9da612947a9b6efdaf8e31f83f84075368352aa1 Merged-In: Ib47c2e2fc1b4a998bb5d31b55ea7c6cd7fe26eb7 Change-Id: I21fb2db3a75a2b5aae29014f62b99c43c4b98672
-rw-r--r--stack/gatt/gatt_cl.cc122
1 files changed, 82 insertions, 40 deletions
diff --git a/stack/gatt/gatt_cl.cc b/stack/gatt/gatt_cl.cc
index 831d031b9..d8896b3a9 100644
--- a/stack/gatt/gatt_cl.cc
+++ b/stack/gatt/gatt_cl.cc
@@ -615,6 +615,7 @@ void gatt_process_prep_write_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
gatt_end_operation(p_clcb, p_clcb->status, &value);
}
}
+
/*******************************************************************************
*
* Function gatt_process_notification
@@ -626,10 +627,10 @@ void gatt_process_prep_write_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
******************************************************************************/
void gatt_process_notification(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code,
uint16_t len, uint8_t* p_data) {
- tGATT_VALUE value;
+ tGATT_VALUE value = {};
tGATT_REG* p_reg;
uint16_t conn_id;
- tGATT_STATUS encrypt_status;
+ tGATT_STATUS encrypt_status = {};
uint8_t* p = p_data;
uint8_t i;
tGATTC_OPTYPE event = (op_code == GATT_HANDLE_VALUE_IND)
@@ -638,34 +639,52 @@ void gatt_process_notification(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code,
VLOG(1) << __func__;
+ // Ensure our packet has enough data (2 bytes)
if (len < GATT_NOTIFICATION_MIN_LEN) {
LOG(ERROR) << "illegal notification PDU length, discard";
return;
}
- memset(&value, 0, sizeof(value));
+ // Get 2 byte handle
STREAM_TO_UINT16(value.handle, p);
+ // Fail early if the GATT handle is not valid
+ if (!GATT_HANDLE_IS_VALID(value.handle)) {
+ /* illegal handle, send ack now */
+ if (op_code == GATT_HANDLE_VALUE_IND)
+ attp_send_cl_confirmation_msg(tcb, cid);
+ return;
+ }
+
+ // Calculate value length based on opcode
if (op_code == GATT_HANDLE_MULTI_VALUE_NOTIF) {
+ // Ensure our packet has enough data; MIN + 2 more bytes for len value
+ if (len < GATT_NOTIFICATION_MIN_LEN + 2) {
+ LOG(ERROR) << "illegal notification PDU length, discard";
+ return;
+ }
+
+ // Allow multi value opcode to set value len from the packet
STREAM_TO_UINT16(value.len, p);
+
+ if (value.len > len - 4) {
+ LOG(ERROR) << "value.len (" << value.len << ") greater than length ("
+ << (len - 4);
+ return;
+ }
+
} else {
+ // For single value, just use the passed in len minus opcode length (2)
value.len = len - 2;
}
+ // Verify the new calculated length
if (value.len > GATT_MAX_ATTR_LEN) {
LOG(ERROR) << "value.len larger than GATT_MAX_ATTR_LEN, discard";
return;
}
- STREAM_TO_ARRAY(value.value, p, value.len);
-
- if (!GATT_HANDLE_IS_VALID(value.handle)) {
- /* illegal handle, send ack now */
- if (op_code == GATT_HANDLE_VALUE_IND)
- attp_send_cl_confirmation_msg(tcb, cid);
- return;
- }
-
+ // Handle indications differently
if (event == GATTC_OPTYPE_INDICATION) {
if (tcb.ind_count) {
/* this is an error case that receiving an indication but we
@@ -676,34 +695,67 @@ void gatt_process_notification(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code,
LOG(ERROR) << __func__ << " rcv Ind. but ind_count=" << tcb.ind_count
<< " (will reset ind_count)";
}
- tcb.ind_count = 0;
- }
- /* should notify all registered client with the handle value
- notificaion/indication
- Note: need to do the indication count and start timer first then do
- callback
- */
+ // Zero out the ind_count
+ tcb.ind_count = 0;
- for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++) {
- if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb &&
- (event == GATTC_OPTYPE_INDICATION))
- tcb.ind_count++;
- }
+ // Notify all registered clients with the handle value
+ // notification/indication
+ // Note: need to do the indication count and start timer first then do
+ // callback
+ for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++) {
+ if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb) tcb.ind_count++;
+ }
- if (event == GATTC_OPTYPE_INDICATION) {
/* start a timer for app confirmation */
- if (tcb.ind_count > 0)
+ if (tcb.ind_count > 0) {
gatt_start_ind_ack_timer(tcb, cid);
- else /* no app to indicate, or invalid handle */
+ } else { /* no app to indicate, or invalid handle */
attp_send_cl_confirmation_msg(tcb, cid);
+ }
}
encrypt_status = gatt_get_link_encrypt_status(tcb);
- uint16_t rem_len = len;
- while (rem_len) {
- tGATT_CL_COMPLETE gatt_cl_complete;
+ STREAM_TO_ARRAY(value.value, p, value.len);
+
+ tGATT_CL_COMPLETE gatt_cl_complete;
+ gatt_cl_complete.att_value = value;
+ gatt_cl_complete.cid = cid;
+
+ for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++) {
+ if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb) {
+ conn_id = GATT_CREATE_CONN_ID(tcb.tcb_idx, p_reg->gatt_if);
+ (*p_reg->app_cb.p_cmpl_cb)(conn_id, event, encrypt_status,
+ &gatt_cl_complete);
+ }
+ }
+
+ // If this is single value, then nothing is left to do
+ if (op_code != GATT_HANDLE_MULTI_VALUE_NOTIF) return;
+
+ // Need a signed type to check if the value is below 0
+ // as uint16_t doesn't have negatives so the negatives register as a number
+ // thus anything less than zero won't trigger the conditional and it is not
+ // always 0
+ // when done looping as value.len is arbitrary.
+ int16_t rem_len = (int16_t)len - (4 /* octets */ + value.len);
+
+ // Already streamed the first value and sent it, lets send the rest
+ while (rem_len > 4 /* octets */) {
+ // 2
+ STREAM_TO_UINT16(value.handle, p);
+ // + 2 = 4
+ STREAM_TO_UINT16(value.len, p);
+ // Accounting
+ rem_len -= 4;
+ // Make sure we don't read past the remaining data even if the length says
+ // we can Also need to watch comparing the int16_t with the uint16_t
+ value.len = std::min(rem_len, (int16_t)value.len);
+ STREAM_TO_ARRAY(value.value, p, value.len);
+ // Accounting
+ rem_len -= value.len;
+
gatt_cl_complete.att_value = value;
gatt_cl_complete.cid = cid;
@@ -714,16 +766,6 @@ void gatt_process_notification(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code,
&gatt_cl_complete);
}
}
-
- if (op_code != GATT_HANDLE_MULTI_VALUE_NOTIF) return;
-
- /* 4 stands for 2 octects for handle and 2 octecs for len */
- rem_len -= (4 + value.len);
- if (rem_len) {
- STREAM_TO_UINT16(value.handle, p);
- STREAM_TO_UINT16(value.len, p);
- STREAM_TO_ARRAY(value.value, p, value.len);
- }
}
}