[utils] Improve remote address skipping and add support for python 2.6 (closes #17362)

This commit is contained in:
Sergey M․ 2018-08-29 01:17:21 +07:00
parent 8959018a5f
commit 9e21e6d96b
No known key found for this signature in database
GPG Key ID: 2C393E0F18A9236D

View File

@ -49,7 +49,6 @@ from .compat import (
compat_os_name, compat_os_name,
compat_parse_qs, compat_parse_qs,
compat_shlex_quote, compat_shlex_quote,
compat_socket_create_connection,
compat_str, compat_str,
compat_struct_pack, compat_struct_pack,
compat_struct_unpack, compat_struct_unpack,
@ -884,7 +883,6 @@ def _create_http_connection(ydl_handler, http_class, is_https, *args, **kwargs):
source_address = ydl_handler._params.get('source_address') source_address = ydl_handler._params.get('source_address')
if source_address is not None: if source_address is not None:
filter_for = socket.AF_INET if '.' in source_address else socket.AF_INET6
# This is to workaround _create_connection() from socket where it will try all # This is to workaround _create_connection() from socket where it will try all
# address data from getaddrinfo() including IPv6. This filters the result from # address data from getaddrinfo() including IPv6. This filters the result from
# getaddrinfo() based on the source_address value. # getaddrinfo() based on the source_address value.
@ -894,7 +892,13 @@ def _create_http_connection(ydl_handler, http_class, is_https, *args, **kwargs):
host, port = address host, port = address
err = None err = None
addrs = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM) addrs = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM)
ip_addrs = [addr for addr in addrs if addr[0] == filter_for] af = socket.AF_INET if '.' in source_address[0] else socket.AF_INET6
ip_addrs = [addr for addr in addrs if addr[0] == af]
if addrs and not ip_addrs:
ip_version = 'v4' if af == socket.AF_INET else 'v6'
raise socket.error(
"No remote IP%s addresses available for connect, can't use '%s' as source address"
% (ip_version, source_address[0]))
for res in ip_addrs: for res in ip_addrs:
af, socktype, proto, canonname, sa = res af, socktype, proto, canonname, sa = res
sock = None sock = None
@ -913,15 +917,15 @@ def _create_http_connection(ydl_handler, http_class, is_https, *args, **kwargs):
if err is not None: if err is not None:
raise err raise err
else: else:
raise socket.error('Unknown error occurred') raise socket.error('getaddrinfo returns an empty list')
hc._create_connection = _create_connection if hasattr(hc, '_create_connection'):
hc._create_connection = _create_connection
sa = (source_address, 0) sa = (source_address, 0)
if hasattr(hc, 'source_address'): # Python 2.7+ if hasattr(hc, 'source_address'): # Python 2.7+
hc.source_address = sa hc.source_address = sa
else: # Python 2.6 else: # Python 2.6
def _hc_connect(self, *args, **kwargs): def _hc_connect(self, *args, **kwargs):
sock = compat_socket_create_connection( sock = _create_connection(
(self.host, self.port), self.timeout, sa) (self.host, self.port), self.timeout, sa)
if is_https: if is_https:
self.sock = ssl.wrap_socket( self.sock = ssl.wrap_socket(