Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Connecting to open Wi-Fi networks broken in 8.0, buggy in 7.3.3 #6897

Closed
skickar opened this issue Sep 12, 2022 · 11 comments
Closed

Connecting to open Wi-Fi networks broken in 8.0, buggy in 7.3.3 #6897

skickar opened this issue Sep 12, 2022 · 11 comments
Assignees
Labels
bug espressif applies to multiple Espressif chips needs retest network
Milestone

Comments

@skickar
Copy link

skickar commented Sep 12, 2022

CircuitPython version

Adafruit CircuitPython 7.3.3 on 2022-08-29; S2Mini with ESP32S2-S2FN4R2
Board ID:lolin_s2_mini

And

Adafruit CircuitPython 8.0.0-beta.0 on 2022-08-18; S2Mini with ESP32S2-S2FN4R2
Board ID:lolin_s2_mini

Code/REPL

import wifi
import ipaddress

SSID = "Virus"

print("Connect to {}".format(SSID))
wifi.radio.connect(SSID)
ipv4 = ipaddress.ip_address("8.8.4.4")
print("Ping google.com: %f ms" % (wifi.radio.ping(ipv4)*1000))

print("Done!")

Behavior

Using an S2 mini board and CP 8.0:

Attempting to connect to an "OPEN" Wi-Fi network may sometimes succeed the first time, but every other attempt will yield a "ConnectionError: No network with that ssid" error. Tested on multiple types of open networks. Attempting to reconnect can cause a hard crash and reboot to safe mode.

Using an S2 Mini Board and CP 7.3:

Certain types of open Wi-Fi networks (like setup networks for IoT devices) which don't provide internet can cause the "wifi.radio.connect()" command to hang forever. There is no way to detect this kind of network, so if a CP device running 7.3 tries to connect to it, it will freeze without crashing or giving output. Adding a timeout has no effect.

Description

I'm writing code to locate open Wi-Fi networks and attempt to connect to them. This is broken by bugs in CircuitPython 7.3 and 8.0.

In 8.0, attempting to join any open network will cause "ConnectionError: No network with that ssid". Sometimes it will work once, then not again. This can also cause a hard crash.

In 7.3, certain types of open networks (without a real internet connection) will cause "wifi.radio.connect(SSID)" to hang forever while trying to connect. Adding a timeout has no effect, and there is no error thrown.

Additional information

Screen Shot 2022-09-12 at 1 20 47 AM

Here is a hard crash in CP 8.0 when trying to connect to open Wi-Fi

signal-2022-09-12-135948

Here is an example of a network that will freeze CP 7.3.3 if it tries to connect

@skickar skickar added the bug label Sep 12, 2022
@DJDevon3
Copy link

This sounds very similar to the behavior I’m getting on my Adafruit feather esp32-s2 except I’m not even using WiFi in my code, I’m using lora. adafruit/Adafruit_CircuitPython_RFM9x#81

Every other save seems to be a common issue. I was getting double outputs to repl on my rp2040 feather too. Things happening in sets of 2 all over the place lately.

I’ve written in some error handling that’s preventing the program from crashing the script but I’m not getting hard faults on the S2. I was getting hard faults on my UM feather S3 though, to the point I stopped using the S3 and switched to the S2.

@anecdata
Copy link
Member

connect() is successful when an IPv4 address is obtained, so the AP is expected to be able to assign IPv4 addresses to connecting stations. Is it possible some of the open AP types are not assigning an IP address, or accepting a static address when using set_ipv4_address()?

@skickar
Copy link
Author

skickar commented Sep 13, 2022

connect() is successful when an IPv4 address is obtained, so the AP is expected to be able to assign IPv4 addresses to connecting stations. Is it possible some of the open AP types are not assigning an IP address, or accepting a static address when using set_ipv4_address()?

As soon as I submitted this I realized the 7.3.3 bug is going to be harder to test because I'm not sure what the issue with that network is. I can probably run Wireshark at the coffee shop and see exactly what the exchange is with the network.

It's worth noting that my MacOS system also can't connect to the network, but times out rather than freezing. I'm pretty sure this is a captive portal AP used for setting up IoT devices and doesn't provide real internet.

For security research, having the connect() freeze forever with no way of timing out is very limiting. It wasn't clear to me what the "timeout" flag does because it seems to have no effect on this freezing. My concept simply won't work if connecting to a new open Wi-Fi network will sometime cause a freeze with no error.

