Skip to content

WiFiUDP::endPacket() issue (BUG) in AP mode after WiFi STA failing to connect to open network #1080

@giorgiogallina

Description

@giorgiogallina

I have already reported the following issue (#1045), but I am now reporting as emerging in a minimal scenario.

I am using an Arduino GIGA R1 WiFi.

The point is that if I try to connect to an open network that does not exist, and then activate AP, WiFiUDP then fails to send any answer.

To test this issue, I have written a short sketch, which I am reporting below.
You can see that everything works fine if no connection is attempted in STA mode, or even after failing to connect to a private network; however, after failing to connect to an open network, the issue arises.

#include <SDRAM.h>
#include <WiFi.h>
#include <IPAddress.h>
#include <WiFiUDP.h>

// #define AP_TEST_ONLY                             // uncomment this line to avoid STA connection (thus only AP mode is acctivated)
#define STA_CONNECT_TO_OPEN_NW        // comment this line to try to connect to protected nw instead of open

#define AP_SSID     "ArduinoAP"
#define AP_PWD      "ArduinoAP"
#define AP_CHANNEL  5
#define STA_SSID    "dummyNetwork"
#define STA_PWD     "nopassword"


uint8_t  _wifi_status = WL_IDLE_STATUS;
WiFiUDP  _ap_udp;


void _printWiFiStatus()
{
  Serial.println("-- WIFI INFO ----------------------------");
  Serial.print("      SSID: ");   Serial.println(WiFi.SSID());
  Serial.print("    status: ");   Serial.println(WiFi.status());
  Serial.print("   IP addr: ");   Serial.println(WiFi.localIP());
  Serial.print("  IP gatew: ");   Serial.println(WiFi.gatewayIP());
  Serial.print("      RSSI: ");   Serial.print(WiFi.RSSI());
  Serial.println("dBm\n-----------------------------------------");
}



/** Disconnect WiFi and reset default parameters. */
void _wifiCleanup()
{
  Serial.println("\nWIFI CLEANUP:");

  WiFi.disconnect();                              // close corrently opened connection
  WiFi.end();

  NetworkInterface* nif = WiFi.getNetwork();      // reset network paramenters
  if (nif != nullptr)
  { nif->set_default_parameters();
  }

  _wifi_status = WiFi.status();
  _printWiFiStatus();                             // print WiFi status
}


/** Try to connect to an open WiFi network (which actually does not exist). */
void _STADummyConnection()
{
  _wifiCleanup();                 // clean previous connection
  WiFi.config(IPAddress());       // enable dhcp
#ifdef STA_CONNECT_TO_OPEN_NW
  WiFi.begin(STA_SSID);           // try to connect to inexistent open network
#else
  WiFi.begin(STA_SSID, STA_PWD);  // try to connect to inexistent private network
#endif
  _wifi_status = WiFi.status();   // update WiFi status variable
  Serial.println("\nWIFI FAKE STA CONNECTION:");
  _printWiFiStatus();             // print WiFi status
}


/** activate Arduino's Access Point (with pwd = ssid) */
void _APOpening()
{
  _wifiCleanup();                                       // clean previous connection
  IPAddress ip = IPAddress((char)random(11, 172), (char)random(0, 255), (char)random(0, 255), 0x01);  // Generate random IP adress in Private IP range
  WiFi.config(ip, ip, ip, IPAddress(255,255,255,0));    // configure static IP
  WiFi.beginAP(AP_SSID, AP_PWD, AP_CHANNEL);            // open access point with given ssid, password and channel
  _wifi_status = WiFi.status();                         // update WiFi status variable
  Serial.println("\nWIFI AP STATUS:");
  _printWiFiStatus();                                   // print WiFi status
}


/** Send packet back to sender*/
void UDPReply(int16_t packet_size)
{
  Serial.println("UDP INFO: read and reply.");
  int tmp_res;
  IPAddress client_ip = _ap_udp.remoteIP();               // get client address
  uint16_t client_port = _ap_udp.remotePort();

  uint8_t *packet_buffer = (uint8_t*)SDRAM.malloc(sizeof(uint8_t) * (packet_size + 4));  // buffer to hold incoming and outgoing packets
  int plen = _ap_udp.read(packet_buffer, packet_size);    // read packet from client
  if (plen >= 0  &&  plen < (packet_size+4))              // safety null-terminated string
  { packet_buffer[plen] = 0;
  }

  // skip own requests (ntp-pool time request from WiFi module)
  if (client_ip != WiFi.localIP())
  {
    Serial.print("UDP INFO: received ");
    Serial.print(packet_size);
    Serial.print(" bytes from ");
    Serial.print(client_ip);
    Serial.write('-');
    Serial.println(client_port);

    tmp_res = _ap_udp.beginPacket(client_ip, client_port);    // get ready for UDP reply
    Serial.print("UDP INFO: beginPacket() -> ");
    Serial.println(tmp_res);

    _ap_udp.write(packet_buffer, plen);                       // write answer for UDP reply
    tmp_res = _ap_udp.endPacket();                            // send UDP reply
    Serial.print("UDP INFO: endPacket() -> ");
    Serial.println(tmp_res);
  }

  delay(40);
  SDRAM.free(packet_buffer);
}


void setup() {
  
  Serial.begin(115200);                                   // Init Serial for debugging messages
  while (!Serial)
  {};
  Serial.println("Serial ready!");

  SDRAM.begin();                                          // setup SDRAM

  while (WiFi.status() == WL_NO_MODULE)                   // check WiFi module is working
  {};

#ifndef AP_TEST_ONLY
  _STADummyConnection();                                  // try connecting to inexistent open network
  delay(200);                                             // wait 0.2s
#endif

  _APOpening();                                           // open Access Point

  if (_wifi_status != WL_AP_LISTENING)                    // check AP was successfully opened
  { return;                                               // (otherwise stop and to nothing)
  }

  uint8_t tmp_res;
  tmp_res = _ap_udp.begin(53);                            // start UDP manager
  Serial.print("\n\nUDP INFO: begin(53) -> ");
  Serial.println(tmp_res);

  while (true)
  {
    if (WiFi.status() == WL_AP_LISTENING)                  // no client connected
    {
      if (_wifi_status != WL_AP_LISTENING)                      // Debug info
      { Serial.println("WiFi status changed to WL_AP_LISTENING");
        _wifi_status = WL_AP_LISTENING;
      }
    }
    
    else if (WiFi.status() == WL_AP_CONNECTED)
    {
      if (_wifi_status != WL_AP_CONNECTED)                      // Debug info
      { Serial.println("WiFi status changed to WL_AP_CONNECTED");
        _wifi_status = WL_AP_CONNECTED;
      }

      int16_t packet_size = _ap_udp.parsePacket();              // get packet size, if available
      if (packet_size > 0)                                      // packet available:
      { UDPReply(packet_size);                                  // read it and send it back
      }
    }

    else
    {
      Serial.print("ERROR: unexpected WiFi Status ");
      Serial.println(WiFi.status());
      delay(1000);
    }
  }

}

void loop() 
{
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions