Skip to content

Commit 9b7b517

Browse files
committed
Safer creation of atoms in ESP32 network_driver.c
Removes the up-fron declaration of `static const char *const` atom strings in favor of inline ATOM_STR() for better redability. Changes to use of `globalcontext_existing_term_from_atom_string` where possible. AP and STA mode specific atoms are only created for the interface(s) that are used. All atoms that are created by the driver are now checked to be certain the creation was sucessful. Addresses concerns raised in issue #1442 for the ESP32 network driver. Signed-off-by: Winford <winford@object.stream>
1 parent dfc3bf1 commit 9b7b517

File tree

2 files changed

+111
-53
lines changed

2 files changed

+111
-53
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ certain VM instructions are used.
2828
- Fixed SPI close command
2929
- Added missing lock on socket structure
3030

31+
### Changed
32+
- Updated atom initalization in esp32 network_driver.c for issue #1442
33+
3134
## [0.6.5] - 2024-10-15
3235

3336
### Added

src/platforms/esp32/components/avm_builtins/network_driver.c

Lines changed: 108 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -60,26 +60,6 @@
6060
#define TAG "network_driver"
6161
#define PORT_REPLY_SIZE (TUPLE_SIZE(2) + REF_SIZE)
6262

63-
static const char *const ap_atom = ATOM_STR("\x2", "ap");
64-
static const char *const ap_channel_atom = ATOM_STR("\xA", "ap_channel");
65-
static const char *const ap_sta_connected_atom = ATOM_STR("\x10", "ap_sta_connected");
66-
static const char *const ap_sta_disconnected_atom = ATOM_STR("\x13", "ap_sta_disconnected");
67-
static const char *const ap_sta_ip_assigned_atom = ATOM_STR("\x12", "ap_sta_ip_assigned");
68-
static const char *const ap_started_atom = ATOM_STR("\xA", "ap_started");
69-
static const char *const dhcp_hostname_atom = ATOM_STR("\xD", "dhcp_hostname");
70-
static const char *const host_atom = ATOM_STR("\x4", "host");
71-
static const char *const max_connections_atom = ATOM_STR("\xF", "max_connections");
72-
static const char *const psk_atom = ATOM_STR("\x3", "psk");
73-
static const char *const sntp_atom = ATOM_STR("\x4", "sntp");
74-
static const char *const sntp_sync_atom = ATOM_STR("\x9", "sntp_sync");
75-
static const char *const ssid_atom = ATOM_STR("\x4", "ssid");
76-
static const char *const ssid_hidden_atom = ATOM_STR("\xB", "ssid_hidden");
77-
static const char *const sta_atom = ATOM_STR("\x3", "sta");
78-
static const char *const sta_connected_atom = ATOM_STR("\xD", "sta_connected");
79-
static const char *const sta_beacon_timeout_atom = ATOM_STR("\x12", "sta_beacon_timeout");
80-
static const char *const sta_disconnected_atom = ATOM_STR("\x10", "sta_disconnected");
81-
static const char *const sta_got_ip_atom = ATOM_STR("\xA", "sta_got_ip");
82-
8363
ESP_EVENT_DECLARE_BASE(sntp_event_base);
8464
ESP_EVENT_DEFINE_BASE(sntp_event_base);
8565

@@ -112,11 +92,6 @@ struct ClientData
11292
uint64_t ref_ticks;
11393
};
11494

115-
static inline term make_atom(GlobalContext *global, AtomString atom_str)
116-
{
117-
return globalcontext_make_atom(global, atom_str);
118-
}
119-
12095
static term tuple_from_addr(Heap *heap, uint32_t addr)
12196
{
12297
term terms[4];
@@ -151,20 +126,58 @@ static void send_got_ip(struct ClientData *data, esp_netif_ip_info_t *info)
151126
term gw = tuple_from_addr(&heap, ntohl(info->gw.addr));
152127

153128
term ip_info = port_heap_create_tuple3(&heap, ip, netmask, gw);
154-
term reply = port_heap_create_tuple2(&heap, make_atom(data->global, sta_got_ip_atom), ip_info);
129+
term reply = port_heap_create_tuple2(&heap, globalcontext_existing_term_from_atom_string(data->global, ATOM_STR("\xA", "sta_got_ip")), ip_info);
155130
send_term(&heap, data, reply);
156131
}
157132
END_WITH_STACK_HEAP(heap, data->global);
158133
}
159134

