summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCjHanks <develop@cjhanks.name>2014-07-04 15:37:32 -0700
committerCjHanks <develop@cjhanks.name>2014-07-04 15:37:32 -0700
commite1b26280586bd5a4368b17796601c35a54498fea (patch)
tree425ae38bb2bae6cd7976b5355914c434874862f1
parentffb1062d1d8e42b2375169e431007f2b589e4846 (diff)
downloadwebsocket-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.py32
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)