diff --git a/tests/test_udp.py b/tests/test_udp.py index d9d6e018..6f0f594c 100644 --- a/tests/test_udp.py +++ b/tests/test_udp.py @@ -284,6 +284,50 @@ async def run(): self.loop.run_until_complete(run()) + def test_socketpair(self): + peername = asyncio.Future(loop=self.loop) + + class Proto(MyDatagramProto): + def datagram_received(self, data, addr): + super().datagram_received(data, addr) + peername.set_result(addr) + + s1, s2 = socket.socketpair(socket.AF_UNIX, socket.SOCK_DGRAM, 0) + + with s1, s2: + try: + f = self.loop.create_datagram_endpoint( + lambda: Proto(loop=self.loop), sock=s1) + except TypeError as ex: + # asyncio in 3.5.0 doesn't have the 'sock' argument + if 'got an unexpected keyword argument' not in ex.args[0]: + raise + else: + tr, pr = self.loop.run_until_complete(f) + self.assertIsInstance(pr, Proto) + + s2.send(b'hello, socketpair') + addr = self.loop.run_until_complete( + asyncio.wait_for(peername, 1, loop=self.loop)) + if sys.platform.startswith('linux'): + self.assertEqual(addr, None) + else: + self.assertEqual(addr, '') + self.assertEqual(pr.nbytes, 17) + + if not self.is_asyncio_loop(): + # asyncio doesn't support sendto(xx) on UDP sockets + # https://git.io/Jfqbw + data = b'from uvloop' + tr.sendto(data) + result = self.loop.run_until_complete(asyncio.wait_for( + self.loop.run_in_executor(None, s2.recv, 1024), + 1, loop=self.loop)) + self.assertEqual(data, result) + + tr.close() + self.loop.run_until_complete(pr.done) + class Test_UV_UDP(_TestUDP, tb.UVTestCase): diff --git a/uvloop/handles/udp.pyx b/uvloop/handles/udp.pyx index 3bca6205..93596fa6 100644 --- a/uvloop/handles/udp.pyx +++ b/uvloop/handles/udp.pyx @@ -344,6 +344,12 @@ cdef void __uv_udp_on_receive(uv.uv_udp_t* handle, if addr is NULL: pyaddr = None + elif addr.sa_family == uv.AF_UNSPEC: + # https://github.com/MagicStack/uvloop/issues/304 + IF UNAME_SYSNAME == "Linux": + pyaddr = None + ELSE: + pyaddr = '' else: try: pyaddr = __convert_sockaddr_to_pyaddr(addr) @@ -356,13 +362,6 @@ cdef void __uv_udp_on_receive(uv.uv_udp_t* handle, udp._on_receive(None, exc, pyaddr) return - if pyaddr is None: - udp._fatal_error( - RuntimeError( - 'uv_udp.receive callback: addr is NULL and nread >= 0'), - False) - return - if nread == 0: data = b'' else: