File tree Expand file tree Collapse file tree 3 files changed +30
-22
lines changed
Expand file tree Collapse file tree 3 files changed +30
-22
lines changed Original file line number Diff line number Diff line change 1515import traceback
1616from datetime import datetime
1717
18+ from .utils import has_dualstack_ipv6
19+
1820try :
1921 import grp
2022 import pwd
@@ -336,24 +338,6 @@ def _is_ssl_sock(sock):
336338 return SSL is not None and isinstance (sock , SSL .Connection )
337339
338340
339- def _support_hybrid_ipv6 ():
340- """Return True if it is possible to use hybrid IPv6/IPv4 sockets
341- on this platform.
342- """
343- # Note: IPPROTO_IPV6 constant is broken on Windows, see:
344- # https://bugs.python.org/issue6926
345- try :
346- if not socket .has_ipv6 :
347- return False
348- with contextlib .closing (socket .socket (socket .AF_INET6 )) as sock :
349- return not sock .getsockopt (socket .IPPROTO_IPV6 , socket .IPV6_V6ONLY )
350- except (OSError , AttributeError ):
351- return False
352-
353-
354- SUPPORTS_HYBRID_IPV6 = _support_hybrid_ipv6 ()
355-
356-
357341class _FileReadWriteError (OSError ):
358342 """Exception raised when reading or writing a file during a transfer."""
359343
@@ -2195,7 +2179,7 @@ def ftp_EPRT(self, line):
21952179 # test if AF_INET6 and IPV6_V6ONLY
21962180 if (
21972181 self .socket .family == socket .AF_INET6
2198- and not SUPPORTS_HYBRID_IPV6
2182+ and not has_dualstack_ipv6 ()
21992183 ):
22002184 self .respond ("522 Network protocol not supported (use 2)." )
22012185 else :
Original file line number Diff line number Diff line change 22# Use of this source code is governed by MIT license that can be
33# found in the LICENSE file.
44
5+ import contextlib
56import os
7+ import socket
68import sys
79
810
@@ -73,3 +75,25 @@ def strerror(err):
7375 if isinstance (err , OSError ):
7476 return os .strerror (err .errno )
7577 return str (err )
78+
79+
80+ # backport of Python 3.8 socket.has_dualstack_ipv6()
81+ @memoize
82+ def has_dualstack_ipv6 ():
83+ """Return True if the platform supports creating a SOCK_STREAM socket
84+ which can handle both AF_INET and AF_INET6 (IPv4 / IPv6) connections.
85+ """
86+ if (
87+ not socket .has_ipv6
88+ or not hasattr (socket , "IPPROTO_IPV6" )
89+ or not hasattr (socket , "IPV6_V6ONLY" )
90+ ):
91+ return False
92+ try :
93+ with contextlib .closing (
94+ socket .socket (socket .AF_INET6 , socket .SOCK_STREAM )
95+ ) as sock :
96+ sock .setsockopt (socket .IPPROTO_IPV6 , socket .IPV6_V6ONLY , 0 )
97+ return True
98+ except OSError :
99+ return False
Original file line number Diff line number Diff line change 2121import pytest
2222
2323from pyftpdlib .filesystems import AbstractedFS
24- from pyftpdlib .handlers import SUPPORTS_HYBRID_IPV6
2524from pyftpdlib .handlers import DTPHandler
2625from pyftpdlib .handlers import FTPHandler
2726from pyftpdlib .handlers import ThrottledDTPHandler
2827from pyftpdlib .ioloop import IOLoop
2928from pyftpdlib .servers import FTPServer
29+ from pyftpdlib .utils import has_dualstack_ipv6
3030
3131from . import BUFSIZE
3232from . import CI_TESTING
@@ -2130,7 +2130,7 @@ def cmdresp(self, cmd):
21302130
21312131 @disable_log_warning
21322132 def test_eprt (self ):
2133- if not SUPPORTS_HYBRID_IPV6 :
2133+ if not has_dualstack_ipv6 () :
21342134 # test wrong proto
21352135 with pytest .raises (ftplib .error_perm , match = "522" ):
21362136 self .client .sendcmd (
@@ -2294,7 +2294,7 @@ def test_eprt_v6(self):
22942294
22952295
22962296@pytest .mark .skipif (
2297- not SUPPORTS_HYBRID_IPV6 , reason = "IPv4/6 dual stack not supported"
2297+ not has_dualstack_ipv6 () , reason = "IPv4/6 dual stack not supported"
22982298)
22992299class TestIPv6MixedEnvironment (PyftpdlibTestCase ):
23002300 """By running the server by specifying "::" as IP address the
You can’t perform that action at this time.
0 commit comments