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_queue_put(struct bt_mesh_proxy_role * role,struct bt_mesh_adv * adv)59 static void proxy_queue_put(struct bt_mesh_proxy_role *role, struct bt_mesh_adv *adv)
60 {
61 k_fifo_put(&role->pending, &(adv->gatt_bearer[bt_conn_index(role->conn)]));
62 }
63
proxy_queue_get(struct bt_mesh_proxy_role * role)64 static struct bt_mesh_adv *proxy_queue_get(struct bt_mesh_proxy_role *role)
65 {
66 void *gatt_bearer;
67
68 gatt_bearer = k_fifo_get(&role->pending, K_NO_WAIT);
69 if (!gatt_bearer) {
70 return NULL;
71 }
72
73 return CONTAINER_OF(gatt_bearer, struct bt_mesh_adv,
74 gatt_bearer[bt_conn_index(role->conn)]);
75 }
76
proxy_sar_timeout(struct k_work * work)77 static void proxy_sar_timeout(struct k_work *work)
78 {
79 struct bt_mesh_proxy_role *role;
80 struct k_work_delayable *dwork = k_work_delayable_from_work(work);
81
82 LOG_WRN("Proxy SAR timeout");
83
84 role = CONTAINER_OF(dwork, struct bt_mesh_proxy_role, sar_timer);
85
86 while (!k_fifo_is_empty(&role->pending)) {
87 struct bt_mesh_adv *adv = proxy_queue_get(role);
88
89 __ASSERT_NO_MSG(adv);
90
91 bt_mesh_adv_unref(adv);
92 }
93
94 if (role->conn) {
95 bt_conn_disconnect(role->conn,
96 BT_HCI_ERR_REMOTE_USER_TERM_CONN);
97 }
98 }
99
bt_mesh_proxy_msg_recv(struct bt_conn * conn,const void * buf,uint16_t len)100 ssize_t bt_mesh_proxy_msg_recv(struct bt_conn *conn,
101 const void *buf, uint16_t len)
102 {
103 const uint8_t *data = buf;
104 struct bt_mesh_proxy_role *role = &roles[bt_conn_index(conn)];
105
106 if (net_buf_simple_tailroom(&role->buf) < len - 1) {
107 LOG_WRN("Proxy role buffer overflow");
108 return -EINVAL;
109 }
110
111 switch (PDU_SAR(data)) {
112 case SAR_COMPLETE:
113 if (role->buf.len) {
114 LOG_WRN("Complete PDU while a pending incomplete one");
115 return -EINVAL;
116 }
117
118 role->msg_type = PDU_TYPE(data);
119 net_buf_simple_add_mem(&role->buf, data + 1, len - 1);
120 role->cb.recv(role);
121 net_buf_simple_reset(&role->buf);
122 break;
123
124 case SAR_FIRST:
125 if (role->buf.len) {
126 LOG_WRN("First PDU while a pending incomplete one");
127 return -EINVAL;
128 }
129
130 k_work_reschedule(&role->sar_timer, PROXY_SAR_TIMEOUT);
131 role->msg_type = PDU_TYPE(data);
132 net_buf_simple_add_mem(&role->buf, data + 1, len - 1);
133 break;
134
135 case SAR_CONT:
136 if (!role->buf.len) {
137 LOG_WRN("Continuation with no prior data");
138 return -EINVAL;
139 }
140
141 if (role->msg_type != PDU_TYPE(data)) {
142 LOG_WRN("Unexpected message type in continuation");
143 return -EINVAL;
144 }
145
146 k_work_reschedule(&role->sar_timer, PROXY_SAR_TIMEOUT);
147 net_buf_simple_add_mem(&role->buf, data + 1, len - 1);
148 break;
149
150 case SAR_LAST:
151 if (!role->buf.len) {
152 LOG_WRN("Last SAR PDU with no prior data");
153 return -EINVAL;
154 }
155
156 if (role->msg_type != PDU_TYPE(data)) {
157 LOG_WRN("Unexpected message type in last SAR PDU");
158 return -EINVAL;
159 }
160
161 /* If this fails, the work handler exits early, as there's no
162 * active SAR buffer.
163 */
164 (void)k_work_cancel_delayable(&role->sar_timer);
165 net_buf_simple_add_mem(&role->buf, data + 1, len - 1);
166 role->cb.recv(role);
167 net_buf_simple_reset(&role->buf);
168 break;
169 }
170
171 return len;
172 }
173
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)174 int bt_mesh_proxy_msg_send(struct bt_conn *conn, uint8_t type,
175 struct net_buf_simple *msg,
176 bt_gatt_complete_func_t end, void *user_data)
177 {
178 int err;
179 uint16_t att_mtu = bt_gatt_get_mtu(conn);
180 uint16_t mtu;
181 struct bt_mesh_proxy_role *role = &roles[bt_conn_index(conn)];
182
183 LOG_DBG("conn %p type 0x%02x len %u: %s", (void *)conn, type, msg->len,
184 bt_hex(msg->data, msg->len));
185
186 /* ATT_MTU - OpCode (1 byte) - Handle (2 bytes) */
187 if (att_mtu < 3) {
188 LOG_WRN("Invalid ATT MTU: %d", att_mtu);
189 return -EINVAL;
190 }
191
192 mtu = att_mtu - 3;
193 if (mtu > msg->len) {
194 net_buf_simple_push_u8(msg, PDU_HDR(SAR_COMPLETE, type));
195 return role->cb.send(conn, msg->data, msg->len, end, user_data);
196 }
197
198 net_buf_simple_push_u8(msg, PDU_HDR(SAR_FIRST, type));
199 err = role->cb.send(conn, msg->data, mtu, NULL, NULL);
200 if (err) {
201 return err;
202 }
203
204 net_buf_simple_pull(msg, mtu);
205
206 while (msg->len) {
207 if (msg->len + 1 <= mtu) {
208 net_buf_simple_push_u8(msg, PDU_HDR(SAR_LAST, type));
209 err = role->cb.send(conn, msg->data, msg->len, end, user_data);
210 if (err) {
211 return err;
212 }
213
214 break;
215 }
216
217 net_buf_simple_push_u8(msg, PDU_HDR(SAR_CONT, type));
218 err = role->cb.send(conn, msg->data, mtu, NULL, NULL);
219 if (err) {
220 return err;
221 }
222
223 net_buf_simple_pull(msg, mtu);
224 }
225
226 return 0;
227 }
228
buf_send_end(struct bt_conn * conn,void * user_data)229 static void buf_send_end(struct bt_conn *conn, void *user_data)
230 {
231 struct bt_mesh_adv *adv = user_data;
232
233 bt_mesh_adv_unref(adv);
234 }
235
proxy_relay_send(struct bt_conn * conn,struct bt_mesh_adv * adv)236 static int proxy_relay_send(struct bt_conn *conn, struct bt_mesh_adv *adv)
237 {
238 int err;
239
240 NET_BUF_SIMPLE_DEFINE(msg, 1 + BT_MESH_NET_MAX_PDU_LEN);
241
242 /* Proxy PDU sending modifies the original buffer,
243 * so we need to make a copy.
244 */
245 net_buf_simple_reserve(&msg, 1);
246 net_buf_simple_add_mem(&msg, adv->b.data, adv->b.len);
247
248 err = bt_mesh_proxy_msg_send(conn, BT_MESH_PROXY_NET_PDU,
249 &msg, buf_send_end, bt_mesh_adv_ref(adv));
250
251 bt_mesh_adv_send_start(0, err, &adv->ctx);
252 if (err) {
253 LOG_ERR("Failed to send proxy message (err %d)", err);
254
255 /* If segment_and_send() fails the buf_send_end() callback will
256 * not be called, so we need to clear the user data (net_buf,
257 * which is just opaque data to segment_and send) reference given
258 * to segment_and_send() here.
259 */
260 bt_mesh_adv_unref(adv);
261 }
262
263 return err;
264 }
265
bt_mesh_proxy_relay_send(struct bt_conn * conn,struct bt_mesh_adv * adv)266 int bt_mesh_proxy_relay_send(struct bt_conn *conn, struct bt_mesh_adv *adv)
267 {
268 struct bt_mesh_proxy_role *role = &roles[bt_conn_index(conn)];
269
270 proxy_queue_put(role, bt_mesh_adv_ref(adv));
271
272 bt_mesh_wq_submit(&role->work);
273
274 return 0;
275 }
276
proxy_msg_send_pending(struct k_work * work)277 static void proxy_msg_send_pending(struct k_work *work)
278 {
279 struct bt_mesh_proxy_role *role = CONTAINER_OF(work, struct bt_mesh_proxy_role, work);
280 struct bt_mesh_adv *adv;
281
282 if (!role->conn) {
283 return;
284 }
285
286 adv = proxy_queue_get(role);
287 if (!adv) {
288 return;
289 }
290
291 (void)proxy_relay_send(role->conn, adv);
292 bt_mesh_adv_unref(adv);
293
294 if (!k_fifo_is_empty(&role->pending)) {
295 bt_mesh_wq_submit(&role->work);
296 }
297 }
298
proxy_msg_init(struct bt_mesh_proxy_role * role)299 static void proxy_msg_init(struct bt_mesh_proxy_role *role)
300 {
301 /* Check if buf has been allocated, in this way, we no longer need
302 * to repeat the operation.
303 */
304 if (role->buf.__buf) {
305 net_buf_simple_reset(&role->buf);
306 return;
307 }
308
309 net_buf_simple_init_with_data(&role->buf,
310 &bufs[bt_conn_index(role->conn) *
311 CONFIG_BT_MESH_PROXY_MSG_LEN],
312 CONFIG_BT_MESH_PROXY_MSG_LEN);
313
314 net_buf_simple_reset(&role->buf);
315
316 k_fifo_init(&role->pending);
317 k_work_init(&role->work, proxy_msg_send_pending);
318
319 k_work_init_delayable(&role->sar_timer, proxy_sar_timeout);
320 }
321
bt_mesh_proxy_role_setup(struct bt_conn * conn,proxy_send_cb_t send,proxy_recv_cb_t recv)322 struct bt_mesh_proxy_role *bt_mesh_proxy_role_setup(struct bt_conn *conn,
323 proxy_send_cb_t send,
324 proxy_recv_cb_t recv)
325 {
326 struct bt_mesh_proxy_role *role;
327
328 conn_count++;
329
330 role = &roles[bt_conn_index(conn)];
331
332 role->conn = bt_conn_ref(conn);
333 proxy_msg_init(role);
334
335 role->cb.recv = recv;
336 role->cb.send = send;
337
338 return role;
339 }
340
bt_mesh_proxy_role_cleanup(struct bt_mesh_proxy_role * role)341 void bt_mesh_proxy_role_cleanup(struct bt_mesh_proxy_role *role)
342 {
343 /* If this fails, the work handler exits early, as
344 * there's no active connection.
345 */
346 (void)k_work_cancel_delayable(&role->sar_timer);
347 bt_conn_unref(role->conn);
348 role->conn = NULL;
349
350 conn_count--;
351
352 bt_mesh_adv_gatt_update();
353 }
354
bt_mesh_proxy_has_avail_conn(void)355 bool bt_mesh_proxy_has_avail_conn(void)
356 {
357 return conn_count < CONFIG_BT_MESH_MAX_CONN;
358 }
359