Skip to content

Crosstalk between WiFi clients. Multiple clients assigned same socket number.  #176

Open
@bobfromdallas

Description

@bobfromdallas

I observed crosstalk between clients. For example, a response to a local FTP command was seen on a client doing an HTTP GET.

This crosstalk occurred after a loss of WiFi and subsequent reconnection.

I have limited understanding of the WiFiNINA software and even less understanding of the associated firmware. In reviewing that code, it seemed that the observed crosstalk could happen if multiple WiFi clients were using the same socket to communicate with the WiFi module. The sketch below shows that duplicate assignment of sockets can occur.

#include "arduino_secrets.h"     // defines SECRET_SSID and SECRET_PASS

#include <Arduino_ConnectionHandler.h>
WiFiConnectionHandler conMan(SECRET_SSID, SECRET_PASS);

//  'printf' style macro
#define dbprintf(fmt, ...) _dbprintf(fmt, ##__VA_ARGS__)
#define DB_BUF_LEN 256
static char dbBufIn[DB_BUF_LEN] = "";
void _dbprintf(const char *fmt, ...) {
    va_list ap;
    va_start(ap, fmt);
    vsnprintf(dbBufIn, DB_BUF_LEN, fmt, ap);
    Serial.write(dbBufIn, strlen(dbBufIn));
    va_end(ap);
}

#define M2MS 60000  // minutes to ms
uint32_t eventTime[5] {1*M2MS, 2*M2MS, 3*M2MS, 4*M2MS, 5*M2MS};   // events at 1, 2, 3, 4, 5 minutes
bool eventDone[5] {false, false, false, false, false};

/////////////// WiFi users
WiFiClient gclient;
constexpr char gHost[] {"script.google.com"};
constexpr uint16_t gPort {443};

WiFiClient yclient;
constexpr char yHost[] {"yahoo.com"};
constexpr uint16_t yPort {80};
///////////////

void setup() {
    Serial.begin(115200);
    delay(2000);  //    routinely takes 1.5 s to begin Serial so just wait 2 s
    if (Serial) 
        dbprintf("\nSuccessfully started serial connection\n");
            
// part of Arduino_DebugUtils included by Arduino_ConnectionHandler
    setDebugMessageLevel(DBG_WARNING); // equals Debug.setDebugLevel
    Debug.timestampOn();

    conMan.addCallback(NetworkConnectionEvent::CONNECTED, onNetworkConnect);
    conMan.addCallback(NetworkConnectionEvent::DISCONNECTED, onNetworkDisconnect);
    conMan.addCallback(NetworkConnectionEvent::ERROR, onNetworkError);

    // start WiFi
    for (uint8_t i=0; i<5; i++) {
        delay(500);
        conMan.check();
    }

    // start the WiFi clients
    gclient.connect(gHost, gPort);
    dbprintf("\t\t\tbegan gclient with socket %u at %u ms\n", gclient._sock, millis());
    yclient.connect(yHost, yPort);
    dbprintf("\t\t\tbegan yclient with socket %u at %u ms\n", yclient._sock, millis());
 
    printSockets();
}  // setup()


void loop() {
    if (!eventDone[0] && millis() > eventTime[0]) {
        eventDone[0] = true;
        dbprintf("\tending WiFi to simulate loss of connection at %u ms\n", millis());
        // WiFi.end();
        WiFi.disconnect();
        delay(5000);
        printSockets();
    }
    if (!eventDone[1] && millis() > eventTime[1]) {
        eventDone[1] = true;
        dbprintf("\nreconnect (1) clients in reverse order\n");
        yclient.connect(yHost, yPort);
        dbprintf("\t\t\tbegan yclient with socket %u at %u ms\n", yclient._sock, millis());
        gclient.connect(gHost, gPort);
        dbprintf("\t\t\tbegan gclient with socket %u at %u ms\n", gclient._sock, millis());
        printSockets();
    }

    conMan.check();
} // loop


void printSockets() {
    dbprintf("gclient using socket %u at %6u. Status: %d.\n", gclient._sock, millis(), gclient.status());
    dbprintf("yclient using socket %u at %6u. Status: %d.\n", yclient._sock, millis(), yclient.status());
}


void onNetworkConnect() {
    Serial.println(">>>>> WiFi CONNECTED to network");
    RGB(0, 0, 8);
}

void onNetworkDisconnect() {
    Serial.println(">>>>> WiFi DISCONNECTED from network");
    Serial.print(">>>>> DISCONNECT reason code: ");
    Serial.println(WiFi.reasonCode());
    RGB(32, 16, 8);
}

void onNetworkError() {
    Serial.println(">>>>> WiFi ERROR");
    Serial.print(">>>>> ERROR reason code: ");
    Serial.println(WiFi.reasonCode());
    RGB(32, 0, 0);
}

void RGB(uint8_t r, uint8_t g, uint8_t b) {
    WiFiDrv::pinMode(25, OUTPUT);  //GREEN
    WiFiDrv::pinMode(26, OUTPUT);  //RED
    WiFiDrv::pinMode(27, OUTPUT);  //BLUE
    
    WiFiDrv::analogWrite(25, g);
    WiFiDrv::analogWrite(26, r);
    WiFiDrv::analogWrite(27, b);
}

This sketch was executed on a MKR WiFi 1010 using version 1.8.8 of the WiFiNINA library. To see what sockets were being assigned the "_sock" variable in WiFiClient.h was changed from private to public.

Here's an output from the sketch.

Successfully started serial connection
[ 3383 ] Current WiFi Firmware: 1.4.4
>>>>> WiFi CONNECTED to network
				began gclient with socket 0 at 7201 ms
				began yclient with socket 1 at 7575 ms
gclient using socket 0 at   7575. Status: 4.
yclient using socket 1 at   7575. Status: 4.
		ending WiFi to simulate loss of connection at 60001 ms
gclient using socket 0 at  65014. Status: 0.
yclient using socket 1 at  65015. Status: 0.
[ 65015 ] Connection to "Guest" lost.
[ 65015 ] Attempting reconnection
>>>>> WiFi DISCONNECTED from network
>>>>> DISCONNECT with reason code: 8
[ 66877 ] Current WiFi Firmware: 1.4.4
[ 69434 ] Connection to "Guest" failed
>>>>> WiFi CONNECTED to network

reconnect (1) clients in reverse order
				began yclient with socket 0 at 120251 ms
				began gclient with socket 0 at 120335 ms
gclient using socket 0 at 120335. Status: 4.
yclient using socket 0 at 120335. Status: 4.

Note that at the end both gclient and yclient are using socket 0.

It seems that the WiFiNINA library and the NINA firmware get out of sync on socket assignments.
A partial sequence of events:
  restarting WiFi clears all socket assignments;
  reconnecting 'yclient' assigns socket 0 to 'gclient'; and
  reconnecting 'gclient' results in duplicate assignment of socket 0 because
    WiFiClient::connect calls WiFiClient::stop because gclient._sock is 0 indicating that socket 0 is still assigned to 'gclient',
    WiFiClient::stop clears the assignment of socket 0, and
    socket 0 then gets assigned to 'gclient'.

Any suggestions on how to prevent this issue would be appreciated.

Metadata

Metadata

Assignees

No one assigned

    Labels

    topic: codeRelated to content of the project itselftype: imperfectionPerceived defect in any part of project

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions