-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
extmod/asyncio/stream.py: Add ipv6 support to start_server(). #17311
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
base: master
Are you sure you want to change the base?
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #17311 +/- ##
==========================================
- Coverage 98.54% 98.38% -0.16%
==========================================
Files 169 171 +2
Lines 21898 22257 +359
==========================================
+ Hits 21579 21898 +319
- Misses 319 359 +40 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
3443947
to
56e8e68
Compare
Code size report:
|
6227c48
to
3b17ecc
Compare
extmod/asyncio/stream.py
Outdated
@@ -180,11 +180,11 @@ async def start_server(cb, host, port, backlog=5, ssl=None): | |||
import socket | |||
|
|||
# Create and bind server socket. | |||
host = socket.getaddrinfo(host, port)[0] # TODO this is blocking! | |||
s = socket.socket() | |||
addr_info = socket.getaddrinfo(host, port)[0] # TODO this is blocking! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be possible to add the family
argument to start_server()
and pass it through to getaddrinfo()
here. Then you could force it to use IPv6 (or IPv4). But maybe that's a separate PR?
|
||
try: | ||
# Check if IPv6 is supported | ||
socket.socket(socket.AF_INET6, socket.SOCK_STREAM) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This detection won't work. All ports based on bare-metal lwIP will let this pass even if they don't have IPv6 enabled.
I don't know if it's possible to detect IPv6??
print("SKIP") | ||
raise SystemExit | ||
|
||
PORT = 8001 # Different from other tests to avoid conflicts |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this needs to use a different port, 8000 should be fine.
|
||
async def handle_connection(reader, writer): | ||
# Test that peername exists | ||
peer = writer.get_extra_info("peername") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The peer
variable is unused. I don't think you need to call this function at all.
|
||
data = await reader.read(100) | ||
print("read:", data) | ||
assert data == message, "Data mismatch" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't need this assert, the .exp will test the data is correct.
|
||
try: | ||
# Check if IPv6 is supported | ||
socket.socket(socket.AF_INET6, socket.SOCK_STREAM) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As above, this detection won't work.
try: | ||
# Connect with IPv6 client | ||
print("connect to ipv6 server") | ||
reader, writer = await asyncio.open_connection("::", PORT) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For this to work requires loopback mode in the TCP/IP driver. That's fine on unix, but it'll fail on most bare-metal ports.
# Read response | ||
data = await reader.read(100) | ||
print("read:", data) | ||
assert data == test_msg, "Data mismatch" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Assert not needed.
tests/run-multitests.py
Outdated
@@ -79,19 +79,59 @@ def globals(**gs): | |||
print("SET {{}} = {{!r}}".format(g, gs[g])) | |||
multitest.flush() | |||
@staticmethod | |||
def get_network_ip(): | |||
def _get_ip_from_ifconfig(_nic, ipv6=False): | |||
# Helper to get IP address from an interface object using appropriate format |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment doesn't add much, and I'm confused what "appropriate format" means?
tests/run-multitests.py
Outdated
pass | ||
|
||
# Find active network interface | ||
try: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code below is very hard to understand. Why so many try/except's?
Ensures that the underlying socket is opened with the correct protocol as parsed by getaddrinfo(). Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
3b17ecc
to
6684282
Compare
The change to the multi test runner and new (duplicated) ipv6 tests have been removed from this PR to simplify it. Updates to support testing ipv6 have been added in a different way in #17793 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for updating, looks good now.
Actually, on second thoughts, I'm wondering if the Adding that argument does add a fair amount to the code size. Whereas just passing through the family from getaddrinfo to the socket costs almost nothing. So, if you want to get this in sooner rather than later, I suggest reverting the family argument addition. |
Summary
I'm starting to use ipv6 more with micropython devices as their discoverability can actually be much better on a local network, without worrying about needing to manually configure (ipv4) ip addresses.
To that end, this PR adds support to start_server() to automatically use the parsed protocol, ie setting
socket.AF_INET
orsocket.AF_INET6
on the socket as parsed bygetaddrinfo()
When adding unit tests for this change, I found the multi-test runner was missing support for ipv6 ip address detection, so that's been added as well (in a separate commit)
The ip address detection in multi-test runner has also been updated to use the newer / preferred
network.ipconfig("addr4")
style interface by default, falling back to ipconfig if needed.Testing
Unit tests are included which check ipv6 support in both
net_hosted
style test andmult_net
tests.Without the change to
extmod/asyncio/stream.py
the tests fails withOSError: 97
Trade-offs and Alternatives