in nimble/host/mesh/src/net.c [502:570]
int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
const struct bt_mesh_send_cb *cb, void *cb_data)
{
const struct bt_mesh_net_cred *cred;
int err;
BT_DBG("src 0x%04x dst 0x%04x len %u headroom %zu tailroom %zu",
tx->src, tx->ctx->addr, buf->om_len, net_buf_headroom(buf),
net_buf_tailroom(buf));
BT_DBG("Payload len %u: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
BT_DBG("Seq 0x%06x", bt_mesh.seq);
cred = net_tx_cred_get(tx);
err = net_header_encode(tx, cred->nid, buf);
if (err) {
goto done;
}
BT_DBG("encoded %u bytes: %s", buf->om_len,
bt_hex(buf->om_data, buf->om_len));
/* Deliver to local network interface if necessary */
if (bt_mesh_fixed_group_match(tx->ctx->addr) ||
bt_mesh_has_addr(tx->ctx->addr)) {
err = loopback(tx, buf->om_data, buf->om_len);
/* Local unicast messages should not go out to network */
if (BT_MESH_ADDR_IS_UNICAST(tx->ctx->addr) ||
tx->ctx->send_ttl == 1U) {
if (!err) {
send_cb_finalize(cb, cb_data);
}
goto done;
}
}
/* Mesh spec 3.4.5.2: "The output filter of the interface connected to
* advertising or GATT bearers shall drop all messages with TTL value
* set to 1." If a TTL=1 packet wasn't for a local interface, it is
* invalid.
*/
if (tx->ctx->send_ttl == 1U) {
err = -EINVAL;
goto done;
}
err = net_encrypt(buf, cred, BT_MESH_NET_IVI_TX, false);
if (err) {
goto done;
}
BT_MESH_ADV(buf)->cb = cb;
BT_MESH_ADV(buf)->cb_data = cb_data;
/* Deliver to GATT Proxy Clients if necessary. */
if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
bt_mesh_proxy_relay(buf, tx->ctx->addr) &&
BT_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) {
err = 0;
goto done;
}
bt_mesh_adv_send(buf, cb, cb_data);
done:
net_buf_unref(buf);
return err;
}