11import asyncio
22import socket
3+ import sys
34from contextlib import asynccontextmanager
45from typing import AsyncGenerator , Callable , Optional , cast
56
@@ -59,11 +60,23 @@ async def connect(
5960 token_handler = token_handler ,
6061 )
6162
63+ # OpenBSD well known to not suppoort dual-stack
64+ dual_stack = not sys .platform .startswith ('openbsd' )
65+
66+ # Use AI_ADDRCONFIG on platforms which doesn't support dual-stack
67+ getaddr_flags = 0
68+ if not dual_stack :
69+ getaddr_flags = socket .AI_ADDRCONFIG
70+
6271 # lookup remote address
63- infos = await loop .getaddrinfo (host , port , type = socket .SOCK_DGRAM , flags = socket . AI_ADDRCONFIG )
72+ infos = await loop .getaddrinfo (host , port , type = socket .SOCK_DGRAM , flags = 0 )
6473
6574 addr = infos [0 ][4 ]
6675 # addr is 2-tuple for AF_INET and 4-tuple for AF_INET6
76+ if dual_stack and len (addr ) == 2 :
77+ addr = ("::ffff:" + addr [0 ], addr [1 ], 0 , 0 )
78+ local_tuple = ("::" , local_port , 0 , 0 )
79+ sock = socket .socket (socket .AF_INET6 , socket .SOCK_DGRAM )
6780 if len (addr ) == 2 :
6881 local_tuple = ("0.0.0.0" , local_port )
6982 sock = socket .socket (socket .AF_INET , socket .SOCK_DGRAM )
@@ -75,6 +88,8 @@ async def connect(
7588
7689 completed = False
7790 try :
91+ if dual_stack :
92+ sock .setsockopt (socket .IPPROTO_IPV6 , socket .IPV6_V6ONLY , 0 )
7893 sock .bind (local_tuple )
7994 completed = True
8095 finally :
0 commit comments