JAndrassy/TelnetStream

Client not properly disconnected when not reading data

Closed this issue · 1 comments

jnslr commented

Description

In my setup i am only sending data via telnet stream, but i do not read data from the stream.
Without reading data, after having 5 connected clients, it is not possible to connect another client, even if the old clients are disconnected.
This is due to the fact, that my client (putty) seems to send some messages on connection/disconnection.
In that case, without ever reading the data from the client, client.avilable() will always be true, event if client.disconnected() is also true.
Hence this section of ArduinoWiFiServerEsp.h will never accept new clients even if the clients are long disconnected.

  void acceptClients() {
    for (uint8_t i = 0; i < MAX_MONITORED_CLIENTS; i++) {
      if (!connectedClients[i]) {
        connectedClients[i] = accept();
      }
    }
  }

How to reproduce

Use this simple sketch, and connect 5 putty clients. Connecting a 6th client will fail, even if the previous ones are already closed.
Commenting in the last section will fix the issue, as we are reading the data, e.g. flushing the input buffer. Then client.avalibale() will be false.

#include <Arduino.h>
#include <string>
#include <ESP8266WiFi.h>
#include <TelnetStream.h>

#include  "credentials.h"

void setup(void) 
{
    WiFi.mode(WIFI_STA);
    WiFi.begin(WIFI_SSID,WIFI_PASS);
    Serial.begin(115200);
    TelnetStream.begin();
    Serial.println("Start Telnet Stream test");
}
 
void loop(void) {
    static unsigned long lastSent = 0;
    static unsigned long cnt = 0;
    
    unsigned long now = millis();
    if (now-lastSent>1000) {
        char msg[20];
        sprintf(msg, "Sending message %lu", cnt);
        Serial.println(msg);
        TelnetStream.println(msg);
        cnt++;
        lastSent = now;
    }

    /*Enable this part makes clients disconnect properly
    std::string rxMsg;
    while (TelnetStream.available()){
        rxMsg += char(TelnetStream.read());
    }
    if (rxMsg.length() > 0)
        Serial.printf("Rx Message: %s",rxMsg.c_str());
    */
}

Environment

[env:TelnetLogging2]
platform = espressif8266@4.1.0
board = d1_mini
framework = arduino
lib_deps =
    https://github.com/jandrassy/TelnetStream#1.2.4

Possible fix

A possible fix would be to flush the input buffer, as soon as we have a pending connection, which is closed, but still has data available.

diff --git a/src/ArduinoWiFiServerESP.h b/src/ArduinoWiFiServerESP.h
index 9ce5860..b300892 100644
--- a/src/ArduinoWiFiServerESP.h
+++ b/src/ArduinoWiFiServerESP.h
@@ -129,6 +129,11 @@ private:

   void acceptClients() {
     for (uint8_t i = 0; i < MAX_MONITORED_CLIENTS; i++) {
+      if (connectedClients[i] && !connectedClients[i].connected()) {
+        while (connectedClients[i].available()){
+          Serial.printf("REad bytes from client %i",connectedClients[i].read());
+        }
+      }
       if (!connectedClients[i]) {
         connectedClients[i] = accept();
       }

But as the ArduinoWiFiServer is now part of the framwork-arudinoespressif8266 it would have to be fixed in serveral places.
Moreover reading the lastWill data of an already disconnected client could be a use case as well, so just throwing away the input buffer seems to be not the best idea, especially in other non telnetStream related applications.

Do you have any better suggestion?
Do you even consider this to be a bug, or is it just in the users responsibility to read the data from the stream as well and live with the pending connections if he/she doesn't do so.

Thanks for your reply,
Best regards

try TelnetPrint instead of TelnetStream