Skip to content

Commit 9cdc4e0

Browse files
committed
Merge pull request getsentry#354 from SilentCircle/master
Add IPv6 support to UDP transport
2 parents 2cebdd8 + b1a9c61 commit 9cdc4e0

File tree

1 file changed

+23
-5
lines changed

1 file changed

+23
-5
lines changed

raven/transport/base.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
try:
1515
# Google App Engine blacklists parts of the socket module, this will prevent
1616
# it from blowing up.
17-
from socket import socket, AF_INET, SOCK_DGRAM, error as socket_error
17+
from socket import socket, AF_INET, AF_INET6, SOCK_DGRAM, has_ipv6, getaddrinfo, error as socket_error
1818
has_socket = True
1919
except:
2020
has_socket = False
@@ -114,15 +114,31 @@ def __init__(self, parsed_url):
114114
self.check_scheme(parsed_url)
115115
self._parsed_url = parsed_url
116116

117+
def _get_addr_info(self, host, port):
118+
"""
119+
Selects the address to connect to, based on the supplied host/port
120+
information. This method prefers v4 addresses, and will only return
121+
a v6 address if it's the only option.
122+
"""
123+
addresses = getaddrinfo(host, port)
124+
if has_ipv6:
125+
v6_addresses = [info for info in addresses if info[0] == AF_INET6]
126+
v4_addresses = [info for info in addresses if info[0] == AF_INET]
127+
if v6_addresses and not v4_addresses:
128+
# The only time we return a v6 address is if it's the only option
129+
return v6_addresses[0]
130+
return addresses[0]
131+
117132
def send(self, data, headers):
118133
auth_header = headers.get('X-Sentry-Auth')
119134

120135
if auth_header is None:
121136
# silently ignore attempts to send messages without an auth header
122137
return
123138

124-
host, port = self._parsed_url.netloc.split(':')
125-
self._send_data(auth_header + '\n\n' + data, (host, int(port)))
139+
host, port = self._parsed_url.netloc.rsplit(':')
140+
addr_info = self._get_addr_info(host, int(port))
141+
self._send_data(auth_header + '\n\n' + data, addr_info)
126142

127143
def compute_scope(self, url, scope):
128144
path_bits = url.path.rsplit('/', 1)
@@ -157,10 +173,12 @@ def __init__(self, parsed_url):
157173
if not has_socket:
158174
raise ImportError('UDPTransport requires the socket module')
159175

160-
def _send_data(self, data, addr):
176+
def _send_data(self, data, addr_info):
161177
udp_socket = None
178+
af = addr_info[0]
179+
addr = addr_info[4]
162180
try:
163-
udp_socket = socket(AF_INET, SOCK_DGRAM)
181+
udp_socket = socket(af, SOCK_DGRAM)
164182
udp_socket.setblocking(False)
165183
udp_socket.sendto(data, addr)
166184
except socket_error:

0 commit comments

Comments
 (0)