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
import os
import errno
import struct
import uuid
import hashlib
@@ -418,16 +419,27 @@ class WebSocket(object):
if not addrinfo_list:
raise WebSocketException("Host not found.: " + hostname + ":" + str(port))
family = addrinfo_list[0][0]
self.sock = socket.socket(family)
self.sock.settimeout(self.timeout)
for opts in DEFAULT_SOCKET_OPTION:
self.sock.setsockopt(*opts)
for opts in self.sockopt:
self.sock.setsockopt(*opts)
# TODO: we need to support proxy
address = addrinfo_list[0][4]
self.sock.connect(address)
for addrinfo in addrinfo_list:
family = addrinfo[0]
self.sock = socket.socket(family)
self.sock.settimeout(self.timeout)
for opts in DEFAULT_SOCKET_OPTION:
self.sock.setsockopt(*opts)
for opts in self.sockopt:
self.sock.setsockopt(*opts)
# TODO: we need to support proxy
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:
self._tunnel(hostname, port)