Skip to content

Commit

Permalink
cm_networking: Replace non-reentrant ntoa functions
Browse files Browse the repository at this point in the history
Also create a new tools header for ntoa helper functions.
  • Loading branch information
MattiasTF committed Nov 20, 2024
1 parent 22b2fce commit 1e75c08
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 18 deletions.
17 changes: 11 additions & 6 deletions software/src/modules/cm_networking/cm_mdns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "event_log_prefix.h"
#include "module_dependencies.h"
#include "tools.h"
#include "tools/net.h"
#include "cool_string.h"

void CMNetworking::setup()
Expand Down Expand Up @@ -107,7 +108,8 @@ void CMNetworking::resolve_hostname(uint8_t charger_idx)

std::lock_guard<std::mutex> lock{dns_resolve_mutex};
if (resolve_state[charger_idx] != RESOLVE_STATE_RESOLVED || dest_addrs[charger_idx].sin_addr.s_addr != in) {
const char *ip_str = ipaddr_ntoa(&ip);
char ip_str[16];
tf_ip4addr_ntoa(&ip, ip_str, sizeof(ip_str));
// Show resolved hostname only if it wasn't already an IP
if (strcmp(this->hosts[charger_idx], ip_str) != 0) {
logger.printfln("Resolved %s to %s", this->hosts[charger_idx], ip_str);
Expand Down Expand Up @@ -232,7 +234,9 @@ void CMNetworking::resolve_via_mdns(mdns_result_t *entry)
if (host == entry->hostname) {
this->dest_addrs[i].sin_addr.s_addr = entry->addr->addr.u_addr.ip4.addr;
if (this->resolve_state[i] != RESOLVE_STATE_RESOLVED) {
logger.printfln("Resolved %s to %s (via mDNS scan)", this->hosts[i], ipaddr_ntoa((const ip_addr *)&entry->addr->addr));
char addr_str[16];
tf_ip4addr_ntoa(&entry->addr->addr, addr_str, sizeof(addr_str));
logger.printfln("Resolved %s to %s (via mDNS scan)", this->hosts[i], addr_str);
}
this->resolve_state[i] = RESOLVE_STATE_RESOLVED;
}
Expand Down Expand Up @@ -275,10 +279,11 @@ void CMNetworking::add_scan_result_entry(mdns_result_t *entry, TFJsonSerializer
json.addObject();
json.addMemberString("hostname", entry->hostname);

char buf[32] = "[no_address]";
if (entry->addr && entry->addr->addr.type == IPADDR_TYPE_V4)
esp_ip4addr_ntoa(&entry->addr->addr.u_addr.ip4, buf, ARRAY_SIZE(buf));
json.addMemberString("ip", buf);
char addr_str[32] = "[no_address]";
if (entry->addr && entry->addr->addr.type == IPADDR_TYPE_V4) {
tf_ip4addr_ntoa(&entry->addr->addr, addr_str, sizeof(addr_str));
}
json.addMemberString("ip", addr_str);

json.addMemberString("display_name", display_name);
json.addMemberNumber("error", error);
Expand Down
37 changes: 25 additions & 12 deletions software/src/modules/cm_networking/cm_protocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "event_log_prefix.h"
#include "module_dependencies.h"
#include "tools.h"
#include "tools/net.h"
#include "modules/meters/meter_defs.h"

int CMNetworking::create_socket(uint16_t port, bool blocking)
Expand Down Expand Up @@ -300,16 +301,23 @@ void CMNetworking::register_manager(const char *const *const hosts,

// Don't log in the first 20 seconds after startup: We are probably still resolving hostnames.
if (charger_idx == -1) {
if (deadline_elapsed(20000))
logger.printfln("Received packet from unknown %s. Is the config complete?", inet_ntoa(source_addr.sin_addr));
if (deadline_elapsed(20_s)) {
char source_str[16];
tf_ip4addr_ntoa(&source_addr, source_str, sizeof(source_str));

logger.printfln("Received packet from unknown %s. Is the config complete?", source_str);
}
return;
}

String validation_error = validate_state_packet_header(&state_pkt, len);
if (!validation_error.isEmpty()) {
char source_str[16];
tf_ip4addr_ntoa(&source_addr, source_str, sizeof(source_str));

logger.printfln("Received state packet from %s (%s) (%i bytes) failed validation: %s",
charge_manager.get_charger_name(charger_idx),
inet_ntoa(source_addr.sin_addr),
source_str,
len,
validation_error.c_str());
if (manager_error_callback) {
Expand All @@ -319,9 +327,12 @@ void CMNetworking::register_manager(const char *const *const hosts,
}

if (seq_num_invalid(state_pkt.header.seq_num, last_seen_seq_num[charger_idx])) {
char source_str[16];
tf_ip4addr_ntoa(&source_addr, source_str, sizeof(source_str));

logger.printfln("Received stale (out of order?) state packet from %s (%s). Last seen seq_num is %u, Received seq_num is %u",
charge_manager.get_charger_name(charger_idx),
inet_ntoa(source_addr.sin_addr),
source_str,
last_seen_seq_num[charger_idx],
state_pkt.header.seq_num);
return;
Expand All @@ -330,9 +341,12 @@ void CMNetworking::register_manager(const char *const *const hosts,
last_seen_seq_num[charger_idx] = state_pkt.header.seq_num;

if (!CM_STATE_FLAGS_MANAGED_IS_SET(state_pkt.v1.state_flags)) {
char source_str[16];
tf_ip4addr_ntoa(&source_addr, source_str, sizeof(source_str));

logger.printfln("%s (%s) reports managed is not activated!",
charge_manager.get_charger_name(charger_idx),
inet_ntoa(source_addr.sin_addr));
source_str);
if (manager_error_callback) {
manager_error_callback(charger_idx, CM_NETWORKING_ERROR_NOT_MANAGED);
}
Expand Down Expand Up @@ -438,10 +452,9 @@ void CMNetworking::register_client(const std::function<void(uint16_t, bool, int8

String validation_error = validate_command_packet_header(&command_pkt, len);
if (!validation_error.isEmpty()) {
logger.printfln("Received command packet from %s (%i bytes) failed validation: %s",
inet_ntoa(((struct sockaddr_in*)&from_addr)->sin_addr),
len,
validation_error.c_str());
char from_str[16];
tf_ip4addr_ntoa(&from_addr, from_str, sizeof(from_str));
logger.printfln("Received command packet from %s (%i bytes) failed validation: %s", from_str, len, validation_error.c_str());
return;
}

Expand All @@ -455,8 +468,8 @@ void CMNetworking::register_client(const std::function<void(uint16_t, bool, int8
if (memcmp(&this->manager_addr, &from_addr, from_addr.s2_len) != 0) {
char manager_str[16];
char from_str[16];
inet_ntoa_r(((struct sockaddr_in*)&manager_addr)->sin_addr, manager_str, sizeof(manager_str));
inet_ntoa_r(((struct sockaddr_in*)&from_addr )->sin_addr, from_str, sizeof(from_str ));
tf_ip4addr_ntoa(&this->manager_addr, manager_str, sizeof(manager_str));
tf_ip4addr_ntoa(&from_addr, from_str, sizeof(from_str ));

if (deadline_elapsed(this->last_manager_addr_change + 1_m)) {
if (this->manager_addr.s2_len > 0) {
Expand All @@ -483,7 +496,7 @@ void CMNetworking::register_client(const std::function<void(uint16_t, bool, int8
if (!this->manager_addr_valid && this->manager_addr.s2_len > 0) {
if (deadline_elapsed(this->last_manager_addr_change + 1_m)) {
char manager_str[16];
inet_ntoa_r(((struct sockaddr_in*)&manager_addr)->sin_addr, manager_str, sizeof(manager_str));
tf_ip4addr_ntoa(&this->manager_addr, manager_str, sizeof(manager_str));

logger.printfln("Accepting manager address %s", manager_str);
this->manager_addr_valid = true;
Expand Down
76 changes: 76 additions & 0 deletions software/src/tools/net.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/* esp32-firmware
* Copyright (C) 2024 Mattias Schäffersmann <[email protected]>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/

#pragma once

#include "esp_netif_ip_addr.h"
#include "lwip/ip_addr.h"
#include "lwip/sockets.h"

#if defined(__GNUC__)
#pragma GCC diagnostic push
#include "gcc_warnings.h"

// Cast from sockaddr to sockaddr_in increases required alignment
#pragma GCC diagnostic ignored "-Wcast-align"
#endif

// lwIP ipaddr

extern inline void tf_ip4addr_ntoa(const ip4_addr_t *addr, char *buf, int buflen) {
ip4addr_ntoa_r(addr, buf, buflen);
}

extern inline void tf_ip4addr_ntoa(const ip_addr_t *addr, char *buf, int buflen) {
tf_ip4addr_ntoa(&addr->u_addr.ip4, buf, buflen);
}

// lwIP inaddr

extern inline void tf_ip4addr_ntoa(const struct in_addr *addr, char *buf, int buflen) {
tf_ip4addr_ntoa(reinterpret_cast<const ip4_addr_t *>(addr), buf, buflen);
}

// lwIP sockaddr

extern inline void tf_ip4addr_ntoa(const struct sockaddr_in *addr, char *buf, int buflen) {
tf_ip4addr_ntoa(&addr->sin_addr, buf, buflen);
}

extern inline void tf_ip4addr_ntoa(const struct sockaddr *addr, char *buf, int buflen) {
tf_ip4addr_ntoa(reinterpret_cast<const struct sockaddr_in *>(addr), buf, buflen);
}

extern inline void tf_ip4addr_ntoa(const struct sockaddr_storage *addr, char *buf, int buflen) {
tf_ip4addr_ntoa(reinterpret_cast<const struct sockaddr_in *>(addr), buf, buflen);
}

// ESP netif IP adresses

extern inline void tf_ip4addr_ntoa(const esp_ip4_addr_t *addr, char *buf, int buflen) {
tf_ip4addr_ntoa(reinterpret_cast<const ip4_addr_t *>(addr), buf, buflen);
}

extern inline void tf_ip4addr_ntoa(const esp_ip_addr_t *addr, char *buf, int buflen) {
tf_ip4addr_ntoa(reinterpret_cast<const ip_addr_t *>(addr), buf, buflen);
}

#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif

0 comments on commit 1e75c08

Please sign in to comment.