in nimble/host/mesh/src/transport.c [1551:1628]
int bt_mesh_trans_recv(struct os_mbuf *buf, struct bt_mesh_net_rx *rx)
{
uint64_t seq_auth = TRANS_SEQ_AUTH_NVAL;
enum bt_mesh_friend_pdu_type pdu_type = BT_MESH_FRIEND_PDU_SINGLE;
struct net_buf_simple_state state;
uint8_t seg_count = 0;
int err;
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
rx->friend_match = bt_mesh_friend_match(rx->sub->net_idx,
rx->ctx.recv_dst);
} else {
rx->friend_match = false;
}
BT_DBG("src 0x%04x dst 0x%04x seq 0x%08x friend_match %u",
rx->ctx.addr, rx->ctx.recv_dst, (unsigned) rx->seq,
rx->friend_match);
/* Remove network headers */
net_buf_simple_pull(buf, BT_MESH_NET_HDR_LEN);
BT_DBG("Payload %s", bt_hex(buf->om_data, buf->om_len));
if (IS_ENABLED(CONFIG_BT_TESTING)) {
bt_test_mesh_net_recv(rx->ctx.recv_ttl, rx->ctl, rx->ctx.addr,
rx->ctx.recv_dst, buf->om_data, buf->om_len);
}
/* If LPN mode is enabled messages are only accepted when we've
* requested the Friend to send them. The messages must also
* be encrypted using the Friend Credentials.
*/
if ((MYNEWT_VAL(BLE_MESH_LOW_POWER)) &&
bt_mesh_lpn_established() && rx->net_if == BT_MESH_NET_IF_ADV &&
(!bt_mesh_lpn_waiting_update() || !rx->friend_cred)) {
BT_WARN("Ignoring unexpected message in Low Power mode");
return -EAGAIN;
}
/* Save the app-level state so the buffer can later be placed in
* the Friend Queue.
*/
net_buf_simple_save(buf, &state);
if (SEG(buf->om_data)) {
/* Segmented messages must match a local element or an
* LPN of this Friend.
*/
if (!rx->local_match && !rx->friend_match) {
return 0;
}
err = trans_seg(buf, rx, &pdu_type, &seq_auth, &seg_count);
} else {
seg_count = 1;
err = trans_unseg(buf, rx, &seq_auth);
}
/* Notify LPN state machine so a Friend Poll will be sent. */
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
bt_mesh_lpn_msg_received(rx);
}
net_buf_simple_restore(buf, &state);
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && rx->friend_match && !err) {
if (seq_auth == TRANS_SEQ_AUTH_NVAL) {
bt_mesh_friend_enqueue_rx(rx, pdu_type, NULL,
seg_count, buf);
} else {
bt_mesh_friend_enqueue_rx(rx, pdu_type, &seq_auth,
seg_count, buf);
}
}
return err;
}