Skip to content

Commit d5ad2b8

Browse files
jlaine1st1
authored andcommitted
Improve UDPTransport.sendto address validation (fixes: #214)
When UDPTransport.sendto is called with a destination address, only perform the validation once and store the result in an LRU cache. Also store some of the socket's properties (family, proto, type) as integers to avoid repeatedly fetching these properties and converting them to integers.
1 parent df0e543 commit d5ad2b8

File tree

2 files changed

+25
-13
lines changed

2 files changed

+25
-13
lines changed

uvloop/handles/udp.pxd

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
cdef class UDPTransport(UVBaseTransport):
22
cdef:
33
object sock
4+
int sock_family
5+
int sock_proto
6+
int sock_type
47
UVPoll poll
58
object address
69
object buffer

uvloop/handles/udp.pyx

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,19 @@
1-
import socket
1+
import functools
2+
3+
4+
@functools.lru_cache()
5+
def validate_address(object addr, int sock_family, int sock_type,
6+
int sock_proto):
7+
addrinfo = __static_getaddrinfo_pyaddr(
8+
addr[0], addr[1],
9+
uv.AF_UNSPEC, sock_type, sock_proto, 0)
10+
if addrinfo is None:
11+
raise ValueError(
12+
'UDP.sendto(): address {!r} requires a DNS lookup'.format(addr))
13+
if addrinfo[0] != sock_family:
14+
raise ValueError(
15+
'UDP.sendto(): {!r} socket family mismatch'.format(addr))
16+
217

318
cdef class UDPTransport(UVBaseTransport):
419

@@ -17,6 +32,9 @@ cdef class UDPTransport(UVBaseTransport):
1732
socket_inc_io_ref(sock)
1833

1934
self.sock = sock
35+
self.sock_family = sock.family
36+
self.sock_proto = sock.proto
37+
self.sock_type = sock.type
2038
self.address = r_addr
2139
self.poll = UVPoll.new(loop, sock.fileno())
2240
self._finish_init()
@@ -143,18 +161,9 @@ cdef class UDPTransport(UVBaseTransport):
143161
raise ValueError(
144162
'Invalid address: must be None or {}'.format(self.address))
145163

146-
if addr is not None and self.sock.family != socket.AF_UNIX:
147-
addrinfo = __static_getaddrinfo_pyaddr(
148-
addr[0], addr[1],
149-
uv.AF_UNSPEC, self.sock.type, self.sock.proto, 0)
150-
if addrinfo is None:
151-
raise ValueError(
152-
'UDP.sendto(): address {!r} requires a DNS lookup'.format(
153-
addr))
154-
if addrinfo[0] != self.sock.family:
155-
raise ValueError(
156-
'UDP.sendto(): {!r} socket family mismatch'.format(
157-
addr))
164+
if addr is not None and self.sock_family != uv.AF_UNIX:
165+
validate_address(addr, self.sock_family, self.sock_type,
166+
self.sock_proto)
158167

159168
if self._conn_lost and self._address:
160169
if self._conn_lost >= LOG_THRESHOLD_FOR_CONNLOST_WRITES:

0 commit comments

Comments
 (0)