Skip to content

Commit

Permalink
apply bpo-37228
Browse files Browse the repository at this point in the history
  • Loading branch information
Olaf1022 committed May 13, 2020
1 parent a2af8cb commit 67cb48e
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 16 deletions.
41 changes: 41 additions & 0 deletions tests/test_udp.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,47 @@ def datagram_received(self, data, addr):
tr.close()
self.loop.run_until_complete(pr.done)

def _skip_create_datagram_endpoint_reuse_addr(self):
if self.implementation == 'asyncio':
if sys.version_info[:2] >= (3, 11):
raise unittest.SkipTest()
if (3, 8, 0) <= sys.version_info < (3, 8, 1):
raise unittest.SkipTest()
if (3, 7, 0) <= sys.version_info < (3, 7, 6):
raise unittest.SkipTest()
if sys.version_info < (3, 6, 10):
raise unittest.SkipTest()

def test_create_datagram_endpoint_reuse_address_error(self):
# bpo-37228: Ensure that explicit passing of `reuse_address=True`
# raises an error, as it is not safe to use SO_REUSEADDR when using UDP

self._skip_create_datagram_endpoint_reuse_addr()

coro = self.loop.create_datagram_endpoint(
lambda: MyDatagramProto(loop=self.loop),
local_addr=('127.0.0.1', 0),
reuse_address=True)

with self.assertRaises(ValueError):
self.loop.run_until_complete(coro)

def test_create_datagram_endpoint_reuse_address_warning(self):
# bpo-37228: Deprecate *reuse_address* parameter

self._skip_create_datagram_endpoint_reuse_addr()

coro = self.loop.create_datagram_endpoint(
lambda: MyDatagramProto(loop=self.loop),
local_addr=('127.0.0.1', 0),
reuse_address=False)

with self.assertWarns(DeprecationWarning):
tr, pr = self.loop.run_until_complete(coro)

tr.close()
self.loop.run_until_complete(pr.done)


class Test_UV_UDP(_TestUDP, tb.UVTestCase):

Expand Down
2 changes: 1 addition & 1 deletion uvloop/handles/udp.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ cdef class UDPTransport(UVBaseTransport):

cdef _connect(self, system.sockaddr* addr, size_t addr_len)

cdef _bind(self, system.sockaddr* addr, bint reuse_addr)
cdef _bind(self, system.sockaddr* addr)
cdef open(self, int family, int sockfd)
cdef _set_broadcast(self, bint on)

Expand Down
5 changes: 1 addition & 4 deletions uvloop/handles/udp.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -104,16 +104,13 @@ cdef class UDPTransport(UVBaseTransport):
exc = convert_error(err)
raise exc

cdef _bind(self, system.sockaddr* addr, bint reuse_addr):
cdef _bind(self, system.sockaddr* addr):
cdef:
int err
int flags = 0

self._ensure_alive()

if reuse_addr:
flags |= uv.UV_UDP_REUSEADDR

err = uv.uv_udp_bind(<uv.uv_udp_t*>self._handle, addr, flags)
if err < 0:
exc = convert_error(err)
Expand Down
3 changes: 1 addition & 2 deletions uvloop/includes/uv.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,7 @@ cdef extern from "uv.h" nogil:

ctypedef enum uv_udp_flags:
UV_UDP_IPV6ONLY = 1,
UV_UDP_PARTIAL = 2,
UV_UDP_REUSEADDR = 4
UV_UDP_PARTIAL = 2

ctypedef enum uv_membership:
UV_LEAVE_GROUP = 0,
Expand Down
27 changes: 18 additions & 9 deletions uvloop/loop.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ cdef inline socket_dec_io_ref(sock):
sock._decref_socketios()


# Used for deprecation and removal of `loop.create_datagram_endpoint()`'s
# *reuse_address* parameter
_unset = object()


@cython.no_gc_clear
cdef class Loop:
def __cinit__(self):
Expand Down Expand Up @@ -2924,7 +2929,7 @@ cdef class Loop:
async def create_datagram_endpoint(self, protocol_factory,
local_addr=None, remote_addr=None, *,
family=0, proto=0, flags=0,
reuse_address=None, reuse_port=None,
reuse_address=_unset, reuse_port=None,
allow_broadcast=None, sock=None):
"""A coroutine which creates a datagram endpoint.
Expand All @@ -2936,11 +2941,6 @@ cdef class Loop:
socket family AF_INET or socket.AF_INET6 depending on host (or
family if specified), socket type SOCK_DGRAM.
reuse_address tells the kernel to reuse a local socket in
TIME_WAIT state, without waiting for its natural timeout to
expire. If not specified it will automatically be set to True on
UNIX.
reuse_port tells the kernel to allow this endpoint to be bound to
the same port as other existing endpoints are bound to, so long as
they all set this flag when being created. This option is not
Expand All @@ -2965,7 +2965,7 @@ cdef class Loop:
'A UDP Socket was expected, got {!r}'.format(sock))
if (local_addr or remote_addr or
family or proto or flags or
reuse_address or reuse_port or allow_broadcast):
reuse_port or allow_broadcast):
# show the problematic kwargs in exception msg
opts = dict(local_addr=local_addr, remote_addr=remote_addr,
family=family, proto=proto, flags=flags,
Expand All @@ -2982,7 +2982,16 @@ cdef class Loop:
udp.open(sock.family, sock.fileno())
udp._attach_fileobj(sock)
else:
reuse_address = bool(reuse_address)
if reuse_address is not _unset:
if reuse_address:
raise ValueError("Passing `reuse_address=True` is no "
"longer supported, as the usage of "
"SO_REUSEPORT in UDP poses a significant "
"security concern.")
else:
warnings_warn("The *reuse_address* parameter has been "
"deprecated as of 0.15.", DeprecationWarning,
stacklevel=2)
reuse_port = bool(reuse_port)
if reuse_port and not has_SO_REUSEPORT:
raise ValueError(
Expand Down Expand Up @@ -3035,7 +3044,7 @@ cdef class Loop:
udp._init(self, lai.ai_family)
if reuse_port:
self._sock_set_reuseport(udp._fileno())
udp._bind(lai.ai_addr, reuse_address)
udp._bind(lai.ai_addr)
except (KeyboardInterrupt, SystemExit):
raise
except BaseException as ex:
Expand Down

0 comments on commit 67cb48e

Please sign in to comment.