Prechádzať zdrojové kódy

Merge branch 'bugfix/ble_mesh_check_subnet_before_update_beacon_sent_v3.3' into 'release/v3.3'

ble_mesh: Check if subnet exists before updating beacon_sent (v3.3)

See merge request espressif/esp-idf!9398
Island 5 rokov pred
rodič
commit
021e23ebf7
1 zmenil súbory, kde vykonal 36 pridanie a 11 odobranie
  1. 36 11
      components/bt/esp_ble_mesh/mesh_core/beacon.c

+ 36 - 11
components/bt/esp_ble_mesh/mesh_core/beacon.c

@@ -40,6 +40,9 @@
 /* 1 transmission, 20ms interval */
 #define PROV_XMIT                  BLE_MESH_TRANSMIT(0, 20)
 
+#define SNB_NET_IDX_SET(_val)      ((void *)((u32_t)(_val)))
+#define SNB_NET_IDX_GET(_ptr)      ((u32_t)(_ptr))
+
 static struct k_delayed_work beacon_timer;
 
 static struct bt_mesh_subnet *cache_check(u8_t data[21])
@@ -71,11 +74,30 @@ static void cache_add(u8_t data[21], struct bt_mesh_subnet *sub)
 
 static void beacon_complete(int err, void *user_data)
 {
-    struct bt_mesh_subnet *sub = user_data;
+    struct bt_mesh_subnet *sub = NULL;
+    u16_t net_idx = BLE_MESH_KEY_UNUSED;
 
     BT_DBG("err %d", err);
 
-    sub->beacon_sent = k_uptime_get_32();
+    net_idx = (u16_t)SNB_NET_IDX_GET(user_data);
+
+    /* For node, directly updating the "beacon_sent" timestamp is fine,
+     * since the subnet is pre-allocated.
+     * For Provisioner, before updating the "beacon_sent" timestamp, we
+     * need to make sure that the subnet still exists, because there is
+     * a chance that the subnet is removed just before the completion of
+     * sending the Secure Network Beacon.
+     */
+    if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) {
+        sub = bt_mesh_subnet_get(net_idx);
+    } else if (IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER) &&
+        bt_mesh_is_provisioner_en()) {
+        sub = bt_mesh_provisioner_subnet_get(net_idx);
+    }
+
+    if (sub) {
+        sub->beacon_sent = k_uptime_get_32();
+    }
 }
 
 void bt_mesh_beacon_create(struct bt_mesh_subnet *sub,
@@ -161,7 +183,17 @@ static int secure_beacon_send(void)
 
         bt_mesh_beacon_create(sub, &buf->b);
 
-        bt_mesh_adv_send(buf, &send_cb, sub);
+        /* Care should be taken here. Previously the user_data is the
+         * pointer of a subnet. When the device is a Provisioner, its
+         * subnet is created dynamically. If the corresponding subnet
+         * is removed right after the Secure Network Beacon is sent,
+         * update its "beacon_sent" timestamp in beacon_complete() will
+         * cause exception.
+         * Here we use the "net_idx" of the subnet instead. And in the
+         * beacon_complete(), we will try to get the subnet before
+         * updating its "beacon_sent" timestamp.
+         */
+        bt_mesh_adv_send(buf, &send_cb, SNB_NET_IDX_SET(sub->net_idx));
         net_buf_unref(buf);
     }
 
@@ -264,16 +296,9 @@ static void update_beacon_observation(void)
 
 static bool ready_to_send(void)
 {
-    if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) {
+    if (bt_mesh_is_provisioned() || bt_mesh_is_provisioner_en()) {
         return true;
     }
-
-    if (IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER) && bt_mesh_is_provisioner_en()) {
-        if (bt_mesh_provisioner_get_node_count()) {
-            return true;
-        }
-    }
-
     return false;
 }