Skip to content
This repository was archived by the owner on Oct 23, 2023. It is now read-only.
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 23 additions & 5 deletions raven/transport/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
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
Expand Down Expand Up @@ -114,15 +114,31 @@ def __init__(self, parsed_url):
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')

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

host, port = self._parsed_url.netloc.split(':')
self._send_data(auth_header + '\n\n' + data, (host, int(port)))
host, port = self._parsed_url.netloc.rsplit(':')
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)
Expand Down Expand Up @@ -157,10 +173,12 @@ def __init__(self, parsed_url):
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:
Expand Down