diff --git a/src/aioquic/asyncio/client.py b/src/aioquic/asyncio/client.py index 211ae36c..998860ab 100644 --- a/src/aioquic/asyncio/client.py +++ b/src/aioquic/asyncio/client.py @@ -1,5 +1,6 @@ import asyncio import socket +import sys from contextlib import asynccontextmanager from typing import AsyncGenerator, Callable, Optional, cast @@ -59,11 +60,23 @@ async def connect( token_handler=token_handler, ) + # OpenBSD well known to not support dual-stack + dual_stack = not sys.platform.startswith('openbsd') + + # Use AI_ADDRCONFIG on platforms which doesn't support dual-stack + getaddr_flags = 0 + if not dual_stack: + getaddr_flags = socket.AI_ADDRCONFIG + # lookup remote address - infos = await loop.getaddrinfo(host, port, type=socket.SOCK_DGRAM, flags=socket.AI_ADDRCONFIG) + infos = await loop.getaddrinfo(host, port, type=socket.SOCK_DGRAM, flags=getaddr_flags) addr = infos[0][4] # addr is 2-tuple for AF_INET and 4-tuple for AF_INET6 + if dual_stack and len(addr) == 2: + addr = ("::ffff:" + addr[0], addr[1], 0, 0) + local_tuple = ("::", local_port, 0, 0) + sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) if len(addr) == 2: local_tuple = ("0.0.0.0", local_port) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) @@ -75,6 +88,8 @@ async def connect( completed = False try: + if dual_stack: + sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0) sock.bind(local_tuple) completed = True finally: