Mads
Multi-Agent Distributed System
Loading...
Searching...
No Matches
Mads::SocketMonitor Class Reference

One monitor per monitored socket. start() must be called before the socket's connect()/bind(): libzmq lets a connection through – and may fire its lifecycle events – while no monitor is attached yet, exactly the same race Mads::ZapAuth::start() avoids for the ZAP handler. More...

#include <socket_monitor.hpp>

Public Member Functions

 SocketMonitor ()
 
 ~SocketMonitor ()
 
 SocketMonitor (const SocketMonitor &)=delete
 
SocketMonitoroperator= (const SocketMonitor &)=delete
 
void start (zmq::socket_t &socket, int events=ZMQ_EVENT_ALL)
 Starts monitoring socket on a private inproc:// endpoint and a dedicated thread. A second call before stop() is a no-op.
 
void attach (zmq::socket_t &socket, int events=ZMQ_EVENT_ALL)
 Attaches to socket without starting any thread, leaving the caller to drive the monitor: include pollable() in a zmq::poll() and call process_pending() whenever it reports ZMQ_POLLIN.
 
zmq::socket_ref pollable () const
 The monitor's own PAIR socket, for inclusion in the caller's zmq::poll(). Its handle() is null until attach()/start() has run, and null again after stop() – so a driving loop can simply re-read it every iteration and pick up a monitor that was attached later.
 
void process_pending ()
 Consumes the events pollable() has signalled, updating last_event()/state() and waking the wait_*() calls.
 
void stop ()
 Stops the monitoring thread (if start() created one) and detaches from the socket (zmq_socket_monitor(socket, nullptr, 0)). Must be called – directly or via the destructor – before the monitored socket is closed. Safe to call more than once and safe if neither start() nor attach() was ever called.
 
bool wait_connected (std::chrono::milliseconds timeout)
 Blocks until a Connected or HandshakeSucceeded event is observed, or timeout elapses. This is a fast "did the transport come up" signal only – ZMQ_EVENT_CONNECTED fires at the TCP level, before any ZMTP security mechanism (NULL/PLAIN/CURVE) has been negotiated. Callers that need to know the handshake itself succeeded (e.g. distinguishing a CURVE rejection from an ordinary connect) must use wait_handshake_succeeded() instead.
 
bool wait_handshake_succeeded (std::chrono::milliseconds timeout)
 Blocks until a ZMTP handshake completes one way or the other, or timeout elapses. Unlike wait_connected(), this does not accept a bare Connected event, so it is not fooled by a CURVE/ZAP rejection: TCP connects immediately regardless of the mechanism, but the handshake only succeeds once the security layer has actually accepted the peer.
 
LinkEvent last_event () const
 The most recent event observed (None if none yet).
 
LinkState state () const
 A consistent snapshot of the link's current status, the event that produced it, and how often it has dropped and recovered.
 
std::string last_event_address () const
 

Detailed Description

One monitor per monitored socket. start() must be called before the socket's connect()/bind(): libzmq lets a connection through – and may fire its lifecycle events – while no monitor is attached yet, exactly the same race Mads::ZapAuth::start() avoids for the ZAP handler.

The monitor runs its own background thread polling the inproc:// pair zmq_socket_monitor() publishes to; nothing about it touches the monitored socket itself, so it composes with any other use of that socket.

state() assumes the monitored socket connects to a single peer. A bound socket gets ZMQ_EVENT_ACCEPTED (not CONNECTED/HANDSHAKE_SUCCEEDED) per arriving peer and ZMQ_EVENT_DISCONNECTED per departing one, so its events would add up to "down" the moment any one of several peers left; use last_event() there, or nothing at all.

Examples
/home/runner/work/MADS/MADS/src/agent.hpp.

Definition at line 114 of file socket_monitor.hpp.

Constructor & Destructor Documentation

◆ SocketMonitor() [1/2]

Mads::SocketMonitor::SocketMonitor ( )

◆ ~SocketMonitor()

Mads::SocketMonitor::~SocketMonitor ( )

◆ SocketMonitor() [2/2]

Mads::SocketMonitor::SocketMonitor ( const SocketMonitor )
delete

Member Function Documentation

◆ attach()

void Mads::SocketMonitor::attach ( zmq::socket_t &  socket,
int  events = ZMQ_EVENT_ALL 
)