Would it be helpful to confirm what's going on with the network that's causing the issue?

If the network isn't providing an IP address, it's worth deciding how CircuitPython should behave in this circumstance to provide the developer with some flexibility in handling a frozen connection.

@DJDevon3
Copy link

Not sure if this is still relevant but I believe a password is required, the field cannot be blank. Unsure if that was ever resolved but it was an issue that prevented many people from joining open wifi networks. I haven't tested it recently though and no idea about its status.

@skickar
Copy link
Author

skickar commented Sep 13, 2022

I don't think that's correct. I am able to join open Wi-Fi networks with no passwords on 7.3.3 with connect() and no password, except for when it's a captive portal type access point that doesn't have internet access.

@dhalbert dhalbert added this to the 8.0.0 milestone Sep 13, 2022
@dhalbert dhalbert added network espressif applies to multiple Espressif chips labels Sep 13, 2022
@DJDevon3
Copy link

@skickar Nice, last I checked on that one was 7.3.2

@skickar
Copy link
Author

skickar commented Sep 23, 2022

Wi-Fi promiscuous mode also seems to be broken, I can't get this code to output anything in 8.0 after the first run even after reboots:

import wifi monitor = wifi.Monitor(channel=1, queue=128) while True: packet = monitor.packet() if packet != {}: print(packet)

This also produces no output:

for network in wifi.radio.start_scanning_networks(): print("\t%s\t\tRSSI: %d\tChannel: %d" % (str(network.ssid, "utf-8"), network.rssi, network.channel)) wifi.radio.stop_scanning_networks()

I've replicated this on an Adafruit Metro Express esp32s2 beta. Once I revert to 7.3.3 all commands work fine.

The problems I'm seeing with 8.0:

  • Can't see a Wi-Fi network scan after first scan
  • Can't connect to networks ("no SSID" error)
  • Can't see packets in promiscuous mode

@anecdata
Copy link
Member

anecdata commented Sep 23, 2022

@skickar can you file a separate issue for monitor? (I haven't yet tried anything past 7.3.x.) Even though it may turn out to be the same underlying issue as the open issue for scanning and connection problems in 8.0.0-beta.0: #6866 Is this what you are seeing? (the workaround for now is to enable web workflow with a /.env file)

P.S. I just tried a brief run of monitor on 8.0.0-beta.0, and it seems to work with web workflow on (although I do try to run monitor without a connection to an AP to maximize throughput --> you can have web workflow on, then turn off Station using wifi.radio.stop_station(), then run monitor w/o a connection to the AP)

@PaulskPt
Copy link

@skickar To avoid an error: TypeError: unsupported types for __mul__: 'NoneType', 'int' I use the following code:

        n = wifi.radio.ping(ipaddress.ip_address("8.8.4.4"))
        if n:
            print("Ping google.com: %f ms" % (n*1000))
        else:
            print("Ping to google.com failed")

because when the result of the call to wifi.radio.ping() is 'None' (which happens) your code is trying to multiply 1000 with None.
As with all 'critical' calls it is best practice to check return values and handle upon the results (as shown in my example) or create a try: ... except: ... block to catch failures/errors.

Also is good practice to have the call wifi.radio.connect("Virus") be followed by a check if the result of the connect was successful or not. In the case of a successfull connect an IP-address should have been assigned. That could be checked as follows:

   ap = "Virus"
   wifi.radio.connect(ap)
   ip = wifi.radio.ipv4_address
   if ip:
       print("WiFi connected to", ap)
       print("IP address=", ip)
   else:
       print("WiFi connection failed")```

@DJDevon3
Copy link

DJDevon3 commented Oct 12, 2022

@skickar please try an 8.0 nightly build (S3 bucket repo) on or after Oct 11, 2022. A lot of bugs were fixed for WiFi on multiple S2 & S3 boards. Please report back.

@dhalbert dhalbert self-assigned this Nov 22, 2022
@dhalbert
Copy link
Collaborator

I tried this on the tip of main with an open network on a spare router I have, both unconnected to the Internet and also (briefly) connected. I repeated a (slightly modified) standard CircuitPython internet test several times with a soft restart in between, and could not cause an error.

I am going to close this for now. Please reopen or resubmit if you still see this problem with the latest 8.0.0. I did not test with 7.3.x.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug espressif applies to multiple Espressif chips needs retest network
Projects
None yet
Development

No branches or pull requests

6 participants