1
1
import asyncio
2
2
import socket
3
+ import sys
3
4
from contextlib import asynccontextmanager
4
5
from typing import AsyncGenerator , Callable , Optional , cast
5
6
@@ -59,11 +60,23 @@ async def connect(
59
60
token_handler = token_handler ,
60
61
)
61
62
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
+
62
71
# 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 )
64
73
65
74
addr = infos [0 ][4 ]
66
75
# 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 )
67
80
if len (addr ) == 2 :
68
81
local_tuple = ("0.0.0.0" , local_port )
69
82
sock = socket .socket (socket .AF_INET , socket .SOCK_DGRAM )
@@ -75,6 +88,8 @@ async def connect(
75
88
76
89
completed = False
77
90
try :
91
+ if dual_stack :
92
+ sock .setsockopt (socket .IPPROTO_IPV6 , socket .IPV6_V6ONLY , 0 )
78
93
sock .bind (local_tuple )
79
94
completed = True
80
95
finally :
0 commit comments