浏览代码

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

Sergey M․ 7 年之前
父节点
当前提交
9e21e6d96b
共有 1 个文件被更改,包括 11 次插入7 次删除
  1. 11 7
      youtube_dl/utils.py

+ 11 - 7
youtube_dl/utils.py

@@ -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')
-        hc._create_connection = _create_connection
-
+                raise socket.error('getaddrinfo returns an empty list')
+        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(