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