@@ -59,12 +59,6 @@ struct esp32_bt_service_attr_info {
59
59
uint16_t handle ;
60
60
};
61
61
62
- struct esp32_bt_gatts_pending_write {
63
- uint16_t handle ;
64
- struct mbuf value ;
65
- SLIST_ENTRY (esp32_bt_gatts_pending_write ) next ;
66
- };
67
-
68
62
struct esp32_bt_gatts_pending_ind {
69
63
uint16_t handle ;
70
64
bool is_ind ;
@@ -80,18 +74,25 @@ struct esp32_bt_gatts_session_entry {
80
74
struct mgos_bt_gatts_conn gsc ;
81
75
struct esp32_bt_gatts_service_entry * se ;
82
76
struct mbuf resp_data ;
83
- SLIST_HEAD (pending_writes , esp32_bt_gatts_pending_write ) pending_writes ;
84
77
SLIST_ENTRY (esp32_bt_gatts_session_entry ) next ;
85
78
};
86
79
80
+ // This notification mode change is awaiting completion of the security
81
+ // procedure.
82
+ struct esp32_bt_gatts_pending_nm_entry {
83
+ struct mgos_bt_gatts_notify_mode_arg nmarg ;
84
+ SLIST_ENTRY (esp32_bt_gatts_pending_nm_entry ) next ;
85
+ };
86
+
87
87
struct esp32_bt_gatts_connection_entry {
88
88
struct mgos_bt_gatt_conn gc ;
89
89
enum mgos_bt_gatt_sec_level sec_level ;
90
- bool need_auth ;
91
- bool ind_in_flight ;
90
+ bool sec_in_flight ;
92
91
/* Notifications/indications are finicky, so we keep at most one in flight. */
93
92
int ind_queue_len ;
93
+ bool ind_in_flight ;
94
94
STAILQ_HEAD (pending_inds , esp32_bt_gatts_pending_ind ) pending_inds ;
95
+ SLIST_HEAD (pending_nm , esp32_bt_gatts_pending_nm_entry ) pending_nm ;
95
96
SLIST_HEAD (sessions , esp32_bt_gatts_session_entry ) sessions ; // 1 per service
96
97
SLIST_ENTRY (esp32_bt_gatts_connection_entry ) next ;
97
98
};
@@ -237,11 +238,10 @@ static enum mgos_bt_gatt_status esp32_bt_gatts_call_handler(
237
238
}
238
239
239
240
void esp32_bt_gatts_close_session (struct esp32_bt_gatts_session_entry * sse ) {
240
- struct esp32_bt_gatts_pending_write * pw , * pwt ;
241
- SLIST_FOREACH_SAFE (pw , & sse -> pending_writes , next , pwt ) {
242
- mbuf_free (& pw -> value );
243
- memset (pw , 0 , sizeof (* pw ));
244
- free (pw );
241
+ struct esp32_bt_gatts_pending_nm_entry * pnm , * pnmt ;
242
+ SLIST_FOREACH_SAFE (pnm , & sse -> ce -> pending_nm , next , pnmt ) {
243
+ memset (pnm , 0 , sizeof (* pnm ));
244
+ free (pnm );
245
245
}
246
246
SLIST_REMOVE (& sse -> ce -> sessions , sse , esp32_bt_gatts_session_entry , next );
247
247
esp32_bt_gatts_call_handler (sse , NULL , MGOS_BT_GATTS_EV_DISCONNECT , NULL );
@@ -262,7 +262,6 @@ static void esp32_bt_gatts_create_sessions(
262
262
sse -> gsc .gc = ce -> gc ;
263
263
sse -> gsc .svc_uuid = se -> uuid ;
264
264
mbuf_init (& sse -> resp_data , 0 );
265
- SLIST_INIT (& sse -> pending_writes );
266
265
enum mgos_bt_gatt_status st =
267
266
esp32_bt_gatts_call_handler (sse , NULL , MGOS_BT_GATTS_EV_CONNECT , NULL );
268
267
if (st != MGOS_BT_GATT_STATUS_OK ) {
@@ -339,12 +338,10 @@ int esp32_bt_gatts_event(const struct ble_gap_event *ev, void *arg) {
339
338
ce -> gc .conn_id = conn_id ;
340
339
ce -> gc .mtu = ble_att_mtu (conn_id );
341
340
esp32_bt_addr_to_mgos (& cd .peer_ota_addr , & ce -> gc .addr );
341
+ SLIST_INIT (& ce -> pending_nm );
342
342
STAILQ_INIT (& ce -> pending_inds );
343
343
SLIST_INSERT_HEAD (& s_conns , ce , next );
344
344
ble_gattc_exchange_mtu (conn_id , NULL , NULL );
345
- if (mgos_sys_config_get_bt_gatts_min_sec_level () > 0 ) {
346
- // ble_gap_security_initiate(conn_id);
347
- }
348
345
break ;
349
346
}
350
347
case BLE_GAP_EVENT_DISCONNECT : {
@@ -370,14 +367,38 @@ int esp32_bt_gatts_event(const struct ble_gap_event *ev, void *arg) {
370
367
break ;
371
368
}
372
369
case BLE_GAP_EVENT_ENC_CHANGE : {
373
- uint16_t conn_id = ev -> enc_change .conn_handle ;
370
+ uint16_t ch = ev -> enc_change .conn_handle ;
374
371
struct ble_gap_conn_desc cd = {0 };
375
- ble_gap_conn_find (conn_id , & cd );
372
+ ble_gap_conn_find (ch , & cd );
376
373
struct ble_gap_sec_state * ss = & cd .sec_state ;
374
+ struct esp32_bt_gatts_connection_entry * ce = find_connection (ch );
375
+ if (ce == NULL ) break ;
376
+ ce -> sec_in_flight = false;
377
377
LOG (LL_DEBUG , ("ENC_CHANGE %s ch %d st %d e %d a %d b %d ks %d" ,
378
- esp32_bt_addr_to_str (& cd .peer_ota_addr , buf1 ), conn_id ,
378
+ esp32_bt_addr_to_str (& cd .peer_ota_addr , buf1 ), ch ,
379
379
ev -> enc_change .status , ss -> encrypted , ss -> authenticated ,
380
380
ss -> bonded , ss -> key_size ));
381
+ if (ev -> enc_change .status != 0 ) {
382
+ ble_gap_terminate (ch , BLE_ERR_REM_USER_CONN_TERM );
383
+ break ;
384
+ }
385
+ while (!SLIST_EMPTY (& ce -> pending_nm )) {
386
+ struct esp32_bt_gatts_pending_nm_entry * pnm =
387
+ SLIST_FIRST (& ce -> pending_nm );
388
+ SLIST_REMOVE_HEAD (& ce -> pending_nm , next );
389
+ struct mgos_bt_gatts_notify_mode_arg * narg = & pnm -> nmarg ;
390
+ uint16_t ah = narg -> handle ;
391
+ struct esp32_bt_service_attr_info * ai = NULL ;
392
+ struct esp32_bt_gatts_session_entry * sse = find_session (ch , ah , & ai );
393
+ LOG (LL_DEBUG ,
394
+ ("NOTIFY_MODE ch %d ah %d %s/%s %d" , ch , ah ,
395
+ mgos_bt_uuid_to_str (& narg -> svc_uuid , buf1 ),
396
+ mgos_bt_uuid_to_str (& narg -> char_uuid , buf2 ), narg -> mode ));
397
+ esp32_bt_gatts_call_handler (sse , ai , MGOS_BT_GATTS_EV_NOTIFY_MODE ,
398
+ narg );
399
+ memset (pnm , 0 , sizeof (* pnm ));
400
+ free (pnm );
401
+ }
381
402
break ;
382
403
}
383
404
case BLE_GAP_EVENT_MTU : {
@@ -410,7 +431,25 @@ int esp32_bt_gatts_event(const struct ble_gap_event *ev, void *arg) {
410
431
} else if (ev -> subscribe .cur_indicate ) {
411
432
narg .mode = MGOS_BT_GATT_NOTIFY_MODE_INDICATE ;
412
433
}
413
- LOG (LL_DEBUG , ("NOTIFY_MODE c %d h %d %s/%s %d" , ch , ah ,
434
+ // Work around https://github.com/apache/mynewt-nimble/issues/1092
435
+ if (sse -> se -> sec_level > 0 ||
436
+ mgos_sys_config_get_bt_gatts_min_sec_level () > 0 ) {
437
+ struct ble_gap_conn_desc cd = {0 };
438
+ ble_gap_conn_find (ch , & cd );
439
+ struct ble_gap_sec_state * ss = & cd .sec_state ;
440
+ if (!ss -> encrypted ) {
441
+ struct esp32_bt_gatts_pending_nm_entry * pnm = calloc (1 , sizeof (* pnm ));
442
+ pnm -> nmarg = narg ;
443
+ SLIST_INSERT_HEAD (& sse -> ce -> pending_nm , pnm , next );
444
+ if (!sse -> ce -> sec_in_flight ) {
445
+ sse -> ce -> sec_in_flight = true;
446
+ ble_gap_security_initiate (ch );
447
+ }
448
+ ret = BLE_ATT_ERR_INSUFFICIENT_AUTHOR ;
449
+ break ;
450
+ }
451
+ }
452
+ LOG (LL_DEBUG , ("NOTIFY_MODE ch %d ah %d %s/%s %d" , ch , ah ,
414
453
mgos_bt_uuid_to_str (& narg .svc_uuid , buf1 ),
415
454
mgos_bt_uuid_to_str (& narg .char_uuid , buf2 ), narg .mode ));
416
455
esp32_bt_gatts_call_handler (sse , ai , MGOS_BT_GATTS_EV_NOTIFY_MODE , & narg );
0 commit comments