1
9
10
11
12
13
14
15
16
17
18
19
20
23
24
25
26
27
28
29
32
33
34
38
39
42
43
48
49
52
53
54
55
56
57
58
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
121
122
123
124
125
126
127
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
171
172
173
177
178
179
180
181
182
183
184
185
186
187
190
191
192
193
197
198
199
200
201
202
203
204
210
211
212
213
214
215
216
217
218
224
225
226
227
228
229
235
236
237
238
239
243
250
251
255
256
257
258
259
260
261
262
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
288
289
292
293
294
295
296
297
298
299
300
301
304
305
306
307
308
309
310
314
315
316
317
318
319
322
323
324
325
326
327
328
329
330
331
332
337
338
339
340
341
342
343
347
348
349
350
351
352
355
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
384
385
386
387
388
389
390
391
392
393
394
395
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
423
424
425
426
427
428
429
430
431
432
436
446
447
448
449
453
454
455
456
457
458
459
460
461
462
463
466
467
479
480
481
482
483
484
485
486
487
/* ... */
#include "esp_wifi.h"
#include "esp_netif.h"
#include "esp_log.h"
#include <string.h>
#include "esp_mesh.h"
#include "esp_mac.h"
#include "lwip/lwip_napt.h"
#include "dhcpserver/dhcpserver.h"
#include "esp_wifi_netif.h"
#include "mesh_netif.h"10 includes
/* ... */
#define RX_SIZE (1560)
#if CONFIG_MESH_USE_GLOBAL_DNS_IP
#define DNS_IP_ADDR CONFIG_MESH_GLOBAL_DNS_IP
#endif
/* ... */
typedef struct mesh_netif_driver* mesh_netif_driver_t;
typedef struct mesh_netif_driver {
esp_netif_driver_base_t base;
uint8_t sta_mac_addr[MAC_ADDR_LEN];
}{ ... }* mesh_netif_driver_t;
/* ... */
static const char* TAG = "mesh_netif";
const esp_netif_ip_info_t g_mesh_netif_subnet_ip = {
.ip = { .addr = ESP_IP4TOADDR( 10, 0, 0, 1) },
.gw = { .addr = ESP_IP4TOADDR( 10, 0, 0, 1) },
.netmask = { .addr = ESP_IP4TOADDR( 255, 255, 0, 0) },
}{...};
/* ... */
static esp_netif_t *netif_sta = NULL;
static esp_netif_t *netif_ap = NULL;
static bool receive_task_is_running = false;
static mesh_addr_t s_route_table[CONFIG_MESH_ROUTE_TABLE_SIZE] = { 0 };
static mesh_raw_recv_cb_t *s_mesh_raw_recv_cb = NULL;
/* ... */
static esp_err_t set_dhcps_dns(esp_netif_t *netif, uint32_t addr)
{
esp_netif_dns_info_t dns;
dns.ip.u_addr.ip4.addr = addr;
dns.ip.type = IPADDR_TYPE_V4;
dhcps_offer_t dhcps_dns_value = OFFER_DNS;
ESP_ERROR_CHECK(esp_netif_dhcps_option(netif, ESP_NETIF_OP_SET, ESP_NETIF_DOMAIN_NAME_SERVER, &dhcps_dns_value, sizeof(dhcps_dns_value)));
ESP_ERROR_CHECK(esp_netif_set_dns_info(netif, ESP_NETIF_DNS_MAIN, &dns));
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_netif_dhcps_start(netif));
return ESP_OK;
}{ ... }
static void receive_task(void *arg)
{
esp_err_t err;
mesh_addr_t from;
int flag = 0;
mesh_data_t data;
static uint8_t rx_buf[RX_SIZE] = { 0, };
ESP_LOGD(TAG, "Receiving task started");
while (receive_task_is_running) {
data.data = rx_buf;
data.size = RX_SIZE;
err = esp_mesh_recv(&from, &data, portMAX_DELAY, &flag, NULL, 0);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Received with err code %d %s", err, esp_err_to_name(err));
continue;
}{...}
if (data.proto == MESH_PROTO_BIN && s_mesh_raw_recv_cb) {
s_mesh_raw_recv_cb(&from, &data);
}{...}
if (esp_mesh_is_root()) {
if (data.proto == MESH_PROTO_AP) {
ESP_LOGD(TAG, "Root received: from: " MACSTR " to " MACSTR " size: %d",
MAC2STR((uint8_t*)data.data) ,MAC2STR((uint8_t*)(data.data+6)), data.size);
if (netif_ap) {
esp_netif_receive(netif_ap, data.data, data.size, NULL);
}{...}
}{...} else if (data.proto == MESH_PROTO_STA) {
ESP_LOGE(TAG, "Root station Should never receive data from mesh!");
}{...}
}{...} else {
if (data.proto == MESH_PROTO_AP) {
ESP_LOGD(TAG, "Node AP should never receive data from mesh");
}{...} else if (data.proto == MESH_PROTO_STA) {
ESP_LOGD(TAG, "Node received: from: " MACSTR " to " MACSTR " size: %d",
MAC2STR((uint8_t*)data.data) ,MAC2STR((uint8_t*)(data.data+6)), data.size);
if (netif_sta) {
esp_netif_receive(netif_sta, data.data, data.size, NULL);
}{...}
}{...}
}{...}
}{...}
vTaskDelete(NULL);
}{ ... }
static void mesh_free(void *h, void* buffer)
{
free(buffer);
}{ ... }
static esp_err_t mesh_netif_transmit_from_root_ap(void *h, void *buffer, size_t len)
{
static const uint8_t eth_broadcast[MAC_ADDR_LEN] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF };
int route_table_size = 0;
mesh_netif_driver_t mesh_driver = h;
mesh_addr_t dest_addr;
mesh_data_t data;
ESP_LOGD(TAG, "Sending to node: " MACSTR ", size: %d" ,MAC2STR((uint8_t*)buffer), len);
memcpy(dest_addr.addr, buffer, MAC_ADDR_LEN);
data.data = buffer;
data.size = len;
data.proto = MESH_PROTO_STA;
data.tos = MESH_TOS_P2P;
if (MAC_ADDR_EQUAL(dest_addr.addr, eth_broadcast)) {
ESP_LOGD(TAG, "Broadcasting!");
esp_mesh_get_routing_table((mesh_addr_t *) &s_route_table,
CONFIG_MESH_ROUTE_TABLE_SIZE * 6, &route_table_size);
for (int i = 0; i < route_table_size; i++) {
if (MAC_ADDR_EQUAL(s_route_table[i].addr, mesh_driver->sta_mac_addr)) {
ESP_LOGD(TAG, "That was me, skipping!");
continue;
}{...}
ESP_LOGD(TAG, "Broadcast: Sending to [%d] " MACSTR, i, MAC2STR(s_route_table[i].addr));
esp_err_t err = esp_mesh_send(&s_route_table[i], &data, MESH_DATA_P2P, NULL, 0);
if (ESP_OK != err) {
ESP_LOGE(TAG, "Send with err code %d %s", err, esp_err_to_name(err));
}{...}
}{...}
}{...} else {
esp_err_t err = esp_mesh_send(&dest_addr, &data, MESH_DATA_P2P, NULL, 0);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Send with err code %d %s", err, esp_err_to_name(err));
return err;
}{...}
}{...}
return ESP_OK;
}{ ... }
static esp_err_t mesh_netif_transmit_from_root_ap_wrap(void *h, void *buffer, size_t len, void *netstack_buf)
{
return mesh_netif_transmit_from_root_ap(h, buffer, len);
}{ ... }
static esp_err_t mesh_netif_transmit_from_node_sta(void *h, void *buffer, size_t len)
{
mesh_data_t data;
ESP_LOGD(TAG, "Sending to root, dest addr: " MACSTR ", size: %d" ,MAC2STR((uint8_t*)buffer), len);
data.data = buffer;
data.size = len;
data.proto = MESH_PROTO_AP;
data.tos = MESH_TOS_P2P;
esp_err_t err = esp_mesh_send(NULL, &data, MESH_DATA_TODS, NULL, 0);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Send with err code %d %s", err, esp_err_to_name(err));
}{...}
return err;
}{ ... }
static esp_err_t mesh_netif_transmit_from_node_sta_wrap(void *h, void *buffer, size_t len, void *netstack_buf)
{
return mesh_netif_transmit_from_node_sta(h, buffer, len);
}{ ... }
static esp_err_t mesh_driver_start_root_ap(esp_netif_t * esp_netif, void * args)
{
mesh_netif_driver_t driver = args;
driver->base.netif = esp_netif;
esp_netif_driver_ifconfig_t driver_ifconfig = {
.handle = driver,
.transmit = mesh_netif_transmit_from_root_ap,
.transmit_wrap = mesh_netif_transmit_from_root_ap_wrap,
.driver_free_rx_buffer = mesh_free
}{...};
return esp_netif_set_driver_config(esp_netif, &driver_ifconfig);
}{ ... }
static esp_err_t mesh_driver_start_node_sta(esp_netif_t * esp_netif, void * args)
{
mesh_netif_driver_t driver = args;
driver->base.netif = esp_netif;
esp_netif_driver_ifconfig_t driver_ifconfig = {
.handle = driver,
.transmit = mesh_netif_transmit_from_node_sta,
.transmit_wrap = mesh_netif_transmit_from_node_sta_wrap,
.driver_free_rx_buffer = mesh_free
}{...};
return esp_netif_set_driver_config(esp_netif, &driver_ifconfig);
}{ ... }
void mesh_delete_if_driver(mesh_netif_driver_t driver)
{
free(driver);
}{ ... }
mesh_netif_driver_t mesh_create_if_driver(bool is_ap, bool is_root)
{
mesh_netif_driver_t driver = calloc(1, sizeof(struct mesh_netif_driver));
if (driver == NULL) {
ESP_LOGE(TAG, "No memory to create a wifi interface handle");
return NULL;
}{...}
if (is_ap && is_root) {
driver->base.post_attach = mesh_driver_start_root_ap;
}{...} else if (!is_ap && !is_root) {
driver->base.post_attach = mesh_driver_start_node_sta;
}{...} else {
return NULL;
}{...}
if (!receive_task_is_running) {
receive_task_is_running = true;
xTaskCreate(receive_task, "netif rx task", 3072, NULL, 5, NULL);
}{...}
esp_wifi_get_mac(WIFI_IF_STA, driver->sta_mac_addr);
return driver;
}{ ... }
esp_err_t mesh_netifs_destroy(void)
{
receive_task_is_running = false;
return ESP_OK;
}{ ... }
static void mesh_netif_init_station(void)
{
esp_netif_config_t cfg_sta = ESP_NETIF_DEFAULT_WIFI_STA();
netif_sta = esp_netif_new(&cfg_sta);
assert(netif_sta);
ESP_ERROR_CHECK(esp_netif_attach_wifi_station(netif_sta));
ESP_ERROR_CHECK(esp_wifi_set_default_wifi_sta_handlers());
}{ ... }
esp_err_t mesh_netifs_init(mesh_raw_recv_cb_t *cb)
{
mesh_netif_init_station();
s_mesh_raw_recv_cb = cb;
return ESP_OK;
}{ ... }
/* ... */
static esp_err_t start_mesh_link_ap(void)
{
uint8_t mac[MAC_ADDR_LEN];
esp_wifi_get_mac(WIFI_IF_AP, mac);
esp_netif_set_mac(netif_ap, mac);
esp_netif_action_start(netif_ap, NULL, 0, NULL);
return ESP_OK;
}{ ... }
/* ... */
static esp_err_t start_wifi_link_sta(void)
{
uint8_t mac[6];
esp_wifi_get_mac(WIFI_IF_STA, mac);
esp_err_t ret;
void *driver = esp_netif_get_io_driver(netif_sta);
if ((ret = esp_wifi_register_if_rxcb(driver, esp_netif_receive, netif_sta)) != ESP_OK) {
ESP_LOGE(TAG, "esp_wifi_register_if_rxcb for if=%p failed with %d", driver, ret);
return ESP_FAIL;
}{...}
esp_netif_set_mac(netif_sta, mac);
esp_netif_action_start(netif_sta, NULL, 0, NULL);
return ESP_OK;
}{ ... }
/* ... */
static esp_err_t start_mesh_link_sta(void)
{
uint8_t mac[MAC_ADDR_LEN];
esp_wifi_get_mac(WIFI_IF_STA, mac);
esp_netif_set_mac(netif_sta, mac);
esp_netif_action_start(netif_sta, NULL, 0, NULL);
esp_netif_action_connected(netif_sta, NULL, 0, NULL);
return ESP_OK;
}{ ... }
/* ... */
static esp_netif_t* create_mesh_link_ap(void)
{
esp_netif_inherent_config_t base_cfg = ESP_NETIF_INHERENT_DEFAULT_WIFI_AP();
base_cfg.if_desc = "mesh_link_ap";
base_cfg.ip_info = &g_mesh_netif_subnet_ip;
esp_netif_config_t cfg = {
.base = &base_cfg,
.driver = NULL,
.stack = ESP_NETIF_NETSTACK_DEFAULT_WIFI_AP }{...};
esp_netif_t * netif = esp_netif_new(&cfg);
assert(netif);
return netif;
}{ ... }
/* ... */
static void destory_mesh_link_ap(void)
{
if (netif_ap) {
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_netif_dhcps_stop(netif_ap));
esp_netif_action_disconnected(netif_ap, NULL, 0, NULL);
mesh_delete_if_driver(esp_netif_get_io_driver(netif_ap));
esp_netif_destroy(netif_ap);
netif_ap = NULL;
}{...}
}{ ... }
/* ... */
static esp_netif_t* create_mesh_link_sta(void)
{
esp_netif_inherent_config_t base_cfg = ESP_NETIF_INHERENT_DEFAULT_WIFI_STA();
base_cfg.if_desc = "mesh_link_sta";
esp_netif_config_t cfg = {
.base = &base_cfg,
.driver = NULL,
.stack = ESP_NETIF_NETSTACK_DEFAULT_WIFI_STA }{...};
esp_netif_t * netif = esp_netif_new(&cfg);
assert(netif);
return netif;
}{ ... }
esp_err_t mesh_netif_start_root_ap(bool is_root, uint32_t addr)
{
if (is_root) {
destory_mesh_link_ap();
netif_ap = create_mesh_link_ap();
mesh_netif_driver_t driver = mesh_create_if_driver(true, true);
if (driver == NULL) {
ESP_LOGE(TAG, "Failed to create wifi interface handle");
return ESP_FAIL;
}{...}
esp_netif_attach(netif_ap, driver);
set_dhcps_dns(netif_ap, addr);
start_mesh_link_ap();
ip_napt_enable(g_mesh_netif_subnet_ip.ip.addr, 1);
}{...}
return ESP_OK;
}{ ... }
esp_err_t mesh_netifs_start(bool is_root)
{
if (is_root) {
if (netif_sta && strcmp(esp_netif_get_desc(netif_sta), "sta") == 0) {
ESP_LOGI(TAG, "Already wifi station, no need to do anything");
}{...} else if (netif_sta && strcmp(esp_netif_get_desc(netif_sta), "mesh_link_sta") == 0) {
esp_netif_action_disconnected(netif_sta, NULL, 0, NULL);
mesh_delete_if_driver(esp_netif_get_io_driver(netif_sta));
esp_netif_destroy(netif_sta);
mesh_netif_init_station();
}{...} else if (netif_sta == NULL) {
mesh_netif_init_station();
}{...}
#if CONFIG_MESH_USE_GLOBAL_DNS_IP
mesh_netif_start_root_ap(true, htonl(DNS_IP_ADDR));
#endif
}{...} else {
if (netif_sta && strcmp(esp_netif_get_desc(netif_sta), "mesh_link_sta") == 0) {
ESP_LOGI(TAG, "Already mesh link station, no need to do anything");
return ESP_OK;
}{...}
if (netif_sta) {
esp_netif_action_disconnected(netif_sta, NULL, 0, NULL);
if (strcmp(esp_netif_get_desc(netif_sta), "sta") == 0) {
ESP_LOGI(TAG, "It was a wifi station removing stuff");
esp_wifi_clear_default_wifi_driver_and_handlers(netif_sta);
}{...}
esp_netif_destroy(netif_sta);
}{...}
netif_sta = create_mesh_link_sta();
mesh_netif_driver_t driver = mesh_create_if_driver(false, false);
if (driver == NULL) {
ESP_LOGE(TAG, "Failed to create wifi interface handle");
return ESP_FAIL;
}{...}
esp_netif_attach(netif_sta, driver);
start_mesh_link_sta();
destory_mesh_link_ap();
}{...}
return ESP_OK;
}{ ... }
esp_err_t mesh_netifs_stop(void)
{
if (netif_sta && strcmp(esp_netif_get_desc(netif_sta), "sta") == 0 && netif_ap == NULL) {
return ESP_OK;
}{...}
if (netif_sta) {
if (strcmp(esp_netif_get_desc(netif_sta), "sta") == 0) {
esp_netif_action_disconnected(netif_sta, NULL, 0, NULL);
esp_netif_action_stop(netif_sta, NULL, 0, NULL);
esp_wifi_clear_default_wifi_driver_and_handlers(netif_sta);
}{...} else {
esp_netif_action_disconnected(netif_sta, NULL, 0, NULL);
mesh_delete_if_driver(esp_netif_get_io_driver(netif_sta));
}{...}
esp_netif_destroy(netif_sta);
netif_sta = NULL;
}{...}
destory_mesh_link_ap();
mesh_netif_init_station();
start_wifi_link_sta();
return ESP_OK;
}{ ... }
uint8_t* mesh_netif_get_station_mac(void)
{
mesh_netif_driver_t mesh = esp_netif_get_io_driver(netif_sta);
return mesh->sta_mac_addr;
}{ ... }