chrysn / aiocoap

The Python CoAP library
Other
264 stars 119 forks source link

Support for broadcast addresses when using UDP transport #291

Open mzpqnxow opened 1 year ago

mzpqnxow commented 1 year ago

This isn't a bug, it's just a placeholder to explain a PR

I recently had the need to use broadcast (not multicast) to integrate with software I did not write, that performs discover on across a layer-2 network. Though aiocoap has support for multicast, there's no support for broadcast, as is evidenced here:

17:03:34 ›  aiocoap-client coap://192.168.1.255/.well-known/core -m GET -vvv        
DEBUG:coap:Sending request - Token: eedd, Remote: <UDP6EndpointAddress 192.168.1.255>
DEBUG:coap:Sending message <aiocoap.Message at 0x7fa89b4a0370: Type.CON GET (MID 54678, token eedd) remote <UDP6EndpointAddress 192.168.3.255>, 1 option(s)>
DEBUG:coap:Exchange added, message ID: 54678.
ERROR:coap:Error received and ignored in this codepath: [Errno 13] Permission denied

The EPERM is misleading, though not the fault of Python or aiocoap ; this is what various socket system calls return when used with a broadcast address but without having explicitly used setsockopt() to set the SO_BROADCAST bit to 1 on the socket

I won't try to argue that the software I'm interfacing with made the right decision in using broadcast rather than multicast. I'm very new to COAP and have not read any of the RFCs so pardon me if this violates the RFC. It wasn't my idea, I'm just stuck with it :)

I'm sending a PR in a few moments that does the bare minimum to make aiocoap-client interact happily when the COAP endpoint is a broadcast address. I tried to be as "light-touch" as possible

Environment

I don't think this is really necessary in this case, but can't hurt:

OS:

$ uname -a
Linux server01 5.10.0-9-amd64 #1 SMP Debian 5.10.70-1 (2021-09-30) x86_64 GNU/Linux

Python and aiocoap versions / build-time libraries/supported transports

Python version: 3.9.2 (default, Feb 28 2021, 17:03:44) 
[GCC 10.2.1 20210110]
aiocoap version: 0.4.4.post0
Modules missing for subsystems:
    dtls: everything there
    oscore: everything there
    linkheader: everything there
    prettyprint: everything there
Python platform: linux
Default server transports:  oscore:tinydtls:tcpserver:tcpclient:tlsserver:tlsclient:ws:udp6
Selected server transports: oscore:tinydtls:tcpserver:tcpclient:tlsserver:tlsclient:ws:udp6
Default client transports:  oscore:tinydtls:tcpclient:tlsclient:ws:udp6
Selected client transports: oscore:tinydtls:tcpclient:tlsclient:ws:udp6
SO_REUSEPORT available (default, selected): True, True
chrysn commented 1 year ago

This isn't a bug, it's just a placeholder to explain a PR

Very much appreciated!

I wasn't aware broadcast is still used anywhere (really IPv4 support is an afterthought here), but if there's a simple fix, then by all means let's fix this :-)

mzpqnxow commented 1 year ago

This isn't a bug, it's just a placeholder to explain a PR

Very much appreciated!

I wasn't aware broadcast is still used anywhere (really IPv4 support is an afterthought here), but if there's a simple fix, then by all means let's fix this :-)

I was surprised as well, especially because the product I encountered seems to have adopted multicast for almost everything else. shrug

Thanks for being open to contributions. I don't usually mind maintaining a fork with minor changes, but it's obviously a little less hassle from my life when things are merged upstream