Mads
Multi-Agent Distributed System
Loading...
Searching...
No Matches
/home/runner/work/MADS/MADS/src/agent.hpp

The Agent class represents an agent in the mads system.

The Agent class represents an agent in the mads system.An agent is an entity that can send and receive messages through ZeroMQ sockets. It is responsible for loading settings, connecting to the appropriate endpoints, and publishing and receiving messages.

// suppose that you have the derived class MyAgent // Create a MyAgent object with the name "myagent" and the settings file MyAgent myagent("myagent", "settings.ini"); myagent.init(); // may throw an error is ini file has errors // either of the two or bothMyAgent: myagent.connect_pub(); myagent.connect_sub(); // get info about the myagent myagent.info(); // Start a main loop with a lambda function: myagent.loop([&]() { // receive a message myagent.receive(); // get the last message received myagent.last_message(); // get the status of the myagent agent, i.e. a map of all last messages by // topics auto status = myagent.status(); string msg = status["topic1"]; // publish a message myagent.publish(json_object.dump()); });

/*
_ _ _
/ \ __ _ ___ _ __ | |_ ___| | __ _ ___ ___
/ _ \ / _` |/ _ \ '_ \| __| / __| |/ _` / __/ __|
/ ___ \ (_| | __/ | | | |_ | (__| | (_| \__ \__ \
/_/ \_\__, |\___|_| |_|\__| \___|_|\__,_|___/___/
|___/
Base class for all agents. This class is used to define the basic
functionalities provided by all agents. Each agent subclass must implement the
pure virtual functions defined in this class (currently none)
Author(s): Paolo Bosetti
*/
#ifndef AGENT_HPP
#define AGENT_HPP
#if defined _WIN32 && !defined NOMINMAX
#define NOMINMAX
#endif
#include "mads.hpp"
#include <nlohmann/json.hpp>
#ifdef _WIN32
#include <winsock2.h>
#else
#include <unistd.h>
#endif
#ifndef _MSC_VER
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunknown-attributes"
#endif
#include <toml++/toml.hpp>
#ifndef _MSC_VER
#pragma GCC diagnostic pop
#endif
#include <iostream>
#include <regex>
#include <string>
#include <string_view>
#include <thread>
#include <future>
#include <zmq.hpp>
#include <zmq_addon.hpp>
#include <mutex>
#include <condition_variable>
#include <optional>
#include <span>
#include <atomic>
#include <memory>
#include "clock_offset.hpp"
#include "curve.hpp"
#include "exec_path.hpp"
#include "topic_match.hpp"
#ifndef HOST_NAME_MAX
#define HOST_NAME_MAX 255
#endif
#ifndef MADS_AGENT_NO_INFO
#include <rang.hpp>
using namespace rang;
#endif
namespace Mads {
template<typename T> struct SharedLatest {
std::mutex mtx;
std::condition_variable cv;
std::optional<T> value;
};
class LazyPayload {
public:
LazyPayload() = default;
static LazyPayload from_text(std::string text) {
p._text = std::move(text);
return p;
}
static LazyPayload from_doc(nlohmann::json doc) {
p._doc = std::move(doc);
return p;
}
const std::string &text() const {
if (!_text)
_text = _doc ? _doc->dump() : std::string();
return *_text;
}
const nlohmann::json &doc() const {
if (!_doc) {
if (_text && !_text->empty())
_doc = nlohmann::json::parse(*_text);
else
_doc = nlohmann::json();
}
return *_doc;
}
private:
mutable std::optional<std::string> _text;
mutable std::optional<nlohmann::json> _doc;
};
struct ClockPeerObservation {
std::string responder_agent_id;
std::string responder_name;
std::string responder_hostname;
std::string responder_domain;
ClockSample sample;
ClockOffsetResult responder_adopted;
};
class Agent; // forward declaration
std::unique_ptr<Agent> start_agent(std::string name, std::string settings_uri,
std::map<std::string, std::string> crypto_settings = {});
class Agent {
/*
____ _ _ _
/ ___|| |_ __ _| |_(_) ___
\___ \| __/ _` | __| |/ __|
___) | || (_| | |_| | (__
|____/ \__\__,_|\__|_|\___|
*/
private:
void setup_curve_on(zmq::socket_t &socket);
std::tuple<std::string, std::string, double>
query_broker(std::string uri, std::string name,
int timeout = DEFAULT_SETTINGS_TIMEOUT_MS);
public:
/*
_ _ __ _
| | (_)/ _| ___ ___ _ _ ___| | ___
| | | | |_ / _ \/ __| | | |/ __| |/ _ \
| |___| | _| __/ (__| |_| | (__| | __/
|_____|_|_| \___|\___|\__, |\___|_|\___|
|___/
*/
Agent(std::string name, std::string settings_uri);
void init(std::string name, std::string settings_uri, bool crypto = false, std::filesystem::path const &key_dir = "", bool install_watchdog = true);
void init(bool crypto = false, bool install_watchdog = true);
void fetch_settings(bool crypto = false);
// Destructor
virtual ~Agent();
void install_loop_watchdog(uint8_t max_count = 3);
/*
____ _ _ _
/ ___| ___| |_| |_(_)_ __ __ _ ___
\___ \ / _ \ __| __| | '_ \ / _` / __|
___) | __/ |_| |_| | | | | (_| \__ \
|____/ \___|\__|\__|_|_| |_|\__, |___/
|___/
*/
virtual void load_settings();
void save_settings(const std::string path = SETTINGS_PATH);
nlohmann::json get_settings();
#ifndef MADS_AGENT_NO_INFO
virtual void info(std::ostream &out = std::cout);
#endif
/*
____ _ _
/ ___|___ _ __ _ __ ___ ___| |_(_) ___ _ __
| | / _ \| '_ \| '_ \ / _ \/ __| __| |/ _ \| '_ \
| |__| (_) | | | | | | | __/ (__| |_| | (_) | | | |
\____\___/|_| |_|_| |_|\___|\___|\__|_|\___/|_| |_|
*/
void connect(std::chrono::milliseconds delay = std::chrono::milliseconds(250));
bool wait_for_connection(std::chrono::milliseconds timeout);
void disconnect();
void shutdown();
void set_cross(bool cross);
void enable_remote_control(bool threaded = false);
}
void register_event(const event_type event = event_type::marker,
const nlohmann::json &info = nlohmann::json(),
const std::string &info_name = "info");
void publish(nlohmann::json payload, std::string topic = "");
void publish(const char *payload, size_t len,
nlohmann::json meta = nlohmann::json{{"format", "raw"}},
std::string topic = "");
void publish(const std::vector<unsigned char> &payload,
nlohmann::json meta = nlohmann::json{{"format", "raw"}},
std::string topic = "");
message_type receive(bool dont_block = false);
bool receive_raw_message(std::string &topic, std::vector<std::string> &parts,
bool dont_block = false);
void publish_raw_message(const std::string &topic,
const std::vector<std::string> &parts);
/*
_
| | ___ ___ _ __
| | / _ \ / _ \| '_ \
| |__| (_) | (_) | |_) |
|_____\___/ \___/| .__/
|_|
*/
using loop_fun_t = std::function<std::chrono::nanoseconds()>;
void loop(loop_fun_t const &lambda,
std::chrono::nanoseconds duration);
void loop(loop_fun_t const &lambda);
void enable_high_res_loop(bool on = true,
std::chrono::nanoseconds spin_margin =
std::chrono::microseconds(200));
bool high_res_loop() const;
void remote_control(std::string payload_str);
/*
_
/ \ ___ ___ ___ ___ ___ ___ _ __ ___
/ _ \ / __/ __/ _ \/ __/ __|/ _ \| '__/ __|
/ ___ \ (_| (_| __/\__ \__ \ (_) | | \__ \
/_/ \_\___\___\___||___/___/\___/|_| |___/
*/
void set_agent_id(std::string id);
std::string get_agent_id();
void set_sub_endpoint(std::string endpoint) { _sub_endpoint = endpoint; }
std::string sub_endpoint() const { return _sub_endpoint; }
void set_pub_endpoint(std::string endpoint) { _pub_endpoint = endpoint; }
std::string pub_endpoint() const { return _pub_endpoint; }
void set_pub_topic(std::string topic);
std::string pub_topic() const { return _pub_topic; }
void set_sub_topic(std::vector<std::string> topics) { _sub_topic = topics; }
std::vector<std::string> sub_topic() const { return _sub_topic; }
std::map<std::string, std::string> status();
std::string name();
std::tuple<std::string, std::string> last_message();
std::tuple<std::string, nlohmann::json> last_json();
std::string last_topic();
std::tuple<std::string, std::string, std::vector<unsigned char>> last_blob();
std::tuple<std::string_view, std::string_view,
std::span<const unsigned char>>
last_blob_view() const;
size_t dropped_messages() const;
bool settings_are_local() const;
bool is_connected();
void set_settings_timeout(int to);
void set_settings_timeout(std::chrono::milliseconds to);
void set_receive_timeout(int to);
void set_receive_timeout(std::chrono::milliseconds to);
bool restart();
std::shared_ptr<Mads::Runtime> runtime() const { return _runtime; }
bool running() const { return keep_running(); }
void set_runtime(std::shared_ptr<Mads::Runtime> runtime);
std::filesystem::path attachment_path();
bool is_crypto();
std::unique_ptr<CurveAuth> *curve_auth();
std::filesystem::path key_dir();
void set_key_dir(const std::filesystem::path &path);
std::string settings_uri();
[[deprecated("conflate is disabled; use set_delivery(Delivery::LastKnownValue)")]]
void set_conflate(bool conflate);
[[deprecated("conflate is disabled; use delivery()")]]
bool conflate();
void set_high_watermark(int i = 1000);
void set_delivery(Delivery d);
Delivery delivery() const;
void set_wire_format(WireFormat fmt);
WireFormat wire_format() const;
void set_compression(Compression c);
Compression compression() const;
static void install_signal_handlers();
/*
____ _ _ ___ __ __ _
/ ___| | ___ ___| | __ / _ \ / _|/ _|___ ___| |_
| | | |/ _ \ / __| |/ /| | | | |_| |_/ __|/ _ \ __|
| |___| | (_) | (__| < | |_| | _| _\__ \ __/ |_
\____|_|\___/ \___|_|\_\ \___/|_| |_| |___/\___|\__|
*/
int timeout_ms = 1000);
std::vector<Mads::ClockPeerObservation> broadcast_clock_probe(
std::chrono::milliseconds window = std::chrono::milliseconds(300));
std::string clock_domain() const;
double timecode_fps = MADS_FPS;
std::string server_key_name = "broker";
std::string client_key_name = "client";
/*
____ _ _
| _ \ _ __(_)_ ____ _| |_ ___
| |_) | '__| \ \ / / _` | __/ _ \
| __/| | | |\ V / (_| | || __/
|_| |_| |_| \_/ \__,_|\__\___|
*/
protected:
bool keep_running() const {
return _runtime->running() && !_stopping.load();
}
void connect_pub(std::chrono::milliseconds delay = std::chrono::milliseconds(0));
void connect_sub();
bool receive_raw(zmq::multipart_t &message, bool dont_block = false);
bool _topic_matches_subscription(const std::string &topic) const;
static std::tuple<std::string, std::string, std::string> split_URL(const std::string &url);
bool _clock_wants_sync() const;
void _handle_clocksync_message(const nlohmann::json &msg);
uint8_t hops);
std::string _clock_agent_identity() const;
// Member variables
std::string _hostname;
std::string _name;
std::string _settings_uri;
std::string _raw_settings;
toml::table _config;
std::string _pub_topic;
std::string _agent_id;
std::vector<std::string> _sub_topic;
// Subset of _sub_topic containing a '+'/'#' wildcard token (P2), computed
// once by connect_sub(). Empty for every agent using only literal
// sub_topic entries, which keeps the receive-time filter a single cheap
// emptiness check in that -- the common -- case, adding no overhead.
std::vector<std::string> _wildcard_sub_topic;
zmq::context_t _context;
zmq::socket_t _publisher;
zmq::socket_t _subscriber;
// Attached before each socket's connect()/bind() (ZMQ_DEVELOPMENT.md
// §2.1); stopped in shutdown() before the sockets are closed.
// A single LazyPayload per message is shared between _last_message and
// _status so the lazy text/object caches are shared and never duplicated.
std::map<std::string, std::shared_ptr<LazyPayload>> _status;
std::tuple<std::string, std::shared_ptr<LazyPayload>> _last_message;
std::tuple<std::string, std::string, std::vector<unsigned char>> _last_blob;
mutable std::mutex _message_state_mutex;
bool _cross = false;
bool _connected = false;
int _receive_timeout = DEFAULT_RECEIVE_TIMEOUT_MS;
bool _init_done = false;
bool _settings_fetched = false;
bool _restart = false;
std::shared_ptr<Mads::Runtime> _runtime = std::make_shared<Mads::Runtime>();
// Per-agent stop request: set by shutdown()/disconnect(), cleared by
// connect(). Keeps an individual agent's teardown from stopping the other
// agents that share its Runtime.
std::atomic<bool> _stopping{false};
bool _remote_controlled = false;
std::chrono::nanoseconds _time_step = std::chrono::nanoseconds(0);
bool _high_res_loop = false;
std::chrono::nanoseconds _spin_margin = std::chrono::microseconds(200);
double _timecode_offset = 0.0;
std::filesystem::path _attachment_path;
bool _crypto = false;
bool _conflate = false;
std::unique_ptr<CurveAuth> _curve_auth = nullptr;
std::filesystem::path _key_dir;
bool _last_value_only = false;
bool _shutdown_done = false;
SharedLatest<zmq::multipart_t> _latest_message;
// The agent's one socket thread (ZMQ_DEVELOPMENT.md §4.1). It always polls
// both socket monitors' PAIR sockets -- which used to cost a thread each --
// and additionally owns _subscriber exclusively whenever LKV delivery
// and/or threaded remote control need it consumed off the application
// thread. A single thread rather than one per feature: two threads calling
// recv() on the same (non-thread-safe) ZMQ socket is undefined behaviour,
// and with LKV and threaded remote control both enabled it also meant a
// message landed on whichever thread's recv() call won the race.
std::thread _io_thread;
// Whether _io_thread polls _subscriber at all. Set by connect_sub() only
// once the socket is fully subscribed, and read by _io_thread, so it must
// be atomic even though it never changes after that.
std::atomic<bool> _io_reads_subscriber{false};
std::thread _watchdog_thread;
// Delayed startup-event publisher: owned (not detached) so shutdown() can
// wake it via _event_cv and join it before the sockets close.
std::thread _startup_event_thread;
std::mutex _event_mtx;
std::condition_variable _event_cv;
// ZMQ sockets are not thread-safe; the event thread publishes concurrently
// with the owner thread, so sends on _publisher are serialized.
std::mutex _publish_mutex;
std::atomic<bool> _watchdog_stop{false};
bool _rc_owns_socket = false;
WireFormat _wire_format = WireFormat::Json;
Compression _compression = Compression::Auto;
std::atomic<size_t> _dropped_messages{0};
nlohmann::json _settings_json; // cached JSON projection of settings
// ---- Clock offset (see clock_offset.hpp) --------------------------
bool _clock_sync_responder = true;
int _clock_announce_ms = 5000;
bool _clock_correction = false;
// Per-clock-domain adoption (§2 of the design): every agent, regardless
// of its own clock_source, records what it hears so clock_offset() can
// return the domain's winner rather than only this agent's own
// measurement.
Mads::ClockConsensus _clock_consensus{std::chrono::seconds(30)};
// This agent's own last measurement (source Broker or Peer), guarded
// separately from _clock_consensus's own internal mutex since it is
// read/written by measure_clock_offset()/_run_peer_measurement() (the
// clock thread or init()) and read by clock_offset() (any thread).
mutable std::mutex _clock_mtx;
uint64_t _clock_seq = 0;
std::thread _clock_thread;
// Pending broadcast_clock_probe() collection state: the send instant (for
// local_elapsed_us) and the pongs gathered so far. Single-flight by
// design (see broadcast_clock_probe()'s doc comment).
mutable std::mutex _clocksync_mtx;
std::chrono::steady_clock::time_point _clocksync_probe_sent_at{};
std::vector<Mads::ClockPeerObservation> _clocksync_pongs;
uint64_t _clocksync_probe_seq = 0;
// Per-initiator rate limit for this agent's own ping responses (§4.1 of
// the design): guarded by _clocksync_mtx too.
std::map<std::string, std::chrono::steady_clock::time_point>
public:
bool dummy = false;
};
} // namespace Mads
#endif // AGENT_HPP
void set_wire_format(WireFormat fmt)
Select the on-the-wire payload encoding used when publishing.
bool restart()
Returns wheter a restart has been requested.
std::mutex _publish_mutex
Definition agent.hpp:1358
toml::table _config
Definition agent.hpp:1289
std::thread _watchdog_thread
Definition agent.hpp:1350
std::string name()
Returns the name of the agent.
std::mutex _clocksync_mtx
Definition agent.hpp:1388
virtual ~Agent()
bool _clock_correction
Definition agent.hpp:1371
Mads::LinkState link_state() const
The current state of this agent's link to the broker: up or down, why (last_handshake – e....
std::map< std::string, std::chrono::steady_clock::time_point > _clocksync_last_reply
Definition agent.hpp:1395
std::filesystem::path attachment_path()
Returns the path to the attachment file.
Mads::ClockOffsetResult clock_offset() const
This agent's currently adopted clock offset: the clock domain's consensus winner (Mads::ClockConsensu...
void set_compression(Compression c)
Select the payload compression policy for outgoing messages.
bool _init_done
Definition agent.hpp:1316
uint64_t _clock_seq
Definition agent.hpp:1383
std::string _pub_endpoint
Definition agent.hpp:1290
void enable_threaded_remote_control()
Definition agent.hpp:477
void shutdown()
Performs a coordinated shutdown of the agent.
int _clock_interval_ms
Definition agent.hpp:1369
void _announce_clock_offset(const Mads::ClockOffsetResult &r)
void set_sub_topic(std::vector< std::string > topics)
Sets the subscribe topics.
Definition agent.hpp:755
std::thread _startup_event_thread
Definition agent.hpp:1353
std::string pub_endpoint() const
Get the publish endpoint URL.
Definition agent.hpp:734
std::filesystem::path _attachment_path
Definition agent.hpp:1329
std::string clock_domain() const
This process's clock-domain identity (Mads::detail::clock_domain_id(): boot_id on Linux,...
std::vector< std::string > sub_topic() const
Gets the subscribe topics.
Definition agent.hpp:762
std::string get_agent_id()
Get the agent ID.
Mads::ClockOffsetResult measure_clock_offset(size_t samples=5, int timeout_ms=1000)
Runs samples four-timestamp exchanges against the broker's settings endpoint and adopts the result as...
bool is_crypto()
Returns whether CURVE encryption is enabled.
Mads::SocketMonitor _sub_monitor
Definition agent.hpp:1305
std::string _raw_settings
Definition agent.hpp:1288
bool conflate()
double _timecode_offset
Definition agent.hpp:1328
std::string _name
Definition agent.hpp:1286
void set_pub_endpoint(std::string endpoint)
Set the publish endpoint URL.
Definition agent.hpp:727
std::string client_key_name
Definition agent.hpp:1152
std::string settings_uri()
std::atomic< size_t > _dropped_messages
Definition agent.hpp:1363
std::vector< std::string > _sub_topic
Definition agent.hpp:1293
bool _clock_sync_responder
Definition agent.hpp:1368
void set_runtime(std::shared_ptr< Mads::Runtime > runtime)
Attach the agent to a different Runtime.
void connect(std::chrono::milliseconds delay=std::chrono::milliseconds(250))
Connects the agent to the publish and subscribe endpoints.
Mads::ClockOffsetResult _own_clock_measurement
Definition agent.hpp:1382
bool _crypto
Definition agent.hpp:1330
bool _shutdown_done
Definition agent.hpp:1335
int high_watermark()
void set_delivery(Delivery d)
Select subscriber delivery semantics.
std::filesystem::path key_dir()
Returns the path to the etc directory.
std::tuple< std::string, nlohmann::json > last_json()
Returns the last received message as a parsed JSON object.
std::condition_variable _event_cv
Definition agent.hpp:1355
std::chrono::nanoseconds _spin_margin
Definition agent.hpp:1327
void save_settings(const std::string path=SETTINGS_PATH)
Save settings read from broker to file.
int _receive_timeout
Definition agent.hpp:1314
std::unique_ptr< CurveAuth > * curve_auth()
Returns a pointer to the CurveAuth object.
void publish_raw_message(const std::string &topic, const std::vector< std::string > &parts)
Publishes a raw multi-part message with no JSON encoding, no automatic field-stamping (agent_id/hostn...
bool _clock_wants_sync() const
void init(std::string name, std::string settings_uri, bool crypto=false, std::filesystem::path const &key_dir="", bool install_watchdog=true)
Initializes the agent.
std::tuple< std::string_view, std::string_view, std::span< const unsigned char > > last_blob_view() const
Zero-copy view of the last received blob.
bool receive_raw(zmq::multipart_t &message, bool dont_block=false)
Internal use wrapping the receive step both for normal operations and for LastKnown Value (LKV) seman...
SharedLatest< zmq::multipart_t > _latest_message
Definition agent.hpp:1336
bool _connected
Definition agent.hpp:1313
bool _topic_matches_subscription(const std::string &topic) const
MQTT-style wildcard filter (P2): true if topic is accepted by at least one entry of _sub_topic – lite...
Mads::ClockOffsetResult _stamp_clock_result(Mads::ClockOffsetResult r, Mads::ClockSource source, uint8_t hops)
std::thread _io_thread
Definition agent.hpp:1345
std::vector< Mads::ClockPeerObservation > broadcast_clock_probe(std::chrono::milliseconds window=std::chrono::milliseconds(300))
Broadcasts a clock-sync ping on CLOCKSYNC_TOPIC and collects every responder's pong that arrives with...
void set_pub_topic(std::string topic)
Sets the publish topic.
void enable_remote_control(bool threaded=false)
Enables remote control for the agent.
bool _conflate
Definition agent.hpp:1331
bool wait_for_connection(std::chrono::milliseconds timeout)
Blocks until the publisher socket's connection is confirmed by a real ZMQ_EVENT_CONNECTED/ZMQ_EVENT_H...
Mads::auth_verbose auth_verbose
Definition agent.hpp:1150
virtual void info(std::ostream &out=std::cout)
Prints information about the agent.
void set_cross(bool cross)
Sets the cross flag.
size_t dropped_messages() const
Number of messages dropped because they were malformed or could not be decoded (bad part count,...
bool _high_res_loop
Definition agent.hpp:1326
std::function< std::chrono::nanoseconds()> loop_fun_t
Enters the main loop of the agent. It also sets a signal handler for SIGNINT, which will set the runn...
Definition agent.hpp:626
std::mutex _clock_mtx
Definition agent.hpp:1381
void remote_control(std::string payload_str)
Handles remote control commands.
int receive_timeout()
Returns the value of timeout in receiving messages.
Mads::SocketMonitor _pub_monitor
Definition agent.hpp:1304
std::vector< Mads::ClockPeerObservation > _clocksync_pongs
Definition agent.hpp:1390
std::string _settings_uri
Definition agent.hpp:1287
std::atomic< bool > _watchdog_stop
Definition agent.hpp:1359
std::atomic< bool > _io_reads_subscriber
Definition agent.hpp:1349
void set_conflate(bool conflate)
void enable_high_res_loop(bool on=true, std::chrono::nanoseconds spin_margin=std::chrono::microseconds(200))
Opt into (or out of) high-resolution loop pacing.
nlohmann::json _settings_json
Definition agent.hpp:1364
void _handle_clocksync_message(const nlohmann::json &msg)
static void install_signal_handlers()
Install SIGINT/SIGTERM handlers that request a clean shutdown.
std::string _hostname
Definition agent.hpp:1285
std::map< std::string, std::string > status()
Returns the status of the system.
uint64_t _clocksync_probe_seq
Definition agent.hpp:1391
void set_high_watermark(int i=1000)
Set the high watermark (ZMQ receive queue bound).
zmq::socket_t _subscriber
Definition agent.hpp:1301
bool is_connected()
Detects if agent is connected.
void loop(loop_fun_t const &lambda, std::chrono::nanoseconds duration)
std::shared_ptr< Mads::Runtime > _runtime
Definition agent.hpp:1319
std::tuple< std::string, std::shared_ptr< LazyPayload > > _last_message
Definition agent.hpp:1309
void set_agent_id(std::string id)
Set the agent ID field.
std::string sub_endpoint() const
Get the subscribe endpoint URL.
Definition agent.hpp:720
std::string _pub_topic
Definition agent.hpp:1291
void _configure_clock_sync()
Parses the [agents]/[<name>] clock_* settings during init() and appends CLOCKSYNC_TOPIC to _sub_topic...
int _clock_announce_ms
Definition agent.hpp:1370
WireFormat _wire_format
Definition agent.hpp:1361
message_type receive(bool dont_block=false)
Receives a message from the subscribe socket.
Mads::ClockSource _clock_source
Definition agent.hpp:1367
double timecode_fps
Definition agent.hpp:1149
void _run_peer_measurement()
std::mutex _message_state_mutex
Definition agent.hpp:1311
std::chrono::nanoseconds _time_step
Definition agent.hpp:1325
void _start_clock_thread()
Brings up _clock_thread if it is not already running: announces this agent's adopted clock offset on ...
bool high_res_loop() const
Returns whether high-resolution loop pacing is enabled.
std::filesystem::path _key_dir
Definition agent.hpp:1333
std::mutex _event_mtx
Definition agent.hpp:1354
bool _settings_fetched
Definition agent.hpp:1317
nlohmann::json get_settings()
Get all settings as JSON.
bool running() const
True while this agent's loops should keep going.
Definition agent.hpp:942
static std::tuple< std::string, std::string, std::string > split_URL(const std::string &url)
int settings_timeout()
Returns the value of timeout in loading settings from URI.
bool settings_are_local() const
Detects if settings are local or loaded from URI.
void fetch_settings(bool crypto=false)
Acquires settings (and any broker-served attachment) without binding the agent to a settings section.
void _start_io_thread()
Brings up _io_thread if it is not already running. Called from whichever of connect_pub()/connect_sub...
std::string pub_topic() const
Gets the publish topic.
Definition agent.hpp:748
bool keep_running() const
True while this agent's loops should keep going.
Definition agent.hpp:1170
void install_loop_watchdog(uint8_t max_count=3)
Install a watch thread to ensure exit from loops.
void set_sub_endpoint(std::string endpoint)
Set the subscribe endpoint URL.
Definition agent.hpp:713
void set_settings_timeout(int to)
Sets the value of timeout in loading settings from URI. Set to for no timeout.
zmq::socket_t _publisher
Definition agent.hpp:1300
std::tuple< std::string, std::string, std::vector< unsigned char > > last_blob()
Returns the last received blob by the agent.
std::shared_ptr< Mads::Runtime > runtime() const
The Runtime that owns this agent's run state.
Definition agent.hpp:931
Delivery delivery() const
Current delivery semantics.
bool _cross
Definition agent.hpp:1312
void _apply_socket_options()
Resolves the plain libzmq transport-tuning knobs (ZMQ_DEVELOPMENT.md §1.4: TCP keepalive,...
std::map< std::string, std::shared_ptr< LazyPayload > > _status
Definition agent.hpp:1308
std::atomic< bool > _stopping
Definition agent.hpp:1323
void setup_crypto(Mads::auth_verbose verbose=auth_verbose::off)
Set the use of CURVE encryption and enables authentication.
std::string server_key_name
Definition agent.hpp:1151
void set_key_dir(const std::filesystem::path &path)
Sets the path to the etc directory.
int _settings_timeout
Definition agent.hpp:1315
Compression compression() const
The compression policy used for outgoing messages.
std::tuple< std::string, std::string > last_message()
Returns the last received message by the agent.
void connect_pub(std::chrono::milliseconds delay=std::chrono::milliseconds(0))
Connects the agent to the publish endpoint.
void publish(nlohmann::json payload, std::string topic="")
Publishes a message with the given JSON payload.
zmq::context_t _context
Definition agent.hpp:1299
void register_event(const event_type event=event_type::marker, const nlohmann::json &info=nlohmann::json(), const std::string &info_name="info")
Registers an event.
WireFormat wire_format() const
The wire format used for outgoing messages.
Compression _compression
Definition agent.hpp:1362
bool _rc_owns_socket
Definition agent.hpp:1360
bool _remote_controlled
Definition agent.hpp:1324
bool receive_raw_message(std::string &topic, std::vector< std::string > &parts, bool dont_block=false)
Receives a message without any JSON/blob (de)serialization (P3).
std::thread _clock_thread
Definition agent.hpp:1384
std::vector< std::string > _wildcard_sub_topic
Definition agent.hpp:1298
virtual void load_settings()
Additional settings to be loaded. Virtual function to be implemented by the derived class.
void set_receive_timeout(int to)
Sets the value of timeout in receiving messages. Set to 0 for no timeout.
void connect_sub()
Connects the agent to the subscribe endpoint and subscribes to the topics.
Mads::ClockConsensus _clock_consensus
Definition agent.hpp:1376
std::string _clock_agent_identity() const
std::string _agent_id
Definition agent.hpp:1292
std::unique_ptr< CurveAuth > _curve_auth
Definition agent.hpp:1332
std::string _sub_endpoint
Definition agent.hpp:1290
std::chrono::steady_clock::time_point _clocksync_probe_sent_at
Definition agent.hpp:1389
std::tuple< std::string, std::string, std::vector< unsigned char > > _last_blob
Definition agent.hpp:1310
bool _restart
Definition agent.hpp:1318
std::string last_topic()
Returns the topic of the last received message by the agent.
bool _last_value_only
Definition agent.hpp:1334
void disconnect()
Disconnects the agent from the publish and subscribe endpoints.
Per-clock-domain adoption of the smallest-delay measurement heard from any agent sharing that domain ...
static LazyPayload from_doc(nlohmann::json doc)
Definition agent.hpp:95
LazyPayload()=default
const nlohmann::json & doc() const
Parsed object form (parses the cached text once if only text exists).
Definition agent.hpp:107
const std::string & text() const
JSON text form (dumps the cached object once if only the object exists).
Definition agent.hpp:101
static LazyPayload from_text(std::string text)
Definition agent.hpp:90
One monitor per monitored socket. start() must be called before the socket's connect()/bind(): libzmq...
Definition agent.hpp:67
ClockSource
Which mechanism produced a ClockOffsetResult.
auth_verbose
Definition curve.hpp:35
std::unique_ptr< Agent > start_agent(std::string name, std::string settings_uri, std::map< std::string, std::string > crypto_settings={})
Quick Agent initialization function.
Result of a clock-offset measurement: offset_us added to a clock in the measured domain yields broker...
std::string responder_domain
Definition agent.hpp:134
std::string responder_hostname
Definition agent.hpp:133
ClockOffsetResult responder_adopted
Definition agent.hpp:138
std::string responder_name
Definition agent.hpp:132
std::string responder_agent_id
Definition agent.hpp:131
std::mutex mtx
Definition agent.hpp:70
std::condition_variable cv
Definition agent.hpp:71
std::optional< T > value
Definition agent.hpp:72