python / asyncio

asyncio historical repository
https://docs.python.org/3/library/asyncio.html
1.04k stars 177 forks source link

Unable to call `recvfrom` for raw ICMP socket #438

Closed foxx closed 8 years ago

foxx commented 8 years ago

Just spent a few hours reading over issues, mailing list threads and source code, trying to determine the best approach for receiving data on a raw ICMP socket.

icmp = socket.getprotobyname("icmp")
sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp)

First suggestion was to use loop.add_reader() to listen for events, and then call sock.recvfrom() however this does not return any object reference, meaning I can't cancel the reader.

Second suggestion was to use loop.sock_recv(), but this does not return the addr like recvfrom() would, which is required for my use case.

Third was to use select.select(), but there were suggestions that this is the incorrect way to do things, and that you should be using streams and protocols instead. However there's no suitable stream/protocol class which I can use to listen for ICMP packets on a raw socket.

Someone submitted a PR to add recvfrom(), but it was rejected in favour of using create_datagram_endpoint(), which doesn't apply in my case.

Any thoughts/suggestions would be much appreciated, at the very least this warrants a docs patch to explain better how ICMP use cases should be handled.

Martiusweb commented 8 years ago

Hi,

loop.add_reader() has a converse method called loop.remove_reader(). You can call sock.recvfrom() until BlockingIOError is raised, in which case you will need to register an callback with add_reader() which will tell you when data is available on the socket. Once you have read all you needed, you can call loop.remove_reader() to prevent future notifications.

foxx commented 8 years ago

@Martiusweb Ahh, that makes more sense now, I'll play around and submit another issue if I can think of a relevant docs patch. Thank you for the swift reply!