135+
// Used to initialize atoms use in STA mode callbacks when sta mode is configured
136+
// callbacks should get the existing atom term from from the atom string.
137+
#define NUM_STA_ATOMS 4
138+
bool init_sta_cb_atoms(GlobalContext *glb)
139+
{
140+
bool result = true;
141+
AtomString sta_cb_atom[NUM_STA_ATOMS] = { ATOM_STR("\xD", "sta_connected"), ATOM_STR("\x12", "sta_beacon_timeout"),
142+
ATOM_STR("\x10", "sta_disconnected"), ATOM_STR("\xA", "sta_got_ip") };
143+
144+
for (int atom = 0; atom < NUM_STA_ATOMS; atom++) {
145+
int index = globalcontext_insert_atom(glb, sta_cb_atom[atom]);
146+
if (UNLIKELY(index < 0)) {
147+
result = false;
148+
}
149+
}
150+
151+
return result;
152+
}
153+
154+
// Used to initialize atoms use in AP mode callbacks when ap mode is configured
155+
// callbacks should get the existing atom term from from the atom string.
156+
#define NUM_AP_ATOMS 4
157+
bool init_ap_cb_atoms(GlobalContext *glb)
158+
{
159+
bool result = true;
160+
AtomString ap_cb_atoms[NUM_AP_ATOMS] = { ATOM_STR("\x10", "ap_sta_connected"), ATOM_STR("\x13", "ap_sta_disconnected"),
161+
ATOM_STR("\x12", "ap_sta_ip_assigned"), ATOM_STR("\xA", "ap_started") };
162+
163+
for (int atom = 0; atom < NUM_AP_ATOMS; atom++) {
164+
int index = globalcontext_insert_atom(glb, ap_cb_atoms[atom]);
165+
if (UNLIKELY(index < 0)) {
166+
result = false;
167+
}
168+
}
169+
170+
return result;
171+
}
172+
160173
static void send_sta_connected(struct ClientData *data)
161174
{
162175
TRACE("Sending sta_connected back to AtomVM\n");
163176

164177
// {Ref, sta_connected}
165178
BEGIN_WITH_STACK_HEAP(PORT_REPLY_SIZE, heap);
166179
{
167-
send_term(&heap, data, make_atom(data->global, sta_connected_atom));
180+
send_term(&heap, data, globalcontext_existing_term_from_atom_string(data->global, ATOM_STR("\xD", "sta_connected")));
168181
}
169182
END_WITH_STACK_HEAP(heap, data->global);
170183
}
@@ -176,7 +189,7 @@ static void send_sta_beacon_timeout(struct ClientData *data)
176189
// {Ref, sta_beacon_timeout}
177190
BEGIN_WITH_STACK_HEAP(PORT_REPLY_SIZE, heap);
178191
{
179-
send_term(&heap, data, make_atom(data->global, sta_beacon_timeout_atom));
192+
send_term(&heap, data, globalcontext_existing_term_from_atom_string(data->global, ATOM_STR("\x12", "sta_beacon_timeout")));
180193
}
181194
END_WITH_STACK_HEAP(heap, data->global);
182195
}
@@ -188,7 +201,7 @@ static void send_sta_disconnected(struct ClientData *data)
188201
// {Ref, sta_disconnected}
189202
BEGIN_WITH_STACK_HEAP(PORT_REPLY_SIZE, heap);
190203
{
191-
send_term(&heap, data, make_atom(data->global, sta_disconnected_atom));
204+
send_term(&heap, data, globalcontext_existing_term_from_atom_string(data->global, ATOM_STR("\x10", "sta_disconnected")));
192205
}
193206
END_WITH_STACK_HEAP(heap, data->global);
194207
}
@@ -200,7 +213,7 @@ static void send_ap_started(struct ClientData *data)
200213
// {Ref, ap_started}
201214
BEGIN_WITH_STACK_HEAP(PORT_REPLY_SIZE, heap);
202215
{
203-
send_term(&heap, data, make_atom(data->global, ap_started_atom));
216+
send_term(&heap, data, globalcontext_existing_term_from_atom_string(data->global, ATOM_STR("\xA", "ap_started")));
204217
}
205218
END_WITH_STACK_HEAP(heap, data->global);
206219
}
@@ -220,13 +233,13 @@ static void send_atom_mac(struct ClientData *data, term atom, uint8_t *mac)
220233
static void send_ap_sta_connected(struct ClientData *data, uint8_t *mac)
221234
{
222235
TRACE("Sending ap_sta_connected back to AtomVM\n");
223-
send_atom_mac(data, make_atom(data->global, ap_sta_connected_atom), mac);
236+
send_atom_mac(data, globalcontext_existing_term_from_atom_string(data->global, ATOM_STR("\x10", "ap_sta_connected")), mac);
224237
}
225238

