Implementation of the CHIRP protocol draft.
- Meson 1.0.0 or newer
- GCC 12 or newer
Optional:
- Gcovr, for coverage report
Build tools in builddir
directory:
meson setup builddir
meson compile -C builddir
First build in a new directory with coverage enabled:
meson setup builddir_coverage -Db_coverage=true
meson compile -C builddir_coverage
Then run tests and create coverage report:
meson test -C builddir_coverage
ninja -C builddir coverage-html
Since CHIRP requires a fixed port and we might have multiple programs running CHIRP on one machine, it is important to ensure that the port is not blocked by one program. Networking libraries like ZeroMQ and NNG do this by default when binding to a wildcard address. To ensure that a socket can be used by more than one program, the SO_REUSEADDR
socket option has to be enabled. Further, to send broadcasts the SO_BROADCAST
socket option has to be enabled.
CHIRP uses an UDP brodcast over port 7123, which means that it send a message to all participants in a network. However, "all" in this context depends the broadcast address.
For example, if you have a device with a fixed IP (e.g. 192.168.1.17) in a subnet (e.g. 255.255.255.0), the general broadcast address (255.255.255.255) does not work. Instead, the broadcast address for the specified subnet has to be used (e.g. 192.168.1.255). On Linux, the broadcast IP for a specific network interface can found for example by running ip a
, it is the IP shown after brd
.
To opposite to the broadcast address is the "any" address, which accepts incoming traffic from any IP. In general it can be deduced from the broadcast address by replacing all 255s with 0s. However, the default any address (0.0.0.0) is enough since message filtering has to be done anyway.
If no network (with DHCP) is avaible, the default broadcast address (255.255.255.255) does not work. As a workaround, the default any address (0.0.0.0) can be used to broadcast over localhost.
TODO:
- Test if default broadcast IP (255.255.255.255) works with DHCP
- Look up if it is possible to find the broadcast IP from network interface platform independently
To receive broadcasts:
./builddir/CHIRP/test/broadcast_recv
To send broadcasts:
./builddir/CHIRP/test/broadcast_send [BRD_IP]
The broadcast IP can be specified optionally. See above for details.
To receive CHIRP messages:
./builddir/CHIRP/test/chirp_recv
To send CHIRP messages:
./builddir/CHIRP/test/chirp_send [BRD_IP]
The broadcast IP can be specified optionally. See above for details.
TODO:
- Mention MD5 hashing and service identifiers somewhere - in CHIRP itself or other RFC?
Note regarding unsubscribing: sending OFFER with port 0 is not optimal, because might have multiple services on one satellite with different ports. Let us to add a new message type instead instead:
- REQUEST always port == 0
- OFFER never port == 0
- LEAVING never port == 0
To run the CHIRP manager, run:
./builddir/CHIRP/test/chirp_manager
The following commands are available:
list_registered_services
: list of services registered by the user in the managerlist_discovered_services
: list of services discovered by the manager and are in the same groupregister_service [SERVICE] [PORT]
: register a service in the managerregister_callback [SERVICE]
: register a discover callback for a service that prints the discovered servicerequest [SERVICE]
: send a CHIRP request for a given serviceunregister_service [SERVICE] [PORT]
: unregister a service in the managerunregister_callback [SERVICE]
: unregister a discover callback for a servicereset
: unregister all services and callbacks, and forget discovered services