Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion wled00/fcn_declare.h
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,8 @@ size_t printSetFormValue(Print& settingsScript, const char* key, int val);
size_t printSetFormValue(Print& settingsScript, const char* key, const char* val);
size_t printSetFormIndex(Print& settingsScript, const char* key, int index);
size_t printSetClassElementHTML(Print& settingsScript, const char* key, const int index, const char* val);
void prepareHostname(char* hostname);
void getWLEDhostname(char* hostname, size_t maxLen, bool preferMDNS=false); // maxLen = hostname buffer size including \0; if preferMDNSname=true, use mdns name (sanitized)
void prepareHostname(char* hostname, size_t maxLen); // legacy function - not recommended for new code
[[gnu::pure]] bool isAsterisksOnly(const char* str, byte maxLen);
bool requestJSONBufferLock(uint8_t moduleID=JSON_LOCK_UNKNOWN);
void releaseJSONBufferLock();
Expand Down
5 changes: 2 additions & 3 deletions wled00/network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -413,9 +413,8 @@ void WiFiEvent(WiFiEvent_t event)
if (!apActive) {
WiFi.disconnect(true); // disable WiFi entirely
}
// convert the "serverDescription" into a valid DNS hostname (alphanumeric)
char hostname[64];
prepareHostname(hostname);
char hostname[64] = {'\0'}; // any "hostname" within a Fully Qualified Domain Name (FQDN) must not exceed 63 characters
getWLEDhostname(hostname, sizeof(hostname), true); // create DNS name based on mDNS name if set, or fall back to standard WLED server name
ETH.setHostname(hostname);
showWelcomePage = false;
break;
Expand Down
73 changes: 55 additions & 18 deletions wled00/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,28 +127,65 @@ size_t printSetClassElementHTML(Print& settingsScript, const char* key, const in
}



void prepareHostname(char* hostname)
{
sprintf_P(hostname, PSTR("wled-%*s"), 6, escapedMac.c_str() + 6);
const char *pC = serverDescription;
unsigned pos = 5; // keep "wled-"
while (*pC && pos < 24) { // while !null and not over length
if (isalnum(*pC)) { // if the current char is alpha-numeric append it to the hostname
hostname[pos] = *pC;
pos++;
} else if (*pC == ' ' || *pC == '_' || *pC == '-' || *pC == '+' || *pC == '!' || *pC == '?' || *pC == '*') {
hostname[pos] = '-';
pos++;
// in-place hostname sanitizer, extracted from prepareHostname()
static void sanitizeHostname(char* hostname, size_t maxLen) {
if (hostname == nullptr || maxLen < 1 || strlen(hostname) < 1) return;

char *pC = hostname;
unsigned pos = 0;
while (*pC && pos < maxLen) {
char c = *pC;
if (isalnum((unsigned char)c)) {
hostname[pos++] = c;
} else if (c == ' ' || c == '_' || c == '-' || c == '+' || c == '!' || c == '?' || c == '*') { // convert certain characters to hyphens
if (pos > 0 && hostname[pos -1] != '-') hostname[pos++] = '-'; // keep single non-leading hyphens only
}
// else do nothing - no leading hyphens and do not include hyphens for all other characters.
// else: drop any character not valid in a DNS hostname label
pC++;
}
//last character must not be hyphen
if (pos > 5) {
while (pos > 4 && hostname[pos -1] == '-') pos--;
hostname[pos] = '\0'; // terminate string (leave at least "wled")
// Hostname must not end with a hyphen.
while (pos > 0 && hostname[pos -1] == '-') pos--;
hostname[min(pos, maxLen-1)] = '\0'; // terminate string
}

/*
* Stores sanitized hostname into buffer provided by caller
* maxLen = hostname buffer size including \0
* preferMDNSname -> use mDNS name if set, otherwise fall back to WLED "server description" name (legacy behaviour)
*/
void getWLEDhostname(char* hostname, size_t maxLen, bool preferMDNS) {
if (maxLen <= 6) { strlcpy(hostname, "wled", maxLen); return; } // buffer too small (should not happen)
if (preferMDNS && (strlen(cmDNS) > 0) && (strcmp_P(cmDNS, PSTR(DEFAULT_MDNS_NAME)) != 0)) { // avoid "x" = not set (use wled-MAC)
strlcpy(hostname, cmDNS, maxLen);
sanitizeHostname(hostname, maxLen); // sanitize cmDNS name
if (strlen(hostname) < 1) { // if result is empty -> fall back to wled-MAC
snprintf_P(hostname, maxLen, PSTR("wled-%*s"), 6, escapedMac.c_str() + 6);
hostname[maxLen -1] = '\0'; // ensure string termination
}
} else {
prepareHostname(hostname, maxLen); // use legacy hostname based on "server description" - already sanitized
}
DEBUG_PRINTF_P(PSTR("getWLEDHostname: '%s'\n"), hostname);
}

/* Legacy hostname construction:
* Start with "wled-" + serverDescription as suffix.
* Sanitize only the suffix (always keep wled- prefix intact).
* If the sanitized suffix ends up empty, fall back to wled-<mac>.
*/
void prepareHostname(char* hostname, size_t maxLen)
{
if (maxLen <= 6) { strlcpy(hostname, "wled", maxLen); return; } // buffer too small (should not happen)
if (strncasecmp_P(serverDescription, PSTR("wled"), 4) == 0) // avoid wled-WLED-... as a hostname
strlcpy(hostname, serverDescription, maxLen);
else
snprintf_P(hostname, maxLen, PSTR("wled-%s"), serverDescription);
hostname[maxLen -1] = '\0'; // ensure string termination

size_t sanOffset = hostname[4] != '-' ? 4 : 5; // ensure that "WLED foo" and "WLED!foo" get sanitized
sanitizeHostname(hostname+sanOffset, maxLen-sanOffset); // sanitize name, keep "wled-" intact
if (strlen(hostname) <= sanOffset)
snprintf_P(hostname, maxLen, PSTR("wled-%*s"), 6, escapedMac.c_str() + 6); // fallback to wled-MAC if sanitization cleaned everything
}


Expand Down
25 changes: 18 additions & 7 deletions wled00/wled.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -507,8 +507,12 @@ void WLED::setup()
#ifndef ESP8266
WiFi.setScanMethod(WIFI_ALL_CHANNEL_SCAN);
WiFi.persistent(true); // storing credentials in NVM fixes boot-up pause as connection is much faster, is disabled after first connection
// ESP32 DNS name must be set before the first connection to the DHCP server; otherwise, the default ESP name (such as "esp32s3-267D0C") will be used.
char hostname[64] = {'\0'};
getWLEDhostname(hostname, sizeof(hostname), true); // create DNS name based on mDNS name if set, or fall back to standard WLED server name
WiFi.setHostname(hostname);
#else
WiFi.persistent(false); // on ES8266 using NVM for wifi config has no benefit of faster connection
WiFi.persistent(false); // on ESP8266 using NVM for wifi config has no benefit of faster connection
#endif
WiFi.onEvent(WiFiEvent);
WiFi.mode(WIFI_STA); // enable scanning
Expand Down Expand Up @@ -691,6 +695,18 @@ void WLED::initConnection()
WiFi.setPhyMode(force802_3g ? WIFI_PHY_MODE_11G : WIFI_PHY_MODE_11N);
#endif

char hostname[64] = {'\0'};
getWLEDhostname(hostname, sizeof(hostname), true); // create DNS name based on mDNS name if set, or fall back to standard WLED server name

#ifdef ARDUINO_ARCH_ESP32
// Reset mode to NULL to force a full STA mode transition, so that WiFi.mode(WIFI_STA) below actually applies the hostname (and TX power, etc.).
// This is required on reconnects when mode is already WIFI_STA.
WiFi.mode(WIFI_MODE_NULL);
apActive = false; // the AP is physically torn down by WIFI_MODE_NULL
delay(5); // give the WiFi stack time to complete the mode transition
WiFi.setHostname(hostname);
#endif

if (multiWiFi[selectedWiFi].staticIP != 0U && multiWiFi[selectedWiFi].staticGW != 0U) {
WiFi.config(multiWiFi[selectedWiFi].staticIP, multiWiFi[selectedWiFi].staticGW, multiWiFi[selectedWiFi].staticSN, dnsAddress);
} else {
Expand Down Expand Up @@ -718,10 +734,6 @@ void WLED::initConnection()

DEBUG_PRINTF_P(PSTR("Connecting to %s...\n"), multiWiFi[selectedWiFi].clientSSID);

// convert the "serverDescription" into a valid DNS hostname (alphanumeric)
char hostname[25];
prepareHostname(hostname);

#ifdef WLED_ENABLE_WPA_ENTERPRISE
if (multiWiFi[selectedWiFi].encryptionType == WIFI_ENCRYPTION_TYPE_PSK) {
DEBUG_PRINTLN(F("Using PSK"));
Expand Down Expand Up @@ -774,8 +786,7 @@ void WLED::initConnection()
#ifdef ARDUINO_ARCH_ESP32
WiFi.setTxPower(wifi_power_t(txPower));
WiFi.setSleep(!noWifiSleep);
WiFi.setHostname(hostname);
#else
#else // ESP8266 accepts a hostname set after WiFi interface initialization
wifi_set_sleep_type((noWifiSleep) ? NONE_SLEEP_T : MODEM_SLEEP_T);
WiFi.hostname(hostname);
#endif
Expand Down
Loading