CHIRP#
Notes on sockets#
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.
Notes on broadcast addresses#
CHIRP uses an UDP broadcast 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 available, 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.
CHIRP Manager#
To run the CHIRP manager, run:
./build/cxx/constellation/tools/chirp_manager [CONSTELLATION_GROUP] [NAME] [BRD_ADDR] [ANY_ADDR]
The following commands are available:
list_registered_services
: list of services registered by the user in the managerlist_discovered_services [SERVICE]
: 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 servicesquit
constellation::chirp
Namespace#
-
enum class constellation::chirp::MessageType : std::uint8_t#
CHIRP message type
Values:
-
enumerator REQUEST#
A message with REQUEST type indicates that CHIRP hosts should reply with an OFFER
-
enumerator OFFER#
A message with OFFER type indicates that service is available
-
enumerator DEPART#
A message with DEPART type indicates that a service is no longer available
-
enumerator REQUEST#
-
enum class constellation::chirp::ServiceIdentifier : std::uint8_t#
CHIRP service identifier
Values:
-
enumerator CONTROL#
The CONTROL service identifier indicates a CSCP (Constellation Satellite Control Protocol) service
-
enumerator HEARTBEAT#
The HEARTBEAT service identifier indicates a CHP (Constellation Heartbeat Protocol) service
-
enumerator MONITORING#
The MONITORING service identifier indicates a CMDP (Constellation Monitoring Distribution Protocol) service
-
enumerator DATA#
The DATA service identifier indicates a CDTP (Constellation Data Transmission Protocol) service
-
enumerator CONTROL#
-
enum class constellation::chirp::ServiceStatus : std::uint8_t#
Status of a service for callbacks from the
Manager
Values:
-
enumerator DISCOVERED#
The service is newly discovered
-
enumerator DEPARTED#
The service departed
-
enumerator DEAD#
The service is considered dead without departure
-
enumerator DISCOVERED#
-
using constellation::chirp::DiscoverCallback = void(DiscoveredService service, ServiceStatus status, std::any user_data)#
Function signature for user callback
The first argument (
service
) contains the discovered service, the second argument is an enum that indicates the status of the service, i.e. whether it is newly discovered, departing, or considered dead, and the third argument (user_data
) is arbitrary user data passed to the callback (done viaManager::RegisterDiscoverCallback
).It is recommended to pass the user data wrapped in an atomic
std::shared_ptr
since the callback is launched asynchronously in a detachedstd::thread
. If the data is modified, it is recommended to use atomic types when possible or astd::mutex
for locking to ensure thread-safe access.
-
std::string_view constellation::chirp::CHIRP_IDENTIFIER = "CHIRP"#
Protocol identifier for CHIRP
-
std::uint8_t constellation::chirp::CHIRP_VERSION = '\x01'#
Version of CHIRP protocol
-
std::size_t constellation::chirp::CHIRP_MESSAGE_LENGTH = 42#
CHIRP Message length in bytes
-
struct BroadcastMessage#
- #include <constellation/core/chirp/BroadcastRecv.hpp>
Incoming broadcast message
Public Functions
-
std::string to_string() const#
Convert the content of the broadcast message to a string
-
std::string to_string() const#
-
class BroadcastRecv#
- #include <constellation/core/chirp/BroadcastRecv.hpp>
Broadcast receiver for incoming CHIRP broadcasts on
CHIRP_PORT
Public Functions
-
BroadcastRecv(const asio::ip::address_v4 &any_address, asio::ip::port_type port)#
Construct broadcast receiver
- Parameters:
any_address – Address for incoming broadcasts (e.g.
asio::ip::address_v4::any()
)port – Port for outgoing broadcasts
-
BroadcastRecv(std::string_view any_ip, asio::ip::port_type port)#
Construct broadcast receiver using human readable IP address
- Parameters:
any_ip – String containing the IP for incoming broadcasts (e.g.
0.0.0.0
)port – Port for outgoing broadcasts
-
BroadcastMessage recvBroadcast()#
Receive broadcast message (blocking)
- Returns:
Received broadcast message
-
std::optional<BroadcastMessage> asyncRecvBroadcast(std::chrono::steady_clock::duration timeout)#
Receive broadcast message (asynchronously)
- Parameters:
timeout – Duration for which to block function call
- Returns:
Broadcast message if received
-
BroadcastRecv(const asio::ip::address_v4 &any_address, asio::ip::port_type port)#
-
class BroadcastSend#
- #include <constellation/core/chirp/BroadcastSend.hpp>
Broadcast sender for outgoing broadcasts
Public Functions
-
BroadcastSend(const std::set<asio::ip::address_v4> &brd_addresses, asio::ip::port_type port)#
Construct broadcast sender
- Parameters:
brd_addresses – Set of broadcast addresses for outgoing broadcasts
port – Port for outgoing broadcasts
-
BroadcastSend(std::string_view brd_ip, asio::ip::port_type port)#
Construct broadcast sender using a single human readable IP address
- Parameters:
brd_ip – String containing the broadcast IP for outgoing broadcasts (e.g.
255.255.255.255
)port – Port for outgoing broadcasts
-
void sendBroadcast(std::string_view message)#
Send broadcast message from string
- Parameters:
message – String with broadcast message
-
void sendBroadcast(std::span<const std::byte> message)#
Send broadcast message
- Parameters:
message – View of message in bytes
-
BroadcastSend(const std::set<asio::ip::address_v4> &brd_addresses, asio::ip::port_type port)#
-
struct DiscoverCallbackEntry#
- #include <constellation/core/chirp/Manager.hpp>
Entry for a user callback in the
Manager
for newly discovered or departing servicesPublic Functions
-
bool operator<(const DiscoverCallbackEntry &other) const#
Public Members
-
DiscoverCallback *callback#
Function pointer to a callback
-
ServiceIdentifier service_id#
Service identifier of the service for which callbacks should be received
-
std::any user_data#
Arbitrary user data passed to the callback function
For information on lifetime and thread-safety see
DiscoverCallback
.
-
bool operator<(const DiscoverCallbackEntry &other) const#
-
struct DiscoveredService#
- #include <constellation/core/chirp/Manager.hpp>
A service discovered by the
Manager
Public Functions
-
std::string to_uri() const#
Convert service information to a URI
-
bool operator<(const DiscoveredService &other) const#
-
std::string to_uri() const#
-
class Manager#
- #include <constellation/core/chirp/Manager.hpp>
Manager for CHIRP broadcasting and receiving
Public Functions
-
void setAsDefaultInstance()#
Set this CHIRP manager as the default instance
-
Manager(const std::optional<asio::ip::address_v4> &brd_address, const asio::ip::address_v4 &any_address, std::string_view group_name, std::string_view host_name)#
- Parameters:
brd_address – Broadcast address for outgoing broadcast messages
any_address – Any address for incoming broadcast messages
group_name – Group name of the group to join
host_name – Host name for outgoing messages
-
Manager(std::string_view brd_ip, std::string_view any_ip, std::string_view group_name, std::string_view host_name)#
- Parameters:
brd_ip – Broadcast IP for outgoing broadcast messages
any_ip – Any IP for incoming broadcast messages
group_name – Group name of the group to join
host_name – Host name for outgoing messages
-
virtual ~Manager()#
-
inline message::MD5Hash getGroupID() const#
- Returns:
Group ID (MD5Hash of the group name)
-
inline message::MD5Hash getHostID() const#
- Returns:
Host ID (MD5Hash of the host name)
-
void start()#
Start the background thread of the manager
-
bool registerService(ServiceIdentifier service_id, networking::Port port)#
Register a service offered by the host in the manager
Calling this function sends a CHIRP broadcast with OFFER type, and registers the service such that the manager responds to CHIRP broadcasts with REQUEST type and the corresponding service identifier.
- Parameters:
service_id – Service identifier of the offered service
port – Port of the offered service
- Return values:
true – if the service was registered
false – if the service was already registered
-
bool unregisterService(ServiceIdentifier service_id, networking::Port port)#
Unregister a previously registered service offered by the host in the manager
Calling this function sends a CHIRP broadcast with DEPART type and removes the service from manager. See also
RegisterService
.- Parameters:
service_id – Service identifier of the previously offered service
port – Port of the previously offered service
- Return values:
true – If the service was unregistered
false – If the service was never registered
-
void unregisterServices()#
Unregisters all offered services registered in the manager
Equivalent to calling
UnregisterService
for every registered service.
-
std::set<RegisteredService> getRegisteredServices()#
Get the list of services currently registered in the manager
- Returns:
Set with all currently registered services
-
bool registerDiscoverCallback(DiscoverCallback *callback, ServiceIdentifier service_id, std::any user_data)#
Register a user callback for newly discovered or departing services
Note that a callback function can be registered multiple times for different services.
Warning
Discover callbacks block the execution of further processing of CHIRP requests and offers, callbacks that take a long time should offload the work to a new thread.
- Parameters:
callback – Function pointer to a callback
service_id – Service identifier of the service for which callbacks should be received
user_data – Arbitrary user data passed to the callback function (see
DiscoverCallback
)
- Return values:
true – If the callback/service/user_data combination was registered
false – If the callback/service/user_data combination was already registered
-
bool unregisterDiscoverCallback(DiscoverCallback *callback, ServiceIdentifier service_id)#
Unregister a previously registered callback for newly discovered or departing services
- Parameters:
callback – Function pointer to the callback of registered callback entry
service_id – Service identifier of registered callback entry
- Return values:
true – If the callback entry was unregistered
false – If the callback entry was never registered
-
void unregisterDiscoverCallbacks()#
Unregisters all discovery callbacks registered in the manager
Equivalent to calling
UnregisterDiscoverCallback
for every discovery callback.
-
void forgetDiscoveredService(ServiceIdentifier identifier, message::MD5Hash host_id)#
Forget the previously discovered services of the given type and host ID, if present.
- Parameters:
identifier – Identifier of the discovered service to be forgotten
host_id – Host ID of the discovered service to be forgotten
-
void forgetDiscoveredServices(message::MD5Hash host_id)#
Forget all previously discovered services of a given host.
- Parameters:
host_id – Host ID of the discovered services to be forgotten
-
void forgetDiscoveredServices()#
Forget all previously discovered services
-
std::vector<DiscoveredService> getDiscoveredServices()#
Returns list of all discovered services
- Returns:
Vector with all discovered services
-
std::vector<DiscoveredService> getDiscoveredServices(ServiceIdentifier service_id)#
Returns list of all discovered services with a given service identifier
- Parameters:
service_id – Service identifier for discovered services that should be listed
- Returns:
Vector with all discovered services with the given service identifier
-
void sendRequest(ServiceIdentifier service_id)#
Send a discovery request for a specific service identifier
This sends a CHIRP broadcast with a REQUEST type and a given service identifier. Other hosts might reply with a CHIRP broadcast with OFFER type for the given service identifier. These can be retrieved either by registering a user callback (see
RegisterDiscoverCallback
) or by getting the list of discovered services shortly after (seeGetDiscoveredServices
).- Parameters:
service_id – Service identifier to send a request for
-
void setAsDefaultInstance()#
-
struct RegisteredService#
- #include <constellation/core/chirp/Manager.hpp>
A service offered by the host and announced by the
Manager
Public Functions
-
bool operator<(const RegisteredService &other) const#
Public Members
-
ServiceIdentifier identifier#
Service identifier of the offered service
-
bool operator<(const RegisteredService &other) const#