Skip to content

Commit

Permalink
[timeouts] Improve response when hosts are not reachable (#939)
Browse files Browse the repository at this point in the history
See #922 and #847

Problem with DNS resolve is that it is quite slow when resulting in a failure and it tends to keep the ESP occupied and make it unresponsive.

Changed the way it is connecting to a controller.
Not sure if http requests are still OK, maybe we should make an exception for those when selected to use DNS.
  • Loading branch information
TD-er authored and psy0rz committed Feb 25, 2018
1 parent aed566b commit 54628bf
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 85 deletions.
14 changes: 14 additions & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@

[common]
build_flags = -D BUILD_GIT='"${env.TRAVIS_TAG}"'
lib_deps = ESP8266Ping


#normal version with stable plugins, 1024k version
[env:normal_ESP8266_1024]
platform = espressif8266@1.5.0
lib_deps = ${common.lib_deps}
framework = arduino
board = esp12e
upload_speed=460800
Expand All @@ -35,6 +37,7 @@ build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.1m128.ld

[env:normal_ESP8266_1024_DOUT]
platform = espressif8266@1.5.0
lib_deps = ${common.lib_deps}
board_flash_mode = dout
framework = arduino
board = esp12e
Expand All @@ -45,6 +48,7 @@ build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.1m128.ld
#normal version with stable plugins, 4096k version
[env:normal_ESP8266_4096]
platform = espressif8266@1.5.0
lib_deps = ${common.lib_deps}
framework = arduino
board = esp12e
upload_speed=460800
Expand All @@ -54,6 +58,7 @@ build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.4m1m.ld
#normal version with stable plugins, 4096k version for esp8285
[env:normal_ESP8285_1024]
platform = espressif8266@1.5.0
lib_deps = ${common.lib_deps}
framework = arduino
board = esp8285
upload_speed=460800
Expand All @@ -64,6 +69,7 @@ build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.1m128.ld -DESP8285
#version with additional plugins (and dependend code) that are in test-stadium 1024k
[env:test_ESP8266_1024]
platform = espressif8266@1.5.0
lib_deps = ${common.lib_deps}
framework = arduino
board = esp12e
upload_speed=460800
Expand All @@ -72,13 +78,15 @@ build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.1m128.ld -D PLUGIN_BUILD
#version with additional plugins (and dependend code) that are in test-stadium 4096k
[env:test_ESP8266_4096]
platform = espressif8266@1.5.0
lib_deps = ${common.lib_deps}
framework = arduino
board = esp12e
upload_speed=460800
build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.4m1m.ld -D PLUGIN_BUILD_TESTING

[env:test_ESP8266_4096_VCC]
platform = espressif8266@1.5.0
lib_deps = ${common.lib_deps}
framework = arduino
board = esp12e
upload_speed=460800
Expand All @@ -87,6 +95,7 @@ build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.4m1m.ld -D PLUGIN_BUILD_
#version with additional plugins (and dependend code) that are in test-stadium 4096k for esp8285
[env:test_ESP8285_1024]
platform = espressif8266@1.5.0
lib_deps = ${common.lib_deps}
framework = arduino
board = esp8285
upload_speed=460800
Expand All @@ -96,6 +105,7 @@ build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.1m128.ld -D PLUGIN_BUILD
#version with additional plugins (and dependend code) that is in development (probably broken or incomplete) 1024k
[env:dev_ESP8266_1024]
platform = espressif8266@1.5.0
lib_deps = ${common.lib_deps}
framework = arduino
board = esp12e
upload_speed=460800
Expand All @@ -104,6 +114,7 @@ build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.1m128.ld -D PLUGIN_BUILD
#version with additional plugins (and dependend code) that is in development (probably broken or incomplete) 4096k
[env:dev_ESP8266_4096]
platform = espressif8266@1.5.0
lib_deps = ${common.lib_deps}
framework = arduino
board = esp12e
upload_speed=460800
Expand All @@ -112,6 +123,7 @@ build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.4m1m.ld -D PLUGIN_BUILD_
#version with additional plugins (and dependend code) that is in development (probably broken or incomplete) 4096k for esp8285
[env:dev_ESP8285_1024]
platform = espressif8266@1.5.0
lib_deps = ${common.lib_deps}
framework = arduino
board = esp8285
upload_speed=460800
Expand All @@ -122,6 +134,7 @@ build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.1m128.ld -D PLUGIN_BUILD
#special patched version for PUYA flash chips, see https://github.com/letscontrolit/ESPEasy/issues/650
[env:dev_ESP8266PUYA_1024]
platform = espressif8266@1.5.0
lib_deps = ${common.lib_deps}
framework = arduino
board = esp12e
upload_speed=460800
Expand All @@ -130,6 +143,7 @@ build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.1m128.ld -D PLUGIN_BUILD
#special patched version for PUYA flash chips, see https://github.com/letscontrolit/ESPEasy/issues/650
[env:dev_ESP8266PUYA_1024_VCC]
platform = espressif8266@1.5.0
lib_deps = ${common.lib_deps}
framework = arduino
board = esp12e
upload_speed=460800
Expand Down
8 changes: 4 additions & 4 deletions src/Controller.ino
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,12 @@ void callback(char* c_topic, byte* b_payload, unsigned int length) {
\*********************************************************************************************/
bool MQTTConnect(int controller_idx)
{
if (!WiFiConnected(100)) return false;
if (MQTTclient.connected())
MQTTclient.disconnect();
ControllerSettingsStruct ControllerSettings;
LoadControllerSettings(controller_idx, (byte*)&ControllerSettings, sizeof(ControllerSettings));
if (!ControllerSettings.checkHostReachable(true))
return false;
if (MQTTclient.connected())
MQTTclient.disconnect();
if (ControllerSettings.UseDNS) {
MQTTclient.setServer(ControllerSettings.getHost().c_str(), ControllerSettings.Port);
} else {
Expand Down Expand Up @@ -226,7 +227,6 @@ boolean MQTTpublish(int controller_idx, const char* topic, const char* payload,
if (MQTTclient.publish(topic, payload, retained))
return true;
addLog(LOG_LEVEL_DEBUG, F("MQTT : publish failed"));
MQTTConnect(controller_idx);
return false;
}

Expand Down
78 changes: 67 additions & 11 deletions src/ESPEasy.ino
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@
#include "ESPEasyTimeTypes.h"
#include "lwip/tcp_impl.h"
#include <ESP8266WiFi.h>
#include <ESP8266Ping.h>
#include <DNSServer.h>
#include <WiFiUdp.h>
#include <ESP8266WebServer.h>
Expand Down Expand Up @@ -433,7 +434,10 @@ ESP8266WebServer WebServer(80);
// udp protocol stuff (syslog, global sync, node info list, ntp time)
WiFiUDP portUDP;

// Forward declarations.
bool WiFiConnected(uint32_t timeout_ms);
bool hostReachable(const IPAddress& ip);
bool hostReachable(const String& hostname);

extern "C" {
#include "spi_flash.h"
Expand Down Expand Up @@ -614,24 +618,55 @@ struct ControllerSettingsStruct
return getIP().toString();
}

boolean connectToHost(WiFiClient &client) {
if (!WiFiConnected(100)) {
void setHostname(const String& controllerhostname) {
strncpy(HostName, controllerhostname.c_str(), sizeof(HostName));
updateIPcache();
}

boolean checkHostReachable(bool quick) {
if (!WiFiConnected(10)) {
return false; // Not connected, so no use in wasting time to connect to a host.
}
if (quick) return true;
if (UseDNS) {
return client.connect(HostName, Port);
if (!updateIPcache()) {
return false;
}
}
return hostReachable(getIP());
}

boolean connectToHost(WiFiClient &client) {
if (!checkHostReachable(true)) {
return false; // Host not reachable
}
return client.connect(getIP(), Port);
byte retry = 2;
bool connected = false;
while (retry > 0 && !connected) {
--retry;
connected = client.connect(getIP(), Port);
if (connected) return true;
if (!checkHostReachable(false))
return false;
}
return false;
}

int beginPacket(WiFiUDP &client) {
if (!WiFiConnected(100)) {
return 0; // Not connected, so no use in wasting time to connect to a host.
if (!checkHostReachable(true)) {
return 0; // Host not reachable
}
if (UseDNS) {
return client.beginPacket(HostName, Port);
byte retry = 2;
int connected = 0;
while (retry > 0 && !connected) {
--retry;
connected = client.beginPacket(getIP(), Port);
if (connected != 0) return connected;
if (!checkHostReachable(false))
return false;
delay(10);
}
return client.beginPacket(getIP(), Port);
return false;
}

String getHostPortString() const {
Expand All @@ -640,6 +675,22 @@ struct ControllerSettingsStruct
result += Port;
return result;
}

private:
bool updateIPcache() {
if (!UseDNS) {
return true;
}
IPAddress tmpIP;
if (WiFi.hostByName(HostName, tmpIP)) {
for (byte x = 0; x < 4; x++) {
IP[x] = tmpIP[x];
}
return true;
}
return false;
}

};

struct NotificationSettingsStruct
Expand Down Expand Up @@ -921,6 +972,7 @@ unsigned long timer20ms;
unsigned long timer1s;
unsigned long timerwd;
unsigned long timermqtt;
unsigned long timermqtt_interval;
unsigned long lastSend;
unsigned long lastWeb;
unsigned int NC_Count = 0;
Expand Down Expand Up @@ -1121,6 +1173,7 @@ void setup()
timer1s = 0; // timer for periodic actions once per/sec
timerwd = 0; // timer for watchdog once per 30 sec
timermqtt = 0; // Timer for the MQTT keep alive loop.
timermqtt_interval = 250; // Interval for checking MQTT

PluginInit();
CPluginInit();
Expand Down Expand Up @@ -1231,14 +1284,17 @@ void loop()

if (timeOutReached(timermqtt)) {
// MQTT_KEEPALIVE = 15 seconds.
timermqtt = millis() + 250;
timermqtt = millis() + timermqtt_interval;
//dont do this in backgroundtasks(), otherwise causes crashes. (https://github.com/letscontrolit/ESPEasy/issues/683)
int enabledMqttController = firstEnabledMQTTController();
if (enabledMqttController >= 0) {
if (!MQTTclient.loop()) {
if (!MQTTCheck(enabledMqttController)) {
// Check failed, no need to retry it immediately.
timermqtt = millis() + 500;
if (timermqtt_interval < 2000)
timermqtt_interval += 250;
} else {
timermqtt_interval = 250;
}
}
}
Expand Down
30 changes: 27 additions & 3 deletions src/Networking.ino
Original file line number Diff line number Diff line change
Expand Up @@ -739,10 +739,10 @@ void SSDP_update() {
}
}

// Check WiFi connection. Maximum timeout 2000 msec.
// Check WiFi connection. Maximum timeout 500 msec.
bool WiFiConnected(uint32_t timeout_ms) {
uint32_t timer = millis() + (timeout_ms > 2000 ? 2000 : timeout_ms);
uint32_t min_delay = timeout_ms / 10;
uint32_t timer = millis() + (timeout_ms > 500 ? 500 : timeout_ms);
uint32_t min_delay = timeout_ms / 20;
if (min_delay < 10) {
yield(); // Allow at least once time for backgroundtasks
min_delay = 10;
Expand All @@ -755,3 +755,27 @@ bool WiFiConnected(uint32_t timeout_ms) {
}
return true;
}

bool hostReachable(const IPAddress& ip) {
// Only do 1 ping at a time to return early
byte retry = 3;
while (retry > 0) {
if (Ping.ping(ip, 1)) return true;
delay(50);
--retry;
}
String log = F("Host unreachable: ");
log += ip;
addLog(LOG_LEVEL_ERROR, log);
return false;
}

bool hostReachable(const String& hostname) {
IPAddress remote_addr;
if (WiFi.hostByName(hostname.c_str(), remote_addr))
return hostReachable(remote_addr);
String log = F("Hostname cannot be resolved: ");
log += hostname;
addLog(LOG_LEVEL_ERROR, log);
return false;
}
Loading

0 comments on commit 54628bf

Please sign in to comment.