summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Wright <josh.wright@silentcircle-llc.com>2013-09-01 09:00:49 -0400
committerJosh Wright <josh.wright@silentcircle-llc.com>2013-09-01 09:00:49 -0400
commitb1a9c618584b793d1e48fde135e9fb9b83a90398 (patch)
tree37a4a08557b6eec7d03ae88764dbcc8ded2f829c
parent08d4dcbf482de3ded8ab2db870607a2d84951b8e (diff)
downloadraven-b1a9c618584b793d1e48fde135e9fb9b83a90398.tar.gz
Add IPv6 support for UDP transports (IPv4 is preferred)
-rw-r--r--raven/transport/base.py26
1 files changed, 22 insertions, 4 deletions
diff --git a/raven/transport/base.py b/raven/transport/base.py
index 257198a..12fa88f 100644
--- a/raven/transport/base.py
+++ b/raven/transport/base.py
@@ -14,7 +14,7 @@ from raven.utils import compat, six
try:
# Google App Engine blacklists parts of the socket module, this will prevent
# it from blowing up.
- from socket import socket, AF_INET, SOCK_DGRAM, error as socket_error
+ from socket import socket, AF_INET, AF_INET6, SOCK_DGRAM, has_ipv6, getaddrinfo, error as socket_error
has_socket = True
except:
has_socket = False
@@ -114,6 +114,21 @@ class BaseUDPTransport(Transport):
self.check_scheme(parsed_url)
self._parsed_url = parsed_url
+ def _get_addr_info(self, host, port):
+ """
+ Selects the address to connect to, based on the supplied host/port
+ information. This method prefers v4 addresses, and will only return
+ a v6 address if it's the only option.
+ """
+ addresses = getaddrinfo(host, port)
+ if has_ipv6:
+ v6_addresses = [info for info in addresses if info[0] == AF_INET6]
+ v4_addresses = [info for info in addresses if info[0] == AF_INET]
+ if v6_addresses and not v4_addresses:
+ # The only time we return a v6 address is if it's the only option
+ return v6_addresses[0]
+ return addresses[0]
+
def send(self, data, headers):
auth_header = headers.get('X-Sentry-Auth')
@@ -122,7 +137,8 @@ class BaseUDPTransport(Transport):
return
host, port = self._parsed_url.netloc.rsplit(':')
- self._send_data(auth_header + '\n\n' + data, (host, int(port)))
+ addr_info = self._get_addr_info(host, int(port))
+ self._send_data(auth_header + '\n\n' + data, addr_info)
def compute_scope(self, url, scope):
path_bits = url.path.rsplit('/', 1)
@@ -157,10 +173,12 @@ class UDPTransport(BaseUDPTransport):
if not has_socket:
raise ImportError('UDPTransport requires the socket module')
- def _send_data(self, data, addr):
+ def _send_data(self, data, addr_info):
udp_socket = None
+ af = addr_info[0]
+ addr = addr_info[4]
try:
- udp_socket = socket(AF_INET, SOCK_DGRAM)
+ udp_socket = socket(af, SOCK_DGRAM)
udp_socket.setblocking(False)
udp_socket.sendto(data, addr)
except socket_error: