1 /* Bluetooth Mesh */
2
3 /*
4 * Copyright (c) 2017 Intel Corporation
5 * Copyright (c) 2021 Lingao Meng
6 *
7 * SPDX-License-Identifier: Apache-2.0
8 */
9
10 #include <zephyr/kernel.h>
11 #include <zephyr/sys/byteorder.h>
12
13 #include <zephyr/net/buf.h>
14 #include <zephyr/bluetooth/bluetooth.h>
15 #include <zephyr/bluetooth/conn.h>
16 #include <zephyr/bluetooth/gatt.h>
17 #include <zephyr/bluetooth/mesh.h>
18
19 #include <zephyr/bluetooth/hci.h>
20
21 #include "common/bt_str.h"
22
23 #include "mesh.h"
24 #include "net.h"
25 #include "rpl.h"
26 #include "transport.h"
27 #include "prov.h"
28 #include "beacon.h"
29 #include "foundation.h"
30 #include "access.h"
31 #include "proxy.h"
32 #include "proxy_msg.h"
33
34 #define LOG_LEVEL CONFIG_BT_MESH_PROXY_LOG_LEVEL
35 #include <zephyr/logging/log.h>
36 LOG_MODULE_REGISTER(bt_mesh_proxy);
37
38 #define PDU_SAR(data) (data[0] >> 6)
39
40 /* MshPRTv1.1: 6.3.2.2:
41 * "The timeout for the SAR transfer is 20 seconds. When the timeout
42 * expires, the Proxy Server shall disconnect."
43 */
44 #define PROXY_SAR_TIMEOUT K_SECONDS(20)
45
46 #define SAR_COMPLETE 0x00
47 #define SAR_FIRST 0x01
48 #define SAR_CONT 0x02
49 #define SAR_LAST 0x03
50
51 #define PDU_HDR(sar, type) (sar << 6 | (type & BIT_MASK(6)))
52
53 static uint8_t __noinit bufs[CONFIG_BT_MAX_CONN * CONFIG_BT_MESH_PROXY_MSG_LEN];
54
55 static struct bt_mesh_proxy_role roles[CONFIG_BT_MAX_CONN];
56
57 static int conn_count;
58
proxy_sar_timeout(struct k_work * work)59 static void proxy_sar_timeout(struct k_work *work)
60 {
61 struct bt_mesh_proxy_role *role;
62 struct k_work_delayable *dwork = k_work_delayable_from_work(work);
63
64 LOG_WRN("Proxy SAR timeout");
65
66 role = CONTAINER_OF(dwork, struct bt_mesh_proxy_role, sar_timer);
67 if (role->conn) {
68 bt_conn_disconnect(role->conn,
69 BT_HCI_ERR_REMOTE_USER_TERM_CONN);
70 }
71 }
72
bt_mesh_proxy_msg_recv(struct bt_conn * conn,const void * buf,uint16_t len)73 ssize_t bt_mesh_proxy_msg_recv(struct bt_conn *conn,
74 const void *buf, uint16_t len)
75 {
76 const uint8_t *data = buf;
77 struct bt_mesh_proxy_role *role = &roles[bt_conn_index(conn)];
78
79 if (net_buf_simple_tailroom(&role->buf) < len - 1) {
80 LOG_WRN("Proxy role buffer overflow");
81 return -EINVAL;
82 }
83
84 switch (PDU_SAR(data)) {
85 case SAR_COMPLETE:
86 if (role->buf.len) {
87 LOG_WRN("Complete PDU while a pending incomplete one");
88 return -EINVAL;
89 }
90
91 role->msg_type = PDU_TYPE(data);
92 net_buf_simple_add_mem(&role->buf, data + 1, len - 1);
93 role->cb.recv(role);
94 net_buf_simple_reset(&role->buf);
95 break;
96
97 case SAR_FIRST:
98 if (role->buf.len) {
99 LOG_WRN("First PDU while a pending incomplete one");
100 return -EINVAL;
101 }
102
103 k_work_reschedule(&role->sar_timer, PROXY_SAR_TIMEOUT);
104 role->msg_type = PDU_TYPE(data);
105 net_buf_simple_add_mem(&role->buf, data + 1, len - 1);
106 break;
107
108 case SAR_CONT:
109 if (!role->buf.len) {
110 LOG_WRN("Continuation with no prior data");
111 return -EINVAL;
112 }
113
114 if (role->msg_type != PDU_TYPE(data)) {
115 LOG_WRN("Unexpected message type in continuation");
116 return -EINVAL;
117 }
118
119 k_work_reschedule(&role->sar_timer, PROXY_SAR_TIMEOUT);
120 net_buf_simple_add_mem(&role->buf, data + 1, len - 1);
121 break;
122
123 case SAR_LAST:
124 if (!role->buf.len) {
125 LOG_WRN("Last SAR PDU with no prior data");
126 return -EINVAL;
127 }
128
129 if (role->msg_type != PDU_TYPE(data)) {
130 LOG_WRN("Unexpected message type in last SAR PDU");
131 return -EINVAL;
132 }
133
134 /* If this fails, the work handler exits early, as there's no
135 * active SAR buffer.
136 */
137 (void)k_work_cancel_delayable(&role->sar_timer);
138 net_buf_simple_add_mem(&role->buf, data + 1, len - 1);
139 role->cb.recv(role);
140 net_buf_simple_reset(&role->buf);
141 break;
142 }
143
144 return len;
145 }
146
bt_mesh_proxy_msg_send(struct bt_conn * conn,uint8_t type,struct net_buf_simple * msg,bt_gatt_complete_func_t end,void * user_data)147 int bt_mesh_proxy_msg_send(struct bt_conn *conn, uint8_t type,
148 struct net_buf_simple *msg,
149 bt_gatt_complete_func_t end, void *user_data)
150 {
151 int err;
152 uint16_t mtu;
153 struct bt_mesh_proxy_role *role = &roles[bt_conn_index(conn)];
154
155 LOG_DBG("conn %p type 0x%02x len %u: %s", (void *)conn, type, msg->len,
156 bt_hex(msg->data, msg->len));
157
158 /* ATT_MTU - OpCode (1 byte) - Handle (2 bytes) */
159 mtu = bt_gatt_get_mtu(conn) - 3;
160 if (mtu > msg->len) {
161 net_buf_simple_push_u8(msg, PDU_HDR(SAR_COMPLETE, type));
162 return role->cb.send(conn, msg->data, msg->len, end, user_data);
163 }
164
165 net_buf_simple_push_u8(msg, PDU_HDR(SAR_FIRST, type));
166 err = role->cb.send(conn, msg->data, mtu, NULL, NULL);
167 if (err) {
168 return err;
169 }
170
171 net_buf_simple_pull(msg, mtu);
172
173 while (msg->len) {
174 if (msg->len + 1 <= mtu) {
175 net_buf_simple_push_u8(msg, PDU_HDR(SAR_LAST, type));
176 err = role->cb.send(conn, msg->data, msg->len, end, user_data);
177 if (err) {
178 return err;
179 }
180
181 break;
182 }
183
184 net_buf_simple_push_u8(msg, PDU_HDR(SAR_CONT, type));
185 err = role->cb.send(conn, msg->data, mtu, NULL, NULL);
186 if (err) {
187 return err;
188 }
189
190 net_buf_simple_pull(msg, mtu);
191 }
192
193 return 0;
194 }
195
buf_send_end(struct bt_conn * conn,void * user_data)196 static void buf_send_end(struct bt_conn *conn, void *user_data)
197 {
198 struct bt_mesh_adv *adv = user_data;
199
200 bt_mesh_adv_unref(adv);
201 }
202
bt_mesh_proxy_relay_send(struct bt_conn * conn,struct bt_mesh_adv * adv)203 int bt_mesh_proxy_relay_send(struct bt_conn *conn, struct bt_mesh_adv *adv)
204 {
205 int err;
206
207 NET_BUF_SIMPLE_DEFINE(msg, 1 + BT_MESH_NET_MAX_PDU_LEN);
208
209 /* Proxy PDU sending modifies the original buffer,
210 * so we need to make a copy.
211 */
212 net_buf_simple_reserve(&msg, 1);
213 net_buf_simple_add_mem(&msg, adv->b.data, adv->b.len);
214
215 err = bt_mesh_proxy_msg_send(conn, BT_MESH_PROXY_NET_PDU,
216 &msg, buf_send_end, bt_mesh_adv_ref(adv));
217
218 bt_mesh_adv_send_start(0, err, &adv->ctx);
219 if (err) {
220 LOG_ERR("Failed to send proxy message (err %d)", err);
221
222 /* If segment_and_send() fails the buf_send_end() callback will
223 * not be called, so we need to clear the user data (net_buf,
224 * which is just opaque data to segment_and send) reference given
225 * to segment_and_send() here.
226 */
227 bt_mesh_adv_unref(adv);
228 }
229
230 return err;
231 }
232
proxy_msg_init(struct bt_mesh_proxy_role * role)233 static void proxy_msg_init(struct bt_mesh_proxy_role *role)
234 {
235 /* Check if buf has been allocated, in this way, we no longer need
236 * to repeat the operation.
237 */
238 if (role->buf.__buf) {
239 net_buf_simple_reset(&role->buf);
240 return;
241 }
242
243 net_buf_simple_init_with_data(&role->buf,
244 &bufs[bt_conn_index(role->conn) *
245 CONFIG_BT_MESH_PROXY_MSG_LEN],
246 CONFIG_BT_MESH_PROXY_MSG_LEN);
247
248 net_buf_simple_reset(&role->buf);
249
250 k_work_init_delayable(&role->sar_timer, proxy_sar_timeout);
251 }
252
bt_mesh_proxy_role_setup(struct bt_conn * conn,proxy_send_cb_t send,proxy_recv_cb_t recv)253 struct bt_mesh_proxy_role *bt_mesh_proxy_role_setup(struct bt_conn *conn,
254 proxy_send_cb_t send,
255 proxy_recv_cb_t recv)
256 {
257 struct bt_mesh_proxy_role *role;
258
259 conn_count++;
260
261 role = &roles[bt_conn_index(conn)];
262
263 role->conn = bt_conn_ref(conn);
264 proxy_msg_init(role);
265
266 role->cb.recv = recv;
267 role->cb.send = send;
268
269 return role;
270 }
271
bt_mesh_proxy_role_cleanup(struct bt_mesh_proxy_role * role)272 void bt_mesh_proxy_role_cleanup(struct bt_mesh_proxy_role *role)
273 {
274 /* If this fails, the work handler exits early, as
275 * there's no active connection.
276 */
277 (void)k_work_cancel_delayable(&role->sar_timer);
278 bt_conn_unref(role->conn);
279 role->conn = NULL;
280
281 conn_count--;
282
283 bt_mesh_adv_gatt_update();
284 }
285
bt_mesh_proxy_has_avail_conn(void)286 bool bt_mesh_proxy_has_avail_conn(void)
287 {
288 return conn_count < CONFIG_BT_MESH_MAX_CONN;
289 }
290