Fix address resolution for cases where first result is not useful.

The socket connection logic always presumed the first returned result from
socket.getaddrinfo(...) is the target.  However it is not uncommon to be
listening IPv4 while ignore IPv6.  This code iterates through the return list
until one connects without a CONNECTION REFUSED error, if all fail, the
exception is rethrown.  `man getaddrinfo` demonstrates a similar use pattern
in C.
This commit is contained in:
CjHanks
2014-07-04 15:37:32 -07:00
parent ffb1062d1d
commit e1b2628058

View File

@@ -47,6 +47,7 @@ else:
from base64 import encodestring as base64encode from base64 import encodestring as base64encode
import os import os
import errno
import struct import struct
import uuid import uuid
import hashlib import hashlib
@@ -418,16 +419,27 @@ class WebSocket(object):
if not addrinfo_list: if not addrinfo_list:
raise WebSocketException("Host not found.: " + hostname + ":" + str(port)) raise WebSocketException("Host not found.: " + hostname + ":" + str(port))
family = addrinfo_list[0][0] for addrinfo in addrinfo_list:
self.sock = socket.socket(family) family = addrinfo[0]
self.sock.settimeout(self.timeout) self.sock = socket.socket(family)
for opts in DEFAULT_SOCKET_OPTION: self.sock.settimeout(self.timeout)
self.sock.setsockopt(*opts) for opts in DEFAULT_SOCKET_OPTION:
for opts in self.sockopt: self.sock.setsockopt(*opts)
self.sock.setsockopt(*opts) for opts in self.sockopt:
# TODO: we need to support proxy self.sock.setsockopt(*opts)
address = addrinfo_list[0][4] # TODO: we need to support proxy
self.sock.connect(address) address = addrinfo[4]
try:
self.sock.connect(address)
except socket.error as error:
if error.errno in (errno.ECONNREFUSED, ):
continue
else:
raise
else:
break
else:
raise error
if proxy_host: if proxy_host:
self._tunnel(hostname, port) self._tunnel(hostname, port)