adafruit / Adafruit_CircuitPython_ESP32SPI

ESP32 as wifi with SPI interface
MIT License
101 stars 74 forks source link

Only allows one TLS connection at a time #134

Open askpatrickw opened 3 years ago

askpatrickw commented 3 years ago

In release 3.5.3 a change was made: "Only allow one TLS connection at a time. Nina FW doesn't work well with multiple."

This broke the Azure_IOT workflow where you use HTTP to determiner your Iot Hub and then connect to it over MQTT. https://github.com/adafruit/Adafruit_CircuitPython_AzureIoT/pull/31#issuecomment-819900695

There was a workaround for that library, but I wanted to document the issue.

justmobilize commented 3 months ago

@tannewt do you remember (almost 4 years ago), why this was removed?

Testing, using:

from digitalio import DigitalInOut
import board
import os

import adafruit_connection_manager
from adafruit_esp32spi import adafruit_esp32spi

esp32_cs = DigitalInOut(board.D13)
esp32_ready = DigitalInOut(board.D11)
esp32_reset = DigitalInOut(board.D12)

spi = board.SPI()
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)

# Get WiFi details, ensure these are setup in settings.toml
ssid = os.getenv("WIFI_SSID")
password = os.getenv("WIFI_PASSWORD")

print(f"\nConnecting to {ssid}...")
esp.connect(ssid, password)
print("connected")

pool = adafruit_connection_manager.get_radio_socketpool(esp)
ssl_context = adafruit_connection_manager.get_radio_ssl_context(esp)

connection_manager = adafruit_connection_manager.get_connection_manager(pool)
socket_1 = connection_manager.get_socket("io.adafruit.com", 443, "https:", is_ssl=True, ssl_context=ssl_context)
socket_2 = connection_manager.get_socket("www.adafruit.com", 443, "https:", is_ssl=True, ssl_context=ssl_context)

I get:

>>> socket_1 = connection_manager.get_socket("io.adafruit.com", 443, "https:", is_ssl=True, ssl_context=ssl_context)
>>> socket_2 = connection_manager.get_socket("www.adafruit.com", 443, "https:", is_ssl=True, ssl_context=ssl_context)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "adafruit_connection_manager.py", line 332, in get_socket
  File "adafruit_connection_manager.py", line 244, in _get_connected_socket
  File "adafruit_connection_manager.py", line 61, in connect
  File "adafruit_esp32spi/adafruit_esp32spi_socketpool.py", line 114, in connect
  File "adafruit_esp32spi/adafruit_esp32spi.py", line 836, in socket_connect
  File "adafruit_esp32spi/adafruit_esp32spi.py", line 721, in socket_open
OSError: 23

If I comment out the code to only allow 1 I get:

>>> socket_1 = connection_manager.get_socket("io.adafruit.com", 443, "https:", is_ssl=True, ssl_context=ssl_context)
>>> socket_2 = connection_manager.get_socket("www.adafruit.com", 443, "https:", is_ssl=True, ssl_context=ssl_context)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "adafruit_connection_manager.py", line 332, in get_socket
  File "adafruit_connection_manager.py", line 244, in _get_connected_socket
  File "adafruit_connection_manager.py", line 61, in connect
  File "/lib/adafruit_esp32spi/adafruit_esp32spi_socketpool.py", line 114, in connect
  File "/lib/adafruit_esp32spi/adafruit_esp32spi.py", line 836, in socket_connect
  File "/lib/adafruit_esp32spi/adafruit_esp32spi.py", line 732, in socket_open
  File "/lib/adafruit_esp32spi/adafruit_esp32spi.py", line 341, in _send_command_get_response
  File "/lib/adafruit_esp32spi/adafruit_esp32spi.py", line 311, in _wait_response_cmd
  File "/lib/adafruit_esp32spi/adafruit_esp32spi.py", line 293, in _check_data
BrokenPipeError: Expected 01 but got 00

cc @dhalbert

dhalbert commented 3 months ago

I found a discussion in the forums that includes @tannewt that is at the same time as the 3.5.3 release: https://forums.adafruit.com/viewtopic.php?p=836698

anecdata commented 3 months ago

I think this† has been noted before, but I can't find it:

secure_socks = []
for sock_num, _ in enumerate(HOSTS):
    secure_socks.append(
        ssl_context.wrap_socket(
            pool.socket(pool.AF_INET, pool.SOCK_STREAM),
            server_hostname=HOSTS[sock_num]
        )
    )

with debug=2, results in:

*** Get socket
    Parameter #0 length is 1
Read 1:  [bytearray(b'\x00')]
Allocated socket #0
*** Get socket
    Parameter #0 length is 1
