-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Hostname unification 2: The Force Push Strikes Back #4893
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…hostname to "nw" key in config JSON - add new config key in "nw" for mDNS (bool) - remove `prepareHostname()` function - update mDNS calls - add hostname update for Ethernet - move WiFi configuration to cfg.json - rename LED and WiFi to Hardware and Network in settings - reorder network settings
WalkthroughThis PR centralizes hostname and mDNS handling: replaces cmDNS with hostName and adds mDNSenabled; updates resolution, MQTT, OTA, MDNS init/update, and captive portal. Config schema shifts hostname/mDNS to nw.*, adds defaults, and applies WiFi/Ethernet settings. UI pages and XML reflect new fields; utility APIs updated and hardened. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. ✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
wled00/mqtt.cpp (1)
1-243
: Remove leftover cmDNS reference and convert MDNS.queryHost calls to resolveHostname
- wled00/wled_eeprom.cpp:83: replace the
cmDNS
argument inwith the updated hostname storage key or removereadStringFromEEPROM(96, cmDNS, 32);cmDNS
entirely.- wled00/network.cpp:277: change
toclnt = MDNS.queryHost(mDNSname.c_str());
clnt = resolveHostname(mDNSname);
- wled00/mqtt.cpp:222: change
tomqttIP = MDNS.queryHost(mqttMDNS.c_str());mqttIP = resolveHostname(mqttMDNS);- wled00/bus_manager.cpp:733: change
toclnt = MDNS.queryHost(_hostname);clnt = resolveHostname(_hostname);- No
prepareHostname(...)
calls with a single argument remain.wled00/bus_manager.cpp (2)
728-737
: Use resolveHostname() to normalize names and avoid duplicated mDNS logic.This path doesn’t lowercase or strip “.local” like other code. Call the shared resolver for consistent behavior and implicit fallback to WiFi.hostByName.
Apply:
#ifdef ARDUINO_ARCH_ESP32 void BusNetwork::resolveHostname() { static unsigned long nextResolve = 0; if (Network.isConnected() && millis() > nextResolve && _hostname.length() > 0) { nextResolve = millis() + 600000; // resolve only every 10 minutes - IPAddress clnt; - if (mDNSenabled) clnt = MDNS.queryHost(_hostname); - else WiFi.hostByName(_hostname.c_str(), clnt); + IPAddress clnt = resolveHostname(_hostname, mDNSenabled); if (clnt != IPAddress()) _client = clnt; } } #endifIf resolveHostname() isn’t visible here, include its declaration:
#include "bus_wrapper.h" +#include "fcn_declare.h" // resolveHostname()
877-906
: Syntax error: missing semicolon after u++.This breaks compilation.
Apply:
- u++ + u++;wled00/set.cpp (1)
35-41
: Potentially inverted client SSID reconnect check.Unchanged code but likely wrong: it reconnects when SSID is equal. Consider flipping to reconnect only when changed or previously empty.
Proposed fix (context only):
- if (strlen(oldSSID) == 0 || !strncmp(multiWiFi[n].clientSSID, oldSSID, 32)) { + if (strlen(oldSSID) == 0 || strncmp(multiWiFi[n].clientSSID, oldSSID, 32) != 0) { forceReconnect = true; }
🧹 Nitpick comments (6)
wled00/data/style.css (2)
67-69
: Consolidate invalid-field styling and fix indentation to tabsYou now style input:invalid here and again on Line 82. Keep a single rule and use tabs per repo guideline for data web files.
Apply within this hunk:
-.err, input:invalid { - color: #f00; -} +.err, input:invalid { + color: #f00; +}
82-84
: Remove duplicate input:invalid ruleThis duplicates the styling added on Line 67. Drop the later block.
-input:invalid { - color: #f00; -}wled00/mqtt.cpp (1)
216-230
: Unify MQTT host resolution via resolveHostname() (honors mDNSenabled and normalizes .local).Avoid duplicating mDNS logic and string munging here. Use the new resolveHostname() helper so behavior matches the rest of the stack and you still fall back cleanly.
Apply:
#ifdef ARDUINO_ARCH_ESP32 - String mqttMDNS = mqttServer; - mqttMDNS.toLowerCase(); // make sure we have a lowercase hostname - int pos = mqttMDNS.indexOf(F(".local")); - if (pos > 0) mqttMDNS.remove(pos); // remove .local domain if present (and anything following it) - if (mDNSenabled && mqttMDNS.length() > 0 && mqttMDNS.indexOf('.') < 0) { // if mDNS is enabled and server does not have domain - mqttIP = MDNS.queryHost(mqttMDNS.c_str()); - if (mqttIP != IPAddress()) // if MDNS resolved the hostname - mqtt->setServer(mqttIP, mqttPort); - else - mqtt->setServer(mqttServer, mqttPort); - } else + IPAddress ip = resolveHostname(String(mqttServer), mDNSenabled); + if (ip != IPAddress()) { + mqtt->setServer(ip, mqttPort); + } else #endif mqtt->setServer(mqttServer, mqttPort);wled00/improv.cpp (1)
209-211
: snprintf size: pass full buffer size for clarity.Using sizeof(vString) instead of sizeof(vString)-1 is simpler; snprintf already reserves space for the NUL.
Apply:
- char vString[33]; - snprintf_P(vString, sizeof(vString)-1, PSTR("%s/%i"), versionString, VERSION); + char vString[33]; + snprintf_P(vString, sizeof(vString), PSTR("%s/%i"), versionString, VERSION);wled00/data/settings_ui.htm (1)
221-225
: Minor UX polish for “Device name”.Consider disabling autocorrect and spellcheck to avoid browser meddling.
Apply:
- Device name: <input type="text" name="DS" minlength="2" maxlength="32"><br> + Device name: <input type="text" name="DS" minlength="2" maxlength="32" autocomplete="off" spellcheck="false"><br>wled00/xml.cpp (1)
277-277
: Consider making the comment more actionable.The comment mentions using
WiFi.softAPmacAddress()
but doesn't explain when or why. Consider expanding it.- // WiFi.softAPmacAddress() for AP MAC address + // TODO: Consider displaying WiFi.softAPmacAddress() when AP is inactive to show AP MAC for reference
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (16)
wled00/bus_manager.cpp
(2 hunks)wled00/cfg.cpp
(4 hunks)wled00/data/settings.htm
(1 hunks)wled00/data/settings_ui.htm
(2 hunks)wled00/data/settings_wifi.htm
(5 hunks)wled00/data/style.css
(1 hunks)wled00/fcn_declare.h
(2 hunks)wled00/improv.cpp
(1 hunks)wled00/mqtt.cpp
(1 hunks)wled00/network.cpp
(3 hunks)wled00/set.cpp
(3 hunks)wled00/util.cpp
(1 hunks)wled00/wled.cpp
(4 hunks)wled00/wled.h
(1 hunks)wled00/wled_server.cpp
(1 hunks)wled00/xml.cpp
(3 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
wled00/{*.cpp,!(html_*)*.h}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use spaces (2 per level) for C++ source and header files
Files:
wled00/wled_server.cpp
wled00/fcn_declare.h
wled00/improv.cpp
wled00/mqtt.cpp
wled00/wled.cpp
wled00/set.cpp
wled00/bus_manager.cpp
wled00/wled.h
wled00/cfg.cpp
wled00/network.cpp
wled00/xml.cpp
wled00/util.cpp
wled00/data/**/*.{htm,html,css,js}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use tabs for indentation in web files (.htm/.html/.css/.js) under wled00/data
Files:
wled00/data/settings.htm
wled00/data/style.css
wled00/data/settings_ui.htm
wled00/data/settings_wifi.htm
🧠 Learnings (3)
📚 Learning: 2025-08-28T05:32:32.719Z
Learnt from: CR
PR: wled/WLED#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-28T05:32:32.719Z
Learning: Applies to wled00/html_*.h : Do not edit generated embedded web files (wled00/html_*.h)
Applied to files:
wled00/wled_server.cpp
wled00/set.cpp
wled00/wled.h
📚 Learning: 2025-04-26T12:51:04.993Z
Learnt from: KrX3D
PR: wled/WLED#4664
File: wled00/syslog.cpp:50-51
Timestamp: 2025-04-26T12:51:04.993Z
Learning: In the WLED codebase, syslog configuration variables (syslogHost, syslogPort, syslogProtocol, syslogFacility, syslogSeverity) are defined as global variables in wled.h and are accessed directly in the SyslogPrinter implementation, rather than being class members.
Applied to files:
wled00/wled.h
📚 Learning: 2025-04-18T22:27:58.634Z
Learnt from: KrX3D
PR: wled/WLED#4237
File: usermods/INA219_v2/INA219_v2.cpp:265-276
Timestamp: 2025-04-18T22:27:58.634Z
Learning: When implementing MQTT message handling in WLED usermods, use `strstr(topic, "/specific/path")` instead of `strcmp_P(topic, PSTR("/specific/path"))` to properly match topics that include the device prefix. The full MQTT topic typically follows the pattern `<mqttDeviceTopic>/specific/path`.
Applied to files:
wled00/cfg.cpp
🧬 Code graph analysis (5)
wled00/fcn_declare.h (3)
wled00/bus_manager.cpp (2)
resolveHostname
(728-737)resolveHostname
(728-728)wled00/network.cpp (2)
resolveHostname
(268-283)resolveHostname
(268-268)wled00/util.cpp (2)
prepareHostname
(131-149)prepareHostname
(131-131)
wled00/wled.cpp (1)
wled00/util.cpp (2)
prepareHostname
(131-149)prepareHostname
(131-131)
wled00/set.cpp (1)
wled00/util.cpp (4)
prepareHostname
(131-149)prepareHostname
(131-131)isAsterisksOnly
(151-159)isAsterisksOnly
(151-151)
wled00/cfg.cpp (1)
wled00/util.cpp (2)
prepareHostname
(131-149)prepareHostname
(131-131)
wled00/xml.cpp (1)
wled00/util.cpp (8)
printSetFormValue
(111-113)printSetFormValue
(111-111)printSetFormValue
(118-120)printSetFormValue
(118-118)printSetFormCheckbox
(108-110)printSetFormCheckbox
(108-108)printSetClassElementHTML
(122-124)printSetClassElementHTML
(122-122)
🔇 Additional comments (35)
wled00/data/settings.htm (1)
41-42
: LGTM: label updates only; routes unchangedThe button text changes read better and keep existing endpoints.
Also applies to: 47-47
wled00/fcn_declare.h (2)
257-257
: LGTM: resolveHostname() declaration matches intended behaviorDefault parameter keeps MDNS optional at call sites.
392-392
: prepareHostname callers correctly pass maxLen
All three usages in wled.cpp, set.cpp, and cfg.cpp now explicitly provide the maxLen argument; no further updates needed.wled00/mqtt.cpp (2)
216-230
: Heads-up: .local without mDNS will likely fail to resolve.If users set an MQTT server like foo.local while mDNS is disabled, AsyncMqttClient will try standard DNS (and fail). Consider warning in UI or documenting this, or automatically strip “.local” only when mDNSenabled is true.
221-221
: LGTM: mDNS gating.Switching the gate from cmDNS length to mDNSenabled is correct and matches the PR’s intent.
wled00/bus_manager.cpp (1)
31-31
: LGTM: new global gate.Extern mDNSenabled aligns this module with the new global switch.
wled00/improv.cpp (1)
212-213
: LGTM: prefer hostName when serverDescription is default.This matches the new hostname model and removes cmDNS coupling.
wled00/data/settings_ui.htm (1)
156-159
: LGTM: Save gating simplified.Dropping ST from the submit condition aligns with the UI changes that removed ST.
wled00/set.cpp (2)
85-86
: LGTM: bounds-safe AP password handling.Using isAsterisksOnly() and sizeof-based strlcpy is correct.
296-297
: LGTM: unsigned loop/index.Matches intent and avoids UB with negative comparisons.
wled00/xml.cpp (4)
193-193
: Good defensive programming with buffer size declaration.Adding an explicit buffer size for the local variable improves safety and clarity.
216-217
: LGTM! Hostname and mDNS settings properly migrated.The change from
cmDNS
tohostName
and addition ofmDNSenabled
checkbox aligns well with the PR's hostname unification objective.
270-273
: Good: Added null check for AP IP display.The addition of
apActive
check prevents displaying invalid AP information when the AP is not active, improving data accuracy.
273-273
: Buffer-safe formatting withsnprintf
.Using
snprintf
with explicit buffer size is the correct approach for safe string formatting.wled00/wled.cpp (4)
144-144
: Appropriate mDNS update gating on ESP8266.Good practice to only update mDNS when it's enabled, avoiding unnecessary processing.
426-427
: Hostname initialization logic looks correct.The code properly checks if hostname equals the default and generates a unique one if needed. The size calculation
sizeof(hostName)-1
ensures null termination space.
500-500
: ArduinoOTA hostname correctly updated.The OTA hostname now uses the unified
hostName
variable, maintaining consistency across the system.
713-717
: mDNS initialization properly gated.The mDNS service is correctly initialized only when
mDNSenabled
is true, with proper cleanup (MDNS.end()
) before reinitializing.wled00/util.cpp (2)
126-131
: Well-documented function signature change.The addition of comprehensive documentation explaining the function's behavior, constraints, and parameters is excellent. The
maxLen
parameter addition improves safety by preventing buffer overflows.
132-148
: Robust hostname generation with proper bounds checking.The implementation correctly:
- Respects the
maxLen
boundary- Generates a MAC-based default hostname
- Sanitizes
serverDescription
characters appropriately- Strips trailing hyphens
- Ensures null termination
wled00/network.cpp (4)
268-283
: New hostname resolution function is well-implemented.The function properly handles both mDNS and DNS resolution with appropriate fallbacks. Good defensive programming with network connectivity check.
285-291
: Verify the intent of the empty string logic.The function sets the string to empty if all MAC bytes are zero. This seems intentional but could be surprising behavior.
Is this intended to handle uninitialized or invalid MAC addresses? If so, consider adding a comment to clarify this behavior:
void fillMAC2Str(char *str, const uint8_t *mac) { sprintf_P(str, PSTR("%02x%02x%02x%02x%02x%02x"), MAC2STR(mac)); byte nul = 0; for (int i = 0; i < 6; i++) nul |= *mac++; // do we have 0 - if (!nul) str[0] = '\0'; // empty string + if (!nul) str[0] = '\0'; // empty string for all-zero MAC (uninitialized/invalid) }
407-407
: Preprocessor directive style consistency.Changed from
#if defined(...)
to#ifdef ...
for consistency.
417-417
: Ethernet hostname correctly set.The Ethernet hostname is now consistently set to the unified
hostName
variable.wled00/data/settings_wifi.htm (6)
6-6
: UI title updated to reflect broader scope.The change from "WiFi Settings" to "Network Settings" accurately reflects that this page now handles WiFi, Ethernet, and ESP-NOW configuration.
137-137
: Good use of callback for dynamic UI updates.Loading the settings script with a callback to
genUrl
ensures the UI updates after settings are loaded.
147-147
: Verify ESP-NOW and Ethernet incompatibility handling.The code disables Ethernet when ESP-NOW is enabled, but should we also disable ESP-NOW when Ethernet is selected?
Consider bidirectional enforcement:
function tE() { // keep the hidden input with MAC addresses, only toggle visibility of the list UI gId('rlc').style.display = d.Sf.RE.checked ? 'block' : 'none'; if (d.Sf.RE.checked) d.Sf.ETH.selectedIndex = 0; // disable Ethernet if ESPNOW is enabled }Also update the ETH select onchange:
-<select name="ETH" onchange="if(this.selectedIndex!=0)d.Sf.RE.checked=false;"> +<select name="ETH" onchange="if(this.selectedIndex!=0){d.Sf.RE.checked=false;tE();}">This ensures the ESP-NOW UI is properly hidden when Ethernet is selected.
180-183
: Live URL preview implementation is helpful.The
genUrl()
function provides immediate feedback to users about their hostname configuration and mDNS availability.
195-195
: Good hostname validation pattern.The pattern
[a-zA-Z0-9_\-]*
correctly restricts hostnames to valid characters. However, consider if empty hostnames should be allowed.Should we enforce a minimum length to prevent empty hostnames?
-<input type="text" name="CM" minlength="2" maxlength="32" pattern="[a-zA-Z0-9_\-]*" oninput="genUrl()"><br> +<input type="text" name="CM" minlength="2" maxlength="32" pattern="[a-zA-Z0-9_\-]+" required oninput="genUrl()"><br>
211-211
: Improved AP SSID validation.Good addition of the pattern attribute to restrict AP SSID to valid characters. The empty option for disabling AP is clearly indicated.
wled00/cfg.cpp (5)
160-169
: Good implementation of WiFi hostname configurationThe WiFi hostname is properly applied using the unified
hostName
variable for both ESP32 and ESP8266 platforms. This ensures consistency across different hardware platforms.
658-660
: MQTT default topic generation uses MAC-based patternThe automatic generation of MQTT client ID and device topic correctly uses the device's MAC address, which aligns well with the hostname unification approach where MAC-based identifiers are used as fallbacks.
871-879
: Serialization correctly implements new schemaThe serialization properly writes
serverDescription
toid.name
andhostName
tonw.name
, withmDNSenabled
written tonw.mdns
. This correctly implements the new unified hostname schema.
69-69
: Size usage is correct: alexaInvocationName[33]
sizeof(alexaInvocationName)
yields 33, matching its definition in wled00/wled.h.
163-164
: txPower is properly constrained and cast to wifi_power_t; no changes requiredThe value is clamped between WIFI_POWER_2dBm and WIFI_POWER_19_5dBm at line 157 before being passed to WiFi.setTxPower at line 164.
getStringFromJson(serverDescription, id["name"], sizeof(serverDescription)); | ||
// legacy behaviour | ||
getStringFromJson(hostName, id[F("mdns")], sizeof(hostName)); | ||
if (strlen(hostName) == 0) { | ||
mDNSenabled = false; // if no host name is set, disable mDNS | ||
prepareHostname(hostName, sizeof(hostName)-1); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential issue with legacy hostname migration logic
The current implementation reads from id["mdns"]
into hostName
for legacy compatibility, but if that field is empty, it disables mDNS and generates a new hostname. This could unexpectedly disable mDNS for users who had it enabled but didn't have an explicit hostname set in their legacy configuration.
Consider preserving the existing mDNS enabled state when migrating legacy configurations:
- // legacy behaviour
- getStringFromJson(hostName, id[F("mdns")], sizeof(hostName));
- if (strlen(hostName) == 0) {
- mDNSenabled = false; // if no host name is set, disable mDNS
- prepareHostname(hostName, sizeof(hostName)-1);
- }
+ // legacy behaviour - preserve existing mDNS state
+ const char* legacyHostname = id[F("mdns")];
+ if (legacyHostname != nullptr) {
+ getStringFromJson(hostName, legacyHostname, sizeof(hostName));
+ }
+ // Generate hostname if empty (from either legacy or new location)
+ if (strlen(hostName) == 0) {
+ prepareHostname(hostName, sizeof(hostName)-1);
+ }
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In wled00/cfg.cpp around lines 60 to 67, the legacy migration currently zeroes
mDNSenabled when id["mdns"] yields an empty hostName; instead, preserve the
existing mDNSenabled flag and only change it if the legacy config explicitly
indicates mDNS should be disabled. Update the logic to: read hostName from
id["mdns"], if hostName is empty call prepareHostname(...) to generate a
hostname but do not set mDNSenabled = false; only set mDNSenabled = false when
the legacy field explicitly signals mDNS should be disabled (or when another
explicit legacy flag indicates disablement).
CJSON(mDNSenabled, nw[F("mdns")]); | ||
getStringFromJson(hostName, nw["name"], sizeof(hostName)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Order of operations issue: mDNS flag might be overwritten
The mDNS enabled flag is set on line 74 from the new location nw["mdns"]
, but the legacy code on lines 62-66 might have already set it to false. This could cause the new value to override the legacy migration logic unexpectedly.
Consider reordering to handle legacy migration after reading the new values:
JsonObject nw = doc["nw"];
- CJSON(mDNSenabled, nw[F("mdns")]);
- getStringFromJson(hostName, nw["name"], sizeof(hostName));
+ // Read new format first
+ bool hasNewHostname = nw["name"] != nullptr;
+ if (hasNewHostname) {
+ getStringFromJson(hostName, nw["name"], sizeof(hostName));
+ CJSON(mDNSenabled, nw[F("mdns")]);
+ }
+ // Only apply legacy if new format not present
+ else if (id[F("mdns")] != nullptr) {
+ getStringFromJson(hostName, id[F("mdns")], sizeof(hostName));
+ // Don't force mDNS disabled for legacy configs
+ }
+ // Generate hostname if still empty
+ if (strlen(hostName) == 0) {
+ prepareHostname(hostName, sizeof(hostName)-1);
+ }
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In wled00/cfg.cpp around lines 62-75, the new mDNS flag is read from nw["mdns"]
on line 74 which can be unintentionally overridden by the earlier legacy
migration block (lines 62-66); move the legacy migration logic to run after you
read the new values (i.e., after the CJSON/getStringFromJson lines) or,
alternatively, keep reading nw["mdns"] first and then apply the legacy check to
explicitly override mDNSenabled when legacy storage indicates it should be
disabled; update the surrounding comment to clarify the order and ensure the
final mDNSenabled value reflects legacy migration when applicable.
strlcpy(hostName, request->arg(F("CM")).c_str(), sizeof(hostName)); | ||
if (strlen(hostName) == 0) prepareHostname(hostName, sizeof(hostName)-1); | ||
#ifdef ARDUINO_ARCH_ESP32 | ||
#ifdef WLED_USE_ETHERNET | ||
ETH.setHostname(hostName); | ||
#endif | ||
WiFi.setHostname(hostName); | ||
#else | ||
WiFi.hostname(hostName); | ||
#endif | ||
mDNSenabled = request->hasArg(F("MD")); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Always sanitize hostName and trigger reconnect when it changes.
Currently prepareHostname() runs only if CM is empty, so user-supplied values can slip through with illegal chars/length. Also, hostname changes should set forceReconnect so stacks pick them up.
Apply:
- strlcpy(hostName, request->arg(F("CM")).c_str(), sizeof(hostName));
- if (strlen(hostName) == 0) prepareHostname(hostName, sizeof(hostName)-1);
+ char oldHost[sizeof(hostName)]; strlcpy(oldHost, hostName, sizeof(oldHost));
+ strlcpy(hostName, request->arg(F("CM")).c_str(), sizeof(hostName));
+ // Sanitize and bound length regardless of user input
+ prepareHostname(hostName, sizeof(hostName)-1);
+ if (strcmp(oldHost, hostName) != 0) forceReconnect = true;
#ifdef ARDUINO_ARCH_ESP32
#ifdef WLED_USE_ETHERNET
ETH.setHostname(hostName);
#endif
WiFi.setHostname(hostName);
#else
WiFi.hostname(hostName);
#endif
mDNSenabled = request->hasArg(F("MD"));
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
strlcpy(hostName, request->arg(F("CM")).c_str(), sizeof(hostName)); | |
if (strlen(hostName) == 0) prepareHostname(hostName, sizeof(hostName)-1); | |
#ifdef ARDUINO_ARCH_ESP32 | |
#ifdef WLED_USE_ETHERNET | |
ETH.setHostname(hostName); | |
#endif | |
WiFi.setHostname(hostName); | |
#else | |
WiFi.hostname(hostName); | |
#endif | |
mDNSenabled = request->hasArg(F("MD")); | |
// Always sanitize hostName and trigger reconnect on change | |
char oldHost[sizeof(hostName)]; strlcpy(oldHost, hostName, sizeof(oldHost)); | |
strlcpy(hostName, request->arg(F("CM")).c_str(), sizeof(hostName)); | |
// Sanitize and bound length regardless of user input | |
prepareHostname(hostName, sizeof(hostName)-1); | |
if (strcmp(oldHost, hostName) != 0) forceReconnect = true; | |
#ifdef ARDUINO_ARCH_ESP32 | |
#ifdef WLED_USE_ETHERNET | |
ETH.setHostname(hostName); | |
#endif | |
WiFi.setHostname(hostName); | |
#else | |
WiFi.hostname(hostName); | |
#endif | |
mDNSenabled = request->hasArg(F("MD")); |
🤖 Prompt for AI Agents
In wled00/set.cpp around lines 66 to 77, always sanitize the user-supplied
hostName and trigger a reconnect when it changes: call prepareHostname(hostName,
sizeof(hostName)) (or an appropriate sanitizer/truncator) for both empty and
non-empty CM values instead of only when CM is empty, compare the sanitized
hostName against the current/previous hostname and if different set
forceReconnect = true so network stacks pick up the change, and then call the
appropriate platform hostname APIs (ETH/WiFi) with the sanitized value.
char oldSSID[33]; strcpy(oldSSID, apSSID); | ||
strlcpy(apSSID, request->arg(F("AS")).c_str(), 33); | ||
strlcpy(apSSID, request->arg(F("AS")).c_str(), sizeof(apSSID)); | ||
if (!strcmp(oldSSID, apSSID) && apActive) forceReconnect = true; | ||
apHide = request->hasArg(F("AH")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix AP SSID change detection (current logic flips condition).
The code forces reconnect when SSID is unchanged.
Apply:
- if (!strcmp(oldSSID, apSSID) && apActive) forceReconnect = true;
+ if (strcmp(oldSSID, apSSID) != 0 && apActive) forceReconnect = true;
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
char oldSSID[33]; strcpy(oldSSID, apSSID); | |
strlcpy(apSSID, request->arg(F("AS")).c_str(), 33); | |
strlcpy(apSSID, request->arg(F("AS")).c_str(), sizeof(apSSID)); | |
if (!strcmp(oldSSID, apSSID) && apActive) forceReconnect = true; | |
apHide = request->hasArg(F("AH")); | |
char oldSSID[33]; strcpy(oldSSID, apSSID); | |
strlcpy(apSSID, request->arg(F("AS")).c_str(), sizeof(apSSID)); | |
if (strcmp(oldSSID, apSSID) != 0 && apActive) forceReconnect = true; | |
apHide = request->hasArg(F("AH")); |
🤖 Prompt for AI Agents
In wled00/set.cpp around lines 79 to 82, the logic that sets forceReconnect is
inverted so it triggers when the SSID is unchanged; change the comparison to
detect a difference and only force reconnect when the SSID actually changed
while AP is active (i.e., replace the current equality check with a non-zero
strcmp/strncmp result combined with apActive) so forceReconnect is set only when
oldSSID and apSSID differ and apActive is true.
@@ -234,7 +234,7 @@ static bool captivePortal(AsyncWebServerRequest *request) | |||
if (!request->hasHeader(F("Host"))) return false; | |||
|
|||
String hostH = request->getHeader(F("Host"))->value(); | |||
if (!isIp(hostH) && hostH.indexOf(F("wled.me")) < 0 && hostH.indexOf(cmDNS) < 0 && hostH.indexOf(':') < 0) { | |||
if (!isIp(hostH) && hostH.indexOf(F("wled.me")) < 0 && hostH.indexOf(hostName) < 0 && hostH.indexOf(':') < 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Captive-portal false negative when hostName is empty; also consider case-insensitive match
If hostName == "", hostH.indexOf(hostName) returns 0 and bypasses the captive portal erroneously. Add an emptiness guard; optionally normalize case.
Minimal fix:
- if (!isIp(hostH) && hostH.indexOf(F("wled.me")) < 0 && hostH.indexOf(hostName) < 0 && hostH.indexOf(':') < 0) {
+ if (!isIp(hostH) && hostH.indexOf(F("wled.me")) < 0 && (hostName[0] == 0 || hostH.indexOf(hostName) < 0) && hostH.indexOf(':') < 0) {
(Optional) case-insensitive match:
- if (!isIp(hostH) && hostH.indexOf(F("wled.me")) < 0 && (hostName[0] == 0 || hostH.indexOf(hostName) < 0) && hostH.indexOf(':') < 0) {
+ String hostHL = hostH; hostHL.toLowerCase();
+ String ownHL = String(hostName); ownHL.toLowerCase();
+ if (!isIp(hostH) && hostHL.indexOf(F("wled.me")) < 0 && (ownHL.length() == 0 || hostHL.indexOf(ownHL) < 0) && hostH.indexOf(':') < 0) {
🤖 Prompt for AI Agents
In wled00/wled_server.cpp around line 237, the host check treats an empty
hostName as matching (hostH.indexOf(hostName) == 0), causing false negatives for
captive-portal; also matches are case-sensitive. Fix by first checking hostName
is non-empty before calling indexOf, and optionally normalize both hostH and
hostName to the same case (e.g., toLowerCase) before testing. Update the
conditional to require hostName.length() > 0 (or !hostName.isEmpty()) before
evaluating hostH.indexOf(hostName) and/or compare with case-insensitive
variants.
WLED_GLOBAL char hostName[33] _INIT(MDNS_NAME); // mDNS address (*.local, replaced by wled-XXXXXX if default is used) | ||
WLED_GLOBAL bool mDNSenabled _INIT(true); // use mDNS (default is true, can be changed in web UI) | ||
WLED_GLOBAL char apSSID[33] _INIT(""); // AP off by default (unless setup) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Good: unified hostName + mDNSenabled
Defaults and sizes look consistent with hostname usage elsewhere.
To ensure no leftover symbols cause build issues (per PR note about cmDNS in wled_eeprom.cpp), run:
🏁 Script executed:
#!/bin/bash
# Find any remaining cmDNS references
rg -nP '\bcmDNS\b' -C2
Length of output: 392
Update EEPROM handlers to use hostName
instead of residual cmDNS
In wled00/wled_eeprom.cpp (around line 83), the EEPROM read/write calls still reference cmDNS
. Replace these with hostName
(adjusting the size parameter to 33) to match the new declaration and avoid undefined-symbol build errors.
Hi, as promised, the cleaner version. See #4751 and #4888.
One thing: there's still one
cmDNS
reference inwled00/wled_eeprom.cpp:83:29:
. This did not break compilation for me, probably due toWLED_ADD_EEPROM_SUPPORT
not being defined. I'm not sure what the correct fix would be.Summary by CodeRabbit