ble_mesh: update protocol error timeout from zephyr

This commit is contained in:
lly 2019-09-02 14:32:54 +08:00
parent 716db01a7f
commit 630e911958

View file

@ -105,7 +105,7 @@ enum {
SEND_CONFIRM, /* Waiting to send Confirm value */
WAIT_NUMBER, /* Waiting for number input from user */
WAIT_STRING, /* Waiting for string input from user */
TIMEOUT_START, /* Provision timeout timer has started */
LINK_INVALID, /* Error occurred during provisioning */
NUM_FLAGS,
};
@ -161,8 +161,7 @@ struct prov_link {
} tx;
#endif
/* Provision timeout timer */
struct k_delayed_work timeout;
struct k_delayed_work prot_timer;
};
struct prov_rx {
@ -176,11 +175,11 @@ struct prov_rx {
#if defined(CONFIG_BLE_MESH_FAST_PROV)
#define RETRANSMIT_TIMEOUT K_MSEC(360)
#define TRANSACTION_TIMEOUT K_SECONDS(3)
#define PROVISION_TIMEOUT K_SECONDS(6)
#define PROTOCOL_TIMEOUT K_SECONDS(6)
#else
#define RETRANSMIT_TIMEOUT K_MSEC(500)
#define TRANSACTION_TIMEOUT K_SECONDS(30)
#define PROVISION_TIMEOUT K_SECONDS(60)
#define PROTOCOL_TIMEOUT K_SECONDS(60)
#endif /* CONFIG_BLE_MESH_FAST_PROV */
#if defined(CONFIG_BLE_MESH_PB_GATT)
@ -197,10 +196,10 @@ static struct prov_link link;
static const struct bt_mesh_prov *prov;
static void close_link(u8_t err, u8_t reason);
static void reset_state(void)
{
k_delayed_work_cancel(&link.prot_timer);
/* Disable Attention Timer if it was set */
if (link.conf_inputs[0]) {
bt_mesh_attention(NULL, 0);
@ -213,7 +212,9 @@ static void reset_state(void)
#endif
#if defined(CONFIG_BLE_MESH_PB_ADV)
/* Clear everything except the retransmit delayed work config */
/* Clear everything except the retransmit and protocol timer
* delayed work objects.
*/
(void)memset(&link, 0, offsetof(struct prov_link, tx.retransmit));
link.rx.prev_id = XACT_NVAL;
@ -224,8 +225,9 @@ static void reset_state(void)
link.rx.buf = &rx_buf;
#endif /* PB_GATT */
#else
(void)memset(&link, 0, offsetof(struct prov_link, timeout));
#else /* !PB_ADV */
/* Clear everything except the protocol timer (k_delayed_work) */
(void)memset(&link, 0, offsetof(struct prov_link, prot_timer));
#endif /* PB_ADV */
}
@ -280,10 +282,6 @@ static void reset_link(void)
{
prov_clear_tx();
if (bt_mesh_atomic_test_and_clear_bit(link.flags, TIMEOUT_START)) {
k_delayed_work_cancel(&link.timeout);
}
if (prov->link_close) {
prov->link_close(BLE_MESH_PROV_ADV);
}
@ -425,7 +423,7 @@ static int prov_send_adv(struct net_buf_simple *msg)
struct net_buf *start, *buf;
u8_t seg_len, seg_id;
u8_t xact_id;
s32_t timeout = PROVISION_TIMEOUT;
s32_t timeout = PROTOCOL_TIMEOUT;
BT_DBG("%s, len %u: %s", __func__, msg->len, bt_hex(msg->data, msg->len));
@ -486,17 +484,12 @@ static int prov_send_adv(struct net_buf_simple *msg)
/* Changed by Espressif, add provisioning timeout timer operations.
* When sending a provisioning PDU successfully, restart the 60s timer.
*/
if (bt_mesh_atomic_test_and_clear_bit(link.flags, TIMEOUT_START)) {
k_delayed_work_cancel(&link.timeout);
}
#if defined(CONFIG_BLE_MESH_FAST_PROV)
if (link.tx_pdu_type >= PROV_COMPLETE) {
timeout = K_SECONDS(60);
}
#endif
if (!bt_mesh_atomic_test_and_set_bit(link.flags, TIMEOUT_START)) {
k_delayed_work_submit(&link.timeout, timeout);
}
k_delayed_work_submit(&link.prot_timer, timeout);
return 0;
}
@ -521,14 +514,7 @@ static int prov_send_gatt(struct net_buf_simple *msg)
return err;
}
if (bt_mesh_atomic_test_and_clear_bit(link.flags, TIMEOUT_START)) {
k_delayed_work_cancel(&link.timeout);
}
if (msg->data[1] != PROV_COMPLETE && msg->data[1] != PROV_FAILED) {
if (!bt_mesh_atomic_test_and_set_bit(link.flags, TIMEOUT_START)) {
k_delayed_work_submit(&link.timeout, PROVISION_TIMEOUT);
}
}
k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
return 0;
}
@ -561,6 +547,8 @@ static void prov_send_fail_msg(u8_t err)
prov_buf_init(&buf, PROV_FAILED);
net_buf_simple_add_u8(&buf, err);
prov_send(&buf);
bt_mesh_atomic_set_bit(link.flags, LINK_INVALID);
}
static void prov_invite(const u8_t *data)
@ -605,7 +593,7 @@ static void prov_invite(const u8_t *data)
if (prov_send(&buf)) {
BT_ERR("%s, Failed to send capabilities", __func__);
close_link(PROV_ERR_RESOURCES, CLOSE_REASON_FAILED);
prov_send_fail_msg(PROV_ERR_RESOURCES);
return;
}
@ -821,7 +809,7 @@ static void send_confirm(void)
if (bt_mesh_prov_conf_salt(link.conf_inputs, link.conf_salt)) {
BT_ERR("%s, Unable to generate confirmation salt", __func__);
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
return;
}
@ -829,7 +817,7 @@ static void send_confirm(void)
if (bt_mesh_prov_conf_key(link.dhkey, link.conf_salt, link.conf_key)) {
BT_ERR("%s, Unable to generate confirmation key", __func__);
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
return;
}
@ -837,7 +825,7 @@ static void send_confirm(void)
if (bt_mesh_rand(link.rand, 16)) {
BT_ERR("%s, Unable to generate random number", __func__);
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
return;
}
@ -848,13 +836,13 @@ static void send_confirm(void)
if (bt_mesh_prov_conf(link.conf_key, link.rand, link.auth,
net_buf_simple_add(&cfm, 16))) {
BT_ERR("%s, Unable to generate confirmation value", __func__);
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
return;
}
if (prov_send(&cfm)) {
BT_ERR("%s, Unable to send Provisioning Confirm", __func__);
close_link(PROV_ERR_RESOURCES, CLOSE_REASON_FAILED);
prov_send_fail_msg(PROV_ERR_RESOURCES);
return;
}
@ -921,7 +909,7 @@ static void prov_dh_key_cb(const u8_t key[32], const u8_t idx)
if (!key) {
BT_ERR("%s, DHKey generation failed", __func__);
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
return;
}
@ -949,7 +937,7 @@ static void send_pub_key(void)
key = bt_mesh_pub_key_get();
if (!key) {
BT_ERR("%s, No public key available", __func__);
close_link(PROV_ERR_RESOURCES, CLOSE_REASON_FAILED);
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
return;
}
@ -974,7 +962,7 @@ static void send_pub_key(void)
if (bt_mesh_dh_key_gen(buf.data, prov_dh_key_cb, 0)) {
BT_ERR("%s, Unable to generate DHKey", __func__);
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
return;
}
@ -994,7 +982,7 @@ static int bt_mesh_calc_dh_key(void)
if (bt_mesh_dh_key_gen(buf.data, prov_dh_key_cb, 0)) {
BT_ERR("%s, Unable to generate DHKey", __func__);
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
return -EIO;
}
@ -1096,7 +1084,7 @@ static void prov_random(const u8_t *data)
if (bt_mesh_prov_conf(link.conf_key, data, link.auth, conf_verify)) {
BT_ERR("%s, Unable to calculate confirmation verification", __func__);
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
return;
}
@ -1104,7 +1092,7 @@ static void prov_random(const u8_t *data)
BT_ERR("%s, Invalid confirmation value", __func__);
BT_DBG("Received: %s", bt_hex(link.conf, 16));
BT_DBG("Calculated: %s", bt_hex(conf_verify, 16));
close_link(PROV_ERR_CFM_FAILED, CLOSE_REASON_FAILED);
prov_send_fail_msg(PROV_ERR_CFM_FAILED);
return;
}
@ -1113,14 +1101,14 @@ static void prov_random(const u8_t *data)
if (prov_send(&rnd)) {
BT_ERR("%s, Failed to send Provisioning Random", __func__);
close_link(PROV_ERR_RESOURCES, CLOSE_REASON_FAILED);
prov_send_fail_msg(PROV_ERR_RESOURCES);
return;
}
if (bt_mesh_prov_salt(link.conf_salt, data, link.rand,
link.prov_salt)) {
BT_ERR("%s, Failed to generate provisioning salt", __func__);
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
return;
}
@ -1157,7 +1145,7 @@ static void prov_data(const u8_t *data)
err = bt_mesh_session_key(link.dhkey, link.prov_salt, session_key);
if (err) {
BT_ERR("%s, Unable to generate session key", __func__);
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
return;
}
@ -1166,7 +1154,7 @@ static void prov_data(const u8_t *data)
err = bt_mesh_prov_nonce(link.dhkey, link.prov_salt, nonce);
if (err) {
BT_ERR("%s, Unable to generate session nonce", __func__);
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
return;
}
@ -1175,14 +1163,14 @@ static void prov_data(const u8_t *data)
err = bt_mesh_prov_decrypt(session_key, nonce, data, pdu);
if (err) {
BT_ERR("%s, Unable to decrypt provisioning data", __func__);
close_link(PROV_ERR_DECRYPT, CLOSE_REASON_FAILED);
prov_send_fail_msg(PROV_ERR_DECRYPT);
return;
}
err = bt_mesh_dev_key(link.dhkey, link.prov_salt, dev_key);
if (err) {
BT_ERR("%s, Unable to generate device key", __func__);
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_FAILED);
prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
return;
}
@ -1249,35 +1237,6 @@ static const struct {
{ prov_failed, 1 },
};
static void close_link(u8_t err, u8_t reason)
{
#if defined(CONFIG_BLE_MESH_PB_GATT)
if (link.conn) {
bt_mesh_pb_gatt_close(link.conn);
return;
}
#endif
#if defined(CONFIG_BLE_MESH_PB_ADV)
if (err) {
prov_send_fail_msg(err);
}
link.rx.seg = 0U;
bearer_ctl_send(LINK_CLOSE, &reason, sizeof(reason));
#endif
reset_state();
}
/* Changed by Espressif, add provisioning timeout timer callback */
static void prov_timeout(struct k_work *work)
{
BT_DBG("%s", __func__);
close_link(PROV_ERR_UNEXP_ERR, CLOSE_REASON_TIMEOUT);
}
#if defined(CONFIG_BLE_MESH_PB_ADV)
static void prov_retransmit(struct k_work *work)
{
@ -1425,6 +1384,12 @@ static void prov_msg_recv(void)
link.rx.prev_id = link.rx.id;
link.rx.id = 0U;
if (bt_mesh_atomic_test_bit(link.flags, LINK_INVALID)) {
BT_WARN("Unexpected msg 0x%02x on invalidated link", type);
prov_send_fail_msg(PROV_ERR_UNEXP_PDU);
return;
}
if (type != PROV_FAILED && type != link.expect) {
BT_WARN("Unexpected msg 0x%02x != 0x%02x", type, link.expect);
prov_send_fail_msg(PROV_ERR_UNEXP_PDU);
@ -1433,26 +1398,21 @@ static void prov_msg_recv(void)
if (type >= ARRAY_SIZE(prov_handlers)) {
BT_ERR("%s, Unknown provisioning PDU type 0x%02x", __func__, type);
close_link(PROV_ERR_NVAL_PDU, CLOSE_REASON_FAILED);
prov_send_fail_msg(PROV_ERR_NVAL_PDU);
return;
}
if (1 + prov_handlers[type].len != link.rx.buf->len) {
BT_ERR("%s, Invalid length %u for type 0x%02x",
__func__, link.rx.buf->len, type);
close_link(PROV_ERR_NVAL_FMT, CLOSE_REASON_FAILED);
prov_send_fail_msg(PROV_ERR_NVAL_FMT);
return;
}
/* Changed by Espressif, add provisioning timeout timer operations.
* When received a provisioning PDU, restart the 60s timer.
*/
if (bt_mesh_atomic_test_and_clear_bit(link.flags, TIMEOUT_START)) {
k_delayed_work_cancel(&link.timeout);
}
if (!bt_mesh_atomic_test_and_set_bit(link.flags, TIMEOUT_START)) {
k_delayed_work_submit(&link.timeout, PROVISION_TIMEOUT);
}
k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
prov_handlers[type].func(&link.rx.buf->data[1]);
}
@ -1485,7 +1445,7 @@ static void gen_prov_cont(struct prov_rx *rx, struct net_buf_simple *buf)
if (seg > link.rx.last_seg) {
BT_ERR("%s, Invalid segment index %u", __func__, seg);
close_link(PROV_ERR_NVAL_FMT, CLOSE_REASON_FAILED);
prov_send_fail_msg(PROV_ERR_NVAL_FMT);
return;
} else if (seg == link.rx.last_seg) {
u8_t expect_len;
@ -1495,7 +1455,7 @@ static void gen_prov_cont(struct prov_rx *rx, struct net_buf_simple *buf)
if (expect_len != buf->len) {
BT_ERR("%s, Incorrect last seg len: %u != %u",
__func__, expect_len, buf->len);
close_link(PROV_ERR_NVAL_FMT, CLOSE_REASON_FAILED);
prov_send_fail_msg(PROV_ERR_NVAL_FMT);
return;
}
}
@ -1548,20 +1508,20 @@ static void gen_prov_start(struct prov_rx *rx, struct net_buf_simple *buf)
if (link.rx.buf->len < 1) {
BT_ERR("%s, Ignoring zero-length provisioning PDU", __func__);
close_link(PROV_ERR_NVAL_FMT, CLOSE_REASON_FAILED);
prov_send_fail_msg(PROV_ERR_NVAL_FMT);
return;
}
if (link.rx.buf->len > link.rx.buf->size) {
BT_ERR("%s, Too large provisioning PDU (%u bytes)",
__func__, link.rx.buf->len);
// close_link(PROV_ERR_NVAL_FMT, CLOSE_REASON_FAILED);
// prov_send_fail_msg(PROV_ERR_NVAL_FMT);
return;
}
if (START_LAST_SEG(rx->gpc) > 0 && link.rx.buf->len <= 20U) {
BT_ERR("%s, Too small total length for multi-segment PDU", __func__);
close_link(PROV_ERR_NVAL_FMT, CLOSE_REASON_FAILED);
prov_send_fail_msg(PROV_ERR_NVAL_FMT);
return;
}
@ -1668,12 +1628,7 @@ int bt_mesh_pb_gatt_recv(struct bt_mesh_conn *conn, struct net_buf_simple *buf)
/* Changed by Espressif, add provisioning timeout timer operations.
* When received a provisioning PDU, restart the 60s timer.
*/
if (bt_mesh_atomic_test_and_clear_bit(link.flags, TIMEOUT_START)) {
k_delayed_work_cancel(&link.timeout);
}
if (!bt_mesh_atomic_test_and_set_bit(link.flags, TIMEOUT_START)) {
k_delayed_work_submit(&link.timeout, PROVISION_TIMEOUT);
}
k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
prov_handlers[type].func(buf->data);
@ -1727,6 +1682,27 @@ bool bt_prov_active(void)
return bt_mesh_atomic_test_bit(link.flags, LINK_ACTIVE);
}
static void protocol_timeout(struct k_work *work)
{
BT_DBG("Protocol timeout");
#if defined(CONFIG_BLE_MESH_PB_GATT)
if (link.conn) {
bt_mesh_pb_gatt_close(link.conn);
return;
}
#endif
#if defined(CONFIG_BLE_MESH_PB_ADV)
u8_t reason = CLOSE_REASON_TIMEOUT;
link.rx.seg = 0U;
bearer_ctl_send(LINK_CLOSE, &reason, sizeof(reason));
reset_state();
#endif
}
int bt_mesh_prov_init(const struct bt_mesh_prov *prov_info)
{
const u8_t *key = NULL;
@ -1743,15 +1719,14 @@ int bt_mesh_prov_init(const struct bt_mesh_prov *prov_info)
return -EIO;
}
k_delayed_work_init(&link.prot_timer, protocol_timeout);
prov = prov_info;
#if defined(CONFIG_BLE_MESH_PB_ADV)
k_delayed_work_init(&link.tx.retransmit, prov_retransmit);
#endif
/* Changed by Espressif, add provisioning timeout timer init */
k_delayed_work_init(&link.timeout, prov_timeout);
reset_state();
return 0;