Skip to content

Commit 9e017e6

Browse files
committed
Accept empty addr in UDP on_receive
* Fixes #304
1 parent d51ce36 commit 9e017e6

File tree

2 files changed

+50
-7
lines changed

2 files changed

+50
-7
lines changed

tests/test_udp.py

+44
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,50 @@ async def run():
284284

285285
self.loop.run_until_complete(run())
286286

287+
def test_socketpair(self):
288+
peername = asyncio.Future(loop=self.loop)
289+
290+
class Proto(MyDatagramProto):
291+
def datagram_received(self, data, addr):
292+
super().datagram_received(data, addr)
293+
peername.set_result(addr)
294+
295+
s1, s2 = socket.socketpair(socket.AF_UNIX, socket.SOCK_DGRAM, 0)
296+
297+
with s1, s2:
298+
try:
299+
f = self.loop.create_datagram_endpoint(
300+
lambda: Proto(loop=self.loop), sock=s1)
301+
except TypeError as ex:
302+
# asyncio in 3.5.0 doesn't have the 'sock' argument
303+
if 'got an unexpected keyword argument' not in ex.args[0]:
304+
raise
305+
else:
306+
tr, pr = self.loop.run_until_complete(f)
307+
self.assertIsInstance(pr, Proto)
308+
309+
s2.send(b'hello, socketpair')
310+
addr = self.loop.run_until_complete(
311+
asyncio.wait_for(peername, 1, loop=self.loop))
312+
if sys.platform.startswith('linux'):
313+
self.assertEqual(addr, None)
314+
else:
315+
self.assertEqual(addr, '')
316+
self.assertEqual(pr.nbytes, 17)
317+
318+
if not self.is_asyncio_loop():
319+
# asyncio doesn't support sendto(xx) on UDP sockets
320+
# https://git.io/Jfqbw
321+
data = b'from uvloop'
322+
tr.sendto(data)
323+
result = self.loop.run_until_complete(asyncio.wait_for(
324+
self.loop.run_in_executor(None, s2.recv, 1024),
325+
1, loop=self.loop))
326+
self.assertEqual(data, result)
327+
328+
tr.close()
329+
self.loop.run_until_complete(pr.done)
330+
287331

288332
class Test_UV_UDP(_TestUDP, tb.UVTestCase):
289333

uvloop/handles/udp.pyx

+6-7
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,12 @@ cdef void __uv_udp_on_receive(uv.uv_udp_t* handle,
344344

345345
if addr is NULL:
346346
pyaddr = None
347+
elif addr.sa_family == uv.AF_UNSPEC:
348+
# https://github.com/MagicStack/uvloop/issues/304
349+
IF UNAME_SYSNAME == "Linux":
350+
pyaddr = None
351+
ELSE:
352+
pyaddr = ''
347353
else:
348354
try:
349355
pyaddr = __convert_sockaddr_to_pyaddr(addr)
@@ -356,13 +362,6 @@ cdef void __uv_udp_on_receive(uv.uv_udp_t* handle,
356362
udp._on_receive(None, exc, pyaddr)
357363
return
358364

359-
if pyaddr is None:
360-
udp._fatal_error(
361-
RuntimeError(
362-
'uv_udp.receive callback: addr is NULL and nread >= 0'),
363-
False)
364-
return
365-
366365
if nread == 0:
367366
data = b''
368367
else:

0 commit comments

Comments
 (0)