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