unix usocket: External representation of (binary) addresses
Ok, https://github.com/micropython/micropython/pull/1002 was closed, because approach of requiring usage of getaddrinfo() to pass addresses to socket functions certainly works. But there's opposite problem - how to show to user an address received from a socket function, e.g. accept(), which doesn't have any solution now. I can imagine following choices:
- Give up and return Python-standard tuple representation of addresses, then almost certainly also need to accept them to all other functions. Bunch more extra code, memory required for minimal socket server grows.
- Stay stubborn and make sockaddr a separate object, which will do conversion only on str() or repr(). No extra RAM overhead with this solution, but object will be more or less involved, e.g. standard Python tuple should be emulated.
- Stay stubborn and low-profile - just provide a function to convert binary address to Python tuple.
Thoughts?
unix extmod/uasyncio: socket.getaddrinfo and uasyncio.open_connection are incompatible
In some situations it may be useful to decouple performing a dns lookup from opening a connection. An example is in Peter Hinch's mqtt_as library where the DNS lookup is performed once and not for every MQTT reconnect. The following test case (extracted from mqtt_as) works fine on esp32 (I believe also pybd and esp8266) but fails on unix:
# test that the output of socket.getaddrinfo can be fed into asyncio.open_connection
import sys
if sys.implementation.name == 'micropython' and sys.platform == 'linux':
sys.path.append("/home/src/esp32/micropython/extmod")
try:
import usocket as socket, uasyncio as asyncio
except:
import socket, asyncio
async def test(peer_name):
# perform DNS lookup
addr = socket.getaddrinfo(peer_name, 80)[0][-1]
print("Addr:", addr)
# open connection
s = await asyncio.open_connection(addr[0], addr[1])
print("Connected!")
if __name__ == "__main__":
asyncio.run(test('micropython.org'))
Sample output:
> python test-dns.py
Addr: ('176.58.119.26', 80)
Connected!
> ./pyboard test-dns.py
Addr: ('176.58.119.26', 80)
Connected!
> ../../micropython/ports/unix/micropython test-dns.py
Addr: bytearray(b'\x02\x00\x00P\xb0:w\x1a\x00\x00\x00\x00\x00\x00\x00\x00')
Traceback (most recent call last):
File "test-dns.py", line 20, in <module>
File "/home/src/esp32/micropython/extmod/uasyncio/core.py", line 210, in run
File "/home/src/esp32/micropython/extmod/uasyncio/core.py", line 190, in run_until_complete
File "/home/src/esp32/micropython/extmod/uasyncio/core.py", line 179, in run_until_complete
File "test-dns.py", line 16, in test
File "/home/src/esp32/micropython/extmod/uasyncio/stream.py", line 61, in open_connection
TypeError: can't convert 'int' object to str implicitly
I realize this probably is the way it is, but I wonder whether there's an easy work-around. The motivation is to be able to run the same code on unix for test&dev purposes.