in nimble/host/mesh/src/transport.c [890:953]
static int ctl_recv(struct bt_mesh_net_rx *rx, uint8_t hdr,
struct os_mbuf *buf, uint64_t *seq_auth)
{
uint8_t ctl_op = TRANS_CTL_OP(&hdr);
BT_DBG("OpCode 0x%02x len %u", ctl_op, buf->om_len);
switch (ctl_op) {
case TRANS_CTL_OP_ACK:
return trans_ack(rx, hdr, buf, seq_auth);
case TRANS_CTL_OP_HEARTBEAT:
return bt_mesh_hb_recv(rx, buf);
}
/* Only acks and heartbeats may need processing without local_match */
if (!rx->local_match) {
return 0;
}
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && !bt_mesh_lpn_established()) {
switch (ctl_op) {
case TRANS_CTL_OP_FRIEND_POLL:
return bt_mesh_friend_poll(rx, buf);
case TRANS_CTL_OP_FRIEND_REQ:
return bt_mesh_friend_req(rx, buf);
case TRANS_CTL_OP_FRIEND_CLEAR:
return bt_mesh_friend_clear(rx, buf);
case TRANS_CTL_OP_FRIEND_CLEAR_CFM:
return bt_mesh_friend_clear_cfm(rx, buf);
case TRANS_CTL_OP_FRIEND_SUB_ADD:
return bt_mesh_friend_sub_add(rx, buf);
case TRANS_CTL_OP_FRIEND_SUB_REM:
return bt_mesh_friend_sub_rem(rx, buf);
}
}
#if (MYNEWT_VAL(BLE_MESH_LOW_POWER))
if (ctl_op == TRANS_CTL_OP_FRIEND_OFFER) {
return bt_mesh_lpn_friend_offer(rx, buf);
}
if (rx->ctx.addr == bt_mesh.lpn.frnd) {
if (ctl_op == TRANS_CTL_OP_FRIEND_CLEAR_CFM) {
return bt_mesh_lpn_friend_clear_cfm(rx, buf);
}
if (!rx->friend_cred) {
BT_WARN("Message from friend with wrong credentials");
return -EINVAL;
}
switch (ctl_op) {
case TRANS_CTL_OP_FRIEND_UPDATE:
return bt_mesh_lpn_friend_update(rx, buf);
case TRANS_CTL_OP_FRIEND_SUB_CFM:
return bt_mesh_lpn_friend_sub_cfm(rx, buf);
}
}
#endif /* MYNEWT_VAL(BLE_MESH_LOW_POWER) */
BT_WARN("Unhandled TransOpCode 0x%02x", ctl_op);
return -ENOENT;
}