Read 1:  [bytearray(b'\x00')]
Allocated socket #0

†Seems to be allocating the same socket? That socket number is coming from NINA.

If we change the code to use the created secure socket (connect, write, read) before allocating the second one, we get further since a new socket number is allocated, but still OSError: 23 (on connect() to the 2nd secure socket):

*** Get socket
    Parameter #0 length is 1
Read 1:  [bytearray(b'\x01')]
Allocated socket #1
=========================
Connecting to remote socket...
*** Socket connect mode 2
*** Open socket to www.adafruit.com 443 2
Traceback (most recent call last):
  File "code.py", line 37, in <module>
  File "adafruit_connection_manager.py", line 69, in connect
  File "adafruit_esp32spi/adafruit_esp32spi_socketpool.py", line 142, in connect
  File "adafruit_esp32spi/adafruit_esp32spi.py", line 836, in socket_connect
  File "adafruit_esp32spi/adafruit_esp32spi.py", line 721, in socket_open
OSError: 23
tannewt commented 3 months ago

I don't remember. Sorry!

dhalbert commented 3 months ago

Given this testing, I'm not sure this can be fixed now. We can revisit after https://github.com/adafruit/nina-fw/pull/62 is done. In the meantime, I'll merge #207.

justmobilize commented 3 months ago

I think this has been noted before, but I can't find it:

secure_socks = []
for sock_num, _ in enumerate(HOSTS):
    secure_socks.append(
        ssl_context.wrap_socket(
            pool.socket(pool.AF_INET, pool.SOCK_STREAM),
            server_hostname=HOSTS[sock_num]
        )
    )

results in (debug=2):

*** Get socket
  Parameter #0 length is 1
Read 1:  [bytearray(b'\x00')]
Allocated socket #0
*** Get socket
  Parameter #0 length is 1
Read 1:  [bytearray(b'\x00')]
Allocated socket #0

Seems to be allocating the same socket? That socket number is coming from NINA.

If we change the code to use the created secure socket (connect, write, read) before allocating the second one, we get further since a new socket number is allocated, but still OSError: 23 (on connect() to the 2nd secure socket):

*** Get socket
  Parameter #0 length is 1
Read 1:  [bytearray(b'\x01')]
Allocated socket #1
=========================
Connecting to remote socket...
*** Socket connect mode 2
*** Open socket to www.adafruit.com 443 2
Traceback (most recent call last):
  File "code.py", line 37, in <module>
  File "adafruit_connection_manager.py", line 69, in connect
  File "adafruit_esp32spi/adafruit_esp32spi_socketpool.py", line 142, in connect
  File "adafruit_esp32spi/adafruit_esp32spi.py", line 836, in socket_connect
  File "adafruit_esp32spi/adafruit_esp32spi.py", line 721, in socket_open
OSError: 23

I think this has been noted before, but I can't find it:

secure_socks = []
for sock_num, _ in enumerate(HOSTS):
    secure_socks.append(
        ssl_context.wrap_socket(
            pool.socket(pool.AF_INET, pool.SOCK_STREAM),
            server_hostname=HOSTS[sock_num]
        )
    )

results in (debug=2):

*** Get socket
  Parameter #0 length is 1
Read 1:  [bytearray(b'\x00')]
Allocated socket #0
*** Get socket
  Parameter #0 length is 1
Read 1:  [bytearray(b'\x00')]
Allocated socket #0

Seems to be allocating the same socket? That socket number is coming from NINA.

If we change the code to use the created secure socket (connect, write, read) before allocating the second one, we get further since a new socket number is allocated, but still OSError: 23 (on connect() to the 2nd secure socket):

*** Get socket
  Parameter #0 length is 1
Read 1:  [bytearray(b'\x01')]
Allocated socket #1
=========================
Connecting to remote socket...
*** Socket connect mode 2
*** Open socket to www.adafruit.com 443 2
Traceback (most recent call last):
  File "code.py", line 37, in <module>
  File "adafruit_connection_manager.py", line 69, in connect
  File "adafruit_esp32spi/adafruit_esp32spi_socketpool.py", line 142, in connect
  File "adafruit_esp32spi/adafruit_esp32spi.py", line 836, in socket_connect
  File "adafruit_esp32spi/adafruit_esp32spi.py", line 721, in socket_open
OSError: 23

A assume in this case HOSTS are two very different hosts?

justmobilize commented 3 months ago

Given this testing, I'm not sure this can be fixed now. We can revisit after adafruit/nina-fw#62 is done. In the meantime, I'll merge #207.

This was going to be my suggestion

anecdata commented 3 months ago

assume in this case HOSTS are two very different hosts?

@justmobilize I used the same two Adafruit hosts (subdomains) that you did