Attaches to socket without starting any thread, leaving the caller to drive the monitor: include pollable() in a zmq::poll() and call process_pending() whenever it reports ZMQ_POLLIN.

This is what lets several monitors – or a monitor and the application's own sockets – share one poll loop instead of one thread each (ZMQ_DEVELOPMENT.md ยง4.1). Same ordering contract as start(): call it before the socket's connect()/bind().

A second call before stop() is a no-op, so a caller that reconnects can call it again without re-arming zmq_socket_monitor().

◆ last_event()

LinkEvent Mads::SocketMonitor::last_event ( ) const

The most recent event observed (None if none yet).

◆ last_event_address()

std::string Mads::SocketMonitor::last_event_address ( ) const

The libzmq-reported peer address the most recent event carried (empty if none yet).

◆ operator=()

SocketMonitor & Mads::SocketMonitor::operator= ( const SocketMonitor )
delete

◆ pollable()

zmq::socket_ref Mads::SocketMonitor::pollable ( ) const

The monitor's own PAIR socket, for inclusion in the caller's zmq::poll(). Its handle() is null until attach()/start() has run, and null again after stop() – so a driving loop can simply re-read it every iteration and pick up a monitor that was attached later.

◆ process_pending()

void Mads::SocketMonitor::process_pending ( )

Consumes the events pollable() has signalled, updating last_event()/state() and waking the wait_*() calls.

Call only from the thread that polls pollable(), and only when that poll reported ZMQ_POLLIN – like the socket it drains, this is not thread-safe. A monitor driven this way must not be stop()ped until that thread has been joined.

◆ start()

void Mads::SocketMonitor::start ( zmq::socket_t &  socket,
int  events = ZMQ_EVENT_ALL 
)

Starts monitoring socket on a private inproc:// endpoint and a dedicated thread. A second call before stop() is a no-op.

Equivalent to attach() plus a thread that does nothing but drive it. Use attach() instead when there is already a poll loop to fold this into.

◆ state()

LinkState Mads::SocketMonitor::state ( ) const

A consistent snapshot of the link's current status, the event that produced it, and how often it has dropped and recovered.

Only ZMQ_EVENT_HANDSHAKE_SUCCEEDED raises the status to Up. A bare ZMQ_EVENT_CONNECTED deliberately does not: it fires as soon as TCP is established, before the ZMTP security mechanism has run, so a CURVE rejection would otherwise register as a connection immediately followed by a spurious drop.

◆ stop()

void Mads::SocketMonitor::stop ( )

Stops the monitoring thread (if start() created one) and detaches from the socket (zmq_socket_monitor(socket, nullptr, 0)). Must be called – directly or via the destructor – before the monitored socket is closed. Safe to call more than once and safe if neither start() nor attach() was ever called.

This resets what state() reports back to Unknown with zeroed counters: a detached monitor has no link to describe, and a later start() begins a fresh observation rather than resuming a stale one.

◆ wait_connected()

bool Mads::SocketMonitor::wait_connected ( std::chrono::milliseconds  timeout)

Blocks until a Connected or HandshakeSucceeded event is observed, or timeout elapses. This is a fast "did the transport come up" signal only – ZMQ_EVENT_CONNECTED fires at the TCP level, before any ZMTP security mechanism (NULL/PLAIN/CURVE) has been negotiated. Callers that need to know the handshake itself succeeded (e.g. distinguishing a CURVE rejection from an ordinary connect) must use wait_handshake_succeeded() instead.

Returns
true if the connection was observed within the timeout.

◆ wait_handshake_succeeded()

bool Mads::SocketMonitor::wait_handshake_succeeded ( std::chrono::milliseconds  timeout)

Blocks until a ZMTP handshake completes one way or the other, or timeout elapses. Unlike wait_connected(), this does not accept a bare Connected event, so it is not fooled by a CURVE/ZAP rejection: TCP connects immediately regardless of the mechanism, but the handshake only succeeds once the security layer has actually accepted the peer.

Decided on state().last_handshake rather than the newest event, so the DISCONNECTED that libzmq fires straight after a rejection cannot make this report a timeout instead of a refusal.

Returns
true if the handshake succeeded within the timeout.

The documentation for this class was generated from the following file: