diff options
author | CjHanks <develop@cjhanks.name> | 2014-07-04 15:37:32 -0700 |
---|---|---|
committer | CjHanks <develop@cjhanks.name> | 2014-07-04 15:37:32 -0700 |
commit | e1b26280586bd5a4368b17796601c35a54498fea (patch) | |
tree | 425ae38bb2bae6cd7976b5355914c434874862f1 | |
parent | ffb1062d1d8e42b2375169e431007f2b589e4846 (diff) | |
download | websocket-client-e1b26280586bd5a4368b17796601c35a54498fea.tar.gz |
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.
-rw-r--r-- | websocket/_core.py | 32 |
1 files changed, 22 insertions, 10 deletions
diff --git a/websocket/_core.py b/websocket/_core.py index 780706e..5948ab3 100644 --- a/websocket/_core.py +++ b/websocket/_core.py @@ -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) |