226239
static void send_ap_sta_disconnected(struct ClientData *data, uint8_t *mac)
227240
{
228241
TRACE("Sending ap_sta_disconnected back to AtomVM\n");
229-
send_atom_mac(data, make_atom(data->global, ap_sta_disconnected_atom), mac);
242+
send_atom_mac(data, globalcontext_existing_term_from_atom_string(data->global, ATOM_STR("\x13", "ap_sta_disconnected")), mac);
230243
}
231244

232245
static void send_ap_sta_ip_assigned(struct ClientData *data, esp_ip4_addr_t *ip)
@@ -236,7 +249,7 @@ static void send_ap_sta_ip_assigned(struct ClientData *data, esp_ip4_addr_t *ip)
236249
BEGIN_WITH_STACK_HEAP(PORT_REPLY_SIZE + TUPLE_SIZE(2) + TUPLE_SIZE(4), heap);
237250
{
238251
term ip_term = tuple_from_addr(&heap, ntohl(ip->addr));
239-
term reply = port_heap_create_tuple2(&heap, make_atom(data->global, ap_sta_ip_assigned_atom), ip_term);
252+
term reply = port_heap_create_tuple2(&heap, globalcontext_existing_term_from_atom_string(data->global, ATOM_STR("\x12", "ap_sta_ip_assigned")), ip_term);
240253
send_term(&heap, data, reply);
241254
}
242255
END_WITH_STACK_HEAP(heap, data->global);
@@ -250,7 +263,7 @@ static void send_sntp_sync(struct ClientData *data, struct timeval *tv)
250263
BEGIN_WITH_STACK_HEAP(PORT_REPLY_SIZE + TUPLE_SIZE(2) * 2 + BOXED_INT64_SIZE * 2, heap);
251264
{
252265
term tv_tuple = port_heap_create_tuple2(&heap, term_make_maybe_boxed_int64(tv->tv_sec, &heap), term_make_maybe_boxed_int64(tv->tv_usec, &heap));
253-
term reply = port_heap_create_tuple2(&heap, make_atom(data->global, sntp_sync_atom), tv_tuple);
266+
term reply = port_heap_create_tuple2(&heap, globalcontext_existing_term_from_atom_string(data->global, ATOM_STR("\x9", "sntp_sync")), tv_tuple);
254267
send_term(&heap, data, reply);
255268
}
256269
END_WITH_STACK_HEAP(heap, data->global);
@@ -380,8 +393,8 @@ static wifi_config_t *get_sta_wifi_config(term sta_config, GlobalContext *global
380393
TRACE("No STA config\n");
381394
return NULL;
382395
}
383-
term ssid_term = interop_kv_get_value(sta_config, ssid_atom, global);
384-
term pass_term = interop_kv_get_value(sta_config, psk_atom, global);
396+
term ssid_term = interop_kv_get_value(sta_config, ATOM_STR("\x4", "ssid"), global);
397+
term pass_term = interop_kv_get_value(sta_config, ATOM_STR("\x3", "psk"), global);
385398

386399
//
387400
// Check parameters
@@ -469,9 +482,9 @@ static wifi_config_t *get_ap_wifi_config(term ap_config, GlobalContext *global)
469482
TRACE("No AP config\n");
470483
return NULL;
471484
}
472-
term ssid_term = interop_kv_get_value(ap_config, ssid_atom, global);
473-
term pass_term = interop_kv_get_value(ap_config, psk_atom, global);
474-
term channel_term = interop_kv_get_value(ap_config, ap_channel_atom, global);
485+
term ssid_term = interop_kv_get_value(ap_config, ATOM_STR("\x4", "ssid"), global);
486+
term pass_term = interop_kv_get_value(ap_config, ATOM_STR("\x3", "psk"), global);
487+
term channel_term = interop_kv_get_value(ap_config, ATOM_STR("\xA", "ap_channel"), global);
475488

476489
//
477490
// Check parameters
@@ -545,9 +558,9 @@ static wifi_config_t *get_ap_wifi_config(term ap_config, GlobalContext *global)
545558
}
546559

547560
wifi_config->ap.authmode = IS_NULL_PTR(psk) ? WIFI_AUTH_OPEN : WIFI_AUTH_WPA_WPA2_PSK;
548-
term ssid_hidden_term = interop_kv_get_value(ap_config, ssid_hidden_atom, global);
561+
term ssid_hidden_term = interop_kv_get_value(ap_config, ATOM_STR("\xB", "ssid_hidden"), global);
549562
wifi_config->ap.ssid_hidden = term_is_invalid_term(ssid_hidden_term) ? 0 : ssid_hidden_term == TRUE_ATOM;
550-
term max_connections_term = interop_kv_get_value(ap_config, max_connections_atom, global);
563+
term max_connections_term = interop_kv_get_value(ap_config, ATOM_STR("\xF", "max_connections"), global);
551564
wifi_config->ap.max_connection = term_is_invalid_term(max_connections_term) ? 4 : term_to_int(max_connections_term);
552565

553566
ESP_LOGI(TAG, "AP ssid: %s", wifi_config->ap.ssid);
@@ -570,16 +583,21 @@ static void time_sync_notification_cb(struct timeval *tv)
570583

571584
static void maybe_set_sntp(term sntp_config, GlobalContext *global)
572585
{
573-
if (!term_is_invalid_term(sntp_config) && !term_is_invalid_term(interop_kv_get_value(sntp_config, host_atom, global))) {
586+
if (!term_is_invalid_term(sntp_config) && !term_is_invalid_term(interop_kv_get_value(sntp_config, ATOM_STR("\x4", "host"), global))) {
574587
int ok;
575-
char *host = interop_term_to_string(interop_kv_get_value(sntp_config, host_atom, global), &ok);
588+
char *host = interop_term_to_string(interop_kv_get_value(sntp_config, ATOM_STR("\x4", "host"), global), &ok);
576589
if (LIKELY(ok)) {
577590
// do not free(sntp)
578591
esp_sntp_setoperatingmode(SNTP_OPMODE_POLL);
579592
esp_sntp_setservername(0, host);
580593
sntp_set_time_sync_notification_cb(time_sync_notification_cb);
581594
esp_sntp_init();
582-
ESP_LOGI(TAG, "SNTP initialized with host set to %s", host);
595+
int sntp_sync_index = globalcontext_insert_atom(global, ATOM_STR("\x9", "sntp_sync"));
596+
if (UNLIKELY(sntp_sync_index < 0)) {
597+
ESP_LOGE(TAG, "Failed to create 'sntp_sync' atom! sntp_sync callbacks will fail.");
598+
} else {
599+
ESP_LOGI(TAG, "SNTP initialized with host set to %s", host);
600+
}
583601
} else {
584602
ESP_LOGE(TAG, "Unable to locate sntp host in configuration");
585603
}
@@ -627,8 +645,8 @@ static void start_network(Context *ctx, term pid, term ref, term config)
627645
//
628646
// Get the STA and AP config, if set
629647
//
630-
term sta_config = interop_kv_get_value_default(config, sta_atom, term_invalid_term(), ctx->global);
631-
term ap_config = interop_kv_get_value_default(config, ap_atom, term_invalid_term(), ctx->global);
648+
term sta_config = interop_kv_get_value_default(config, ATOM_STR("\x3", "sta"), term_invalid_term(), ctx->global);
649+
term ap_config = interop_kv_get_value_default(config, ATOM_STR("\x2", "ap"), term_invalid_term(), ctx->global);
632650
if (UNLIKELY(term_is_invalid_term(sta_config) && term_is_invalid_term(ap_config))) {
633651
ESP_LOGE(TAG, "Expected STA or AP configuration but got neither");
634652
term error = port_create_error_tuple(ctx, BADARG_ATOM);
@@ -725,10 +743,39 @@ static void start_network(Context *ctx, term pid, term ref, term config)
725743
wifi_mode_t wifi_mode = WIFI_MODE_NULL;
726744
if (!IS_NULL_PTR(sta_wifi_config) && !IS_NULL_PTR(ap_wifi_config)) {
727745
wifi_mode = WIFI_MODE_APSTA;
728-
} else if (!IS_NULL_PTR(sta_wifi_config)) {
729-
wifi_mode = WIFI_MODE_STA;
730-
} else {
746+
bool sta_atoms_ok = init_sta_cb_atoms(ctx->global);
747+
bool ap_atoms_ok = init_ap_cb_atoms(ctx->global);
748+
if (UNLIKELY(!sta_atoms_ok || !ap_atoms_ok)) {
749+
ESP_LOGE(TAG, "Unable to insert callback atoms");
750+
free(ap_wifi_config);
751+
free(sta_wifi_config);
752+
port_ensure_available(ctx, TUPLE_SIZE(2));
753+
term error = port_create_error_tuple(ctx, OUT_OF_MEMORY_ATOM);
754+
port_send_reply(ctx, pid, ref, error);
755+
return;
756+
}
757+
} else if (!IS_NULL_PTR(ap_wifi_config)) {
731758
wifi_mode = WIFI_MODE_AP;
759+
bool ap_atoms_ok = init_ap_cb_atoms(ctx->global);
760+
if (UNLIKELY(!ap_atoms_ok)) {
761+
ESP_LOGE(TAG, "Unable to insert callback atoms");
762+
free(ap_wifi_config);
763+
port_ensure_available(ctx, TUPLE_SIZE(2));
764+
term error = port_create_error_tuple(ctx, OUT_OF_MEMORY_ATOM);
765+
port_send_reply(ctx, pid, ref, error);
766+
return;
767+
}
768+
} else {
769+
wifi_mode = WIFI_MODE_STA;
770+
bool sta_atoms_ok = init_sta_cb_atoms(ctx->global);
771+
if (UNLIKELY(!sta_atoms_ok)) {
772+
ESP_LOGE(TAG, "Unable to insert callback atoms");
773+
free(sta_wifi_config);
774+
port_ensure_available(ctx, TUPLE_SIZE(2));
775+
term error = port_create_error_tuple(ctx, OUT_OF_MEMORY_ATOM);
776+
port_send_reply(ctx, pid, ref, error);
777+
return;
778+
}
732779
}
733780
if ((err = esp_wifi_set_mode(wifi_mode)) != ESP_OK) {
734781
ESP_LOGE(TAG, "Error setting wifi mode %d", err);
@@ -789,16 +836,16 @@ static void start_network(Context *ctx, term pid, term ref, term config)
789836
//
790837
// Set up simple NTP, if configured
791838
//
792-
maybe_set_sntp(interop_kv_get_value(config, sntp_atom, ctx->global), ctx->global);
839+
maybe_set_sntp(interop_kv_get_value(config, ATOM_STR("\x4", "sntp"), ctx->global), ctx->global);
793840

794841
//
795842
// Set the DHCP hostname, if STA mode is enabled
796843
//
797844
if (!IS_NULL_PTR(sta_wifi_config)) {
798-
set_dhcp_hostname(sta_wifi_interface, "STA", interop_kv_get_value(sta_config, dhcp_hostname_atom, ctx->global));
845+
set_dhcp_hostname(sta_wifi_interface, "STA", interop_kv_get_value(sta_config, ATOM_STR("\xD", "dhcp_hostname"), ctx->global));
799846
}
800847
if (!IS_NULL_PTR(ap_wifi_config)) {
801-
set_dhcp_hostname(ap_wifi_interface, "AP", interop_kv_get_value(ap_config, dhcp_hostname_atom, ctx->global));
848+
set_dhcp_hostname(ap_wifi_interface, "AP", interop_kv_get_value(ap_config, ATOM_STR("\xD", "dhcp_hostname"), ctx->global));
802849
}
803850

804851
//
@@ -861,9 +908,17 @@ static void get_sta_rssi(Context *ctx, term pid, term ref)
861908
return;
862909
}
863910
term rssi = term_from_int(sta_rssi);
911+
int rssi_atom_index = globalcontext_insert_atom(ctx->global, ATOM_STR("\x4", "rssi"));
912+
if (UNLIKELY(rssi_atom_index < 0)) {
913+
ESP_LOGE(TAG, "Failed to create 'rssi' atom!");
914+
port_ensure_available(ctx, tuple_reply_size);
915+
term error = port_create_error_tuple(ctx, OUT_OF_MEMORY_ATOM);
916+
port_send_reply(ctx, pid, ref, error);
917+
return;
918+
}
864919
// {Ref, {rssi, -25}}
865920
port_ensure_available(ctx, tuple_reply_size);
866-
term reply = port_create_tuple2(ctx, make_atom(ctx->global, ATOM_STR("\x4", "rssi")), rssi);
921+
term reply = port_create_tuple2(ctx, term_from_atom_index(rssi_atom_index), rssi);
867922
port_send_reply(ctx, pid, ref, reply);
868923
}
869924

0 commit comments

Comments
 (0)