zmq_socket_monitor_versioned.txt 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. zmq_socket_monitor_versioned(3)
  2. ===============================
  3. NAME
  4. ----
  5. zmq_socket_monitor_versioned - monitor socket events
  6. SYNOPSIS
  7. --------
  8. *int zmq_socket_monitor_versioned (void '*socket', char '*endpoint', uint64_t 'events', int 'event_version', int 'type');*
  9. *int zmq_socket_monitor_pipes_stats (void '*socket');*
  10. DESCRIPTION
  11. -----------
  12. The _zmq_socket_monitor_versioned()_ method lets an application thread track
  13. socket events (like connects) on a ZeroMQ socket. Each call to this
  14. method creates a 'ZMQ_PAIR' socket and binds that to the specified
  15. inproc:// 'endpoint'. To collect the socket events, you must create
  16. your own 'ZMQ_PAIR' socket, and connect that to the endpoint.
  17. The 'events' argument is a bitmask of the socket events you wish to
  18. monitor, see 'Supported events' below. To monitor all events for a version, use
  19. the event value ZMQ_EVENT_ALL_V<version>, e.g. ZMQ_EVENT_ALL_V1. For non-DRAFT event
  20. versions, this value will not change in the future, so new event types will only be
  21. added in new versions (note that this is a change over zmq_socket_monitor and the
  22. unversioned ZMQ_EVENT_ALL).
  23. Note that event_version 2 is currently in DRAFT mode. The protocol may be
  24. changed at any time for event_versions in DRAFT.
  25. ZMQ_CURRENT_EVENT_VERSION and ZMQ_CURRENT_EVENT_VERSION_DRAFT are always defined
  26. to the most recent stable or DRAFT event version, which are currently 1 resp. 2
  27. This page describes the protocol for 'event_version' 2 only. For the protocol
  28. used with 'event_version' 1, please refer to linkzmq:zmq_socket_monitor[3].
  29. Each event is sent in multiple frames. The first frame contains an event
  30. number (64 bits). The number and content of further frames depend on this
  31. event number.
  32. Unless it is specified differently, the second frame contains the number of
  33. value frames that will follow it as a 64 bits integer. The third frame to N-th
  34. frames contain an event value (64 bits) that provides additional data according
  35. to the event number. Each event type might have a different number of values.
  36. The second-to-last and last frames contain strings that specifies the affected
  37. connection or endpoint. The former frame contains a string denoting the local
  38. endpoint, while the latter frame contains a string denoting the remote endpoint.
  39. Either of these may be empty, depending on the event type and whether the
  40. connection uses a bound or connected local endpoint.
  41. Note that the format of the second and further frames, and also the number of
  42. frames, may be different for events added in the future.
  43. The 'type' argument is used to specify the type of the monitoring socket.
  44. Supported types are 'ZMQ_PAIR', 'ZMQ_PUB' and 'ZMQ_PUSH'. Note that consumers
  45. of the events will have to be compatible with the socket type, for instance a
  46. monitoring socket of type 'ZMQ_PUB' will require consumers of type 'ZMQ_SUB'.
  47. In the case that the monitoring socket type is of 'ZMQ_PUB', the multipart
  48. message topic is the event number, thus consumers should subscribe to the
  49. events they want to receive.
  50. The _zmq_socket_monitor_pipes_stats()_ method triggers an event of type
  51. ZMQ_EVENT_PIPES_STATS for each connected peer of the monitored socket.
  52. NOTE: _zmq_socket_monitor_pipes_stats()_ is in DRAFT state.
  53. ----
  54. Monitoring events are only generated by some transports: At the moment these
  55. are SOCKS, TCP, IPC, and TIPC. Note that it is not an error to call
  56. 'zmq_socket_monitor_versioned' on a socket that is connected or bound to some
  57. other transport, as this may not be known at the time
  58. 'zmq_socket_monitor_versioned' is called. Also, a socket can be connected/bound
  59. to multiple endpoints using different transports.
  60. ----
  61. Supported events (v1)
  62. ----------------
  63. ZMQ_EVENT_CONNECTED
  64. ~~~~~~~~~~~~~~~~~~~
  65. The socket has successfully connected to a remote peer. The event value
  66. is the file descriptor (FD) of the underlying network socket. Warning:
  67. there is no guarantee that the FD is still valid by the time your code
  68. receives this event.
  69. ZMQ_EVENT_CONNECT_DELAYED
  70. ~~~~~~~~~~~~~~~~~~~~~~~~~
  71. A connect request on the socket is pending. The event value is unspecified.
  72. ZMQ_EVENT_CONNECT_RETRIED
  73. ~~~~~~~~~~~~~~~~~~~~~~~~~
  74. A connect request failed, and is now being retried. The event value is the
  75. reconnect interval in milliseconds. Note that the reconnect interval is
  76. recalculated for each retry.
  77. ZMQ_EVENT_LISTENING
  78. ~~~~~~~~~~~~~~~~~~~
  79. The socket was successfully bound to a network interface. The event value
  80. is the FD of the underlying network socket. Warning: there is no guarantee
  81. that the FD is still valid by the time your code receives this event.
  82. ZMQ_EVENT_BIND_FAILED
  83. ~~~~~~~~~~~~~~~~~~~~~
  84. The socket could not bind to a given interface. The event value is the
  85. errno generated by the system bind call.
  86. ZMQ_EVENT_ACCEPTED
  87. ~~~~~~~~~~~~~~~~~~
  88. The socket has accepted a connection from a remote peer. The event value is
  89. the FD of the underlying network socket. Warning: there is no guarantee that
  90. the FD is still valid by the time your code receives this event.
  91. ZMQ_EVENT_ACCEPT_FAILED
  92. ~~~~~~~~~~~~~~~~~~~~~~~
  93. The socket has rejected a connection from a remote peer. The event value is
  94. the errno generated by the accept call.
  95. ZMQ_EVENT_CLOSED
  96. ~~~~~~~~~~~~~~~~
  97. The socket was closed. The event value is the FD of the (now closed) network
  98. socket.
  99. ZMQ_EVENT_CLOSE_FAILED
  100. ~~~~~~~~~~~~~~~~~~~~~~
  101. The socket close failed. The event value is the errno returned by the system
  102. call. Note that this event occurs only on IPC transports.
  103. ZMQ_EVENT_DISCONNECTED
  104. ~~~~~~~~~~~~~~~~~~~~~~
  105. The socket was disconnected unexpectedly. The event value is the FD of the
  106. underlying network socket. Warning: this socket will be closed.
  107. ZMQ_EVENT_MONITOR_STOPPED
  108. ~~~~~~~~~~~~~~~~~~~~~~~~~
  109. Monitoring on this socket ended.
  110. ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL
  111. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  112. Unspecified error during handshake.
  113. The event value is an errno.
  114. ZMQ_EVENT_HANDSHAKE_SUCCEEDED
  115. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  116. The ZMTP security mechanism handshake succeeded.
  117. The event value is unspecified.
  118. ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL
  119. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  120. The ZMTP security mechanism handshake failed due to some mechanism protocol
  121. error, either between the ZMTP mechanism peers, or between the mechanism
  122. server and the ZAP handler. This indicates a configuration or implementation
  123. error in either peer resp. the ZAP handler.
  124. The event value is one of the ZMQ_PROTOCOL_ERROR_* values:
  125. ZMQ_PROTOCOL_ERROR_ZMTP_UNSPECIFIED
  126. ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND
  127. ZMQ_PROTOCOL_ERROR_ZMTP_INVALID_SEQUENCE
  128. ZMQ_PROTOCOL_ERROR_ZMTP_KEY_EXCHANGE
  129. ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_UNSPECIFIED
  130. ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_MESSAGE
  131. ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_HELLO
  132. ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_INITIATE
  133. ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_ERROR
  134. ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_READY
  135. ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_WELCOME
  136. ZMQ_PROTOCOL_ERROR_ZMTP_INVALID_METADATA
  137. ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC
  138. ZMQ_PROTOCOL_ERROR_ZMTP_MECHANISM_MISMATCH
  139. ZMQ_PROTOCOL_ERROR_ZAP_UNSPECIFIED
  140. ZMQ_PROTOCOL_ERROR_ZAP_MALFORMED_REPLY
  141. ZMQ_PROTOCOL_ERROR_ZAP_BAD_REQUEST_ID
  142. ZMQ_PROTOCOL_ERROR_ZAP_BAD_VERSION
  143. ZMQ_PROTOCOL_ERROR_ZAP_INVALID_STATUS_CODE
  144. ZMQ_PROTOCOL_ERROR_ZAP_INVALID_METADATA
  145. ZMQ_EVENT_HANDSHAKE_FAILED_AUTH
  146. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  147. The ZMTP security mechanism handshake failed due to an authentication failure.
  148. The event value is the status code returned by the ZAP handler (i.e. 300,
  149. 400 or 500).
  150. ----
  151. Supported events (v2)
  152. ----------------
  153. ZMQ_EVENT_PIPE_STATS
  154. ~~~~~~~~~~~~~~~~~~~~
  155. This event provides two values, the number of messages in each of the two
  156. queues associated with the returned endpoint (respectively egress and ingress).
  157. This event only triggers after calling the function
  158. _zmq_socket_monitor_pipes_stats()_.
  159. NOTE: this measurement is asynchronous, so by the time the message is received
  160. the internal state might have already changed.
  161. NOTE: when the monitored socket and the monitor are not used in a poll, the
  162. event might not be delivered until an API has been called on the monitored
  163. socket, like zmq_getsockopt for example (the option is irrelevant).
  164. NOTE: in DRAFT state, not yet available in stable releases.
  165. RETURN VALUE
  166. ------------
  167. The _zmq_socket_monitor()_ and _zmq_socket_monitor_pipes_stats()_ functions
  168. return a value of 0 or greater if successful. Otherwise they return `-1` and
  169. set 'errno' to one of the values defined below.
  170. ERRORS - _zmq_socket_monitor()_
  171. -------------------------------
  172. *ETERM*::
  173. The 0MQ 'context' associated with the specified 'socket' was terminated.
  174. *EPROTONOSUPPORT*::
  175. The transport protocol of the monitor 'endpoint' is not supported. Monitor
  176. sockets are required to use the inproc:// transport.
  177. *EINVAL*::
  178. The monitor 'endpoint' supplied does not exist or the specified socket 'type'
  179. is not supported.
  180. ERRORS - _zmq_socket_monitor_pipes_stats()_
  181. -------------------------------------------
  182. *ENOTSOCK*::
  183. The 'socket' parameter was not a valid 0MQ socket.
  184. *EINVAL*::
  185. The socket did not have monitoring enabled.
  186. *EAGAIN*::
  187. The monitored socket did not have any connections to monitor yet.
  188. EXAMPLE
  189. -------
  190. .Monitoring client and server sockets
  191. ----
  192. // Read one event off the monitor socket; return values and addresses
  193. // by reference, if not null, and event number by value. Returns -1
  194. // in case of error.
  195. static uint64_t
  196. get_monitor_event (void *monitor, uint64_t *value, char **local_address, char **remote_address)
  197. {
  198. // First frame in message contains event number
  199. zmq_msg_t msg;
  200. zmq_msg_init (&msg);
  201. if (zmq_msg_recv (&msg, monitor, 0) == -1)
  202. return -1; // Interrupted, presumably
  203. assert (zmq_msg_more (&msg));
  204. uint64_t event;
  205. memcpy (&event, zmq_msg_data (&msg), sizeof (event));
  206. zmq_msg_close (&msg);
  207. // Second frame in message contains the number of values
  208. zmq_msg_init (&msg);
  209. if (zmq_msg_recv (&msg, monitor, 0) == -1)
  210. return -1; // Interrupted, presumably
  211. assert (zmq_msg_more (&msg));
  212. uint64_t value_count;
  213. memcpy (&value_count, zmq_msg_data (&msg), sizeof (value_count));
  214. zmq_msg_close (&msg);
  215. for (uint64_t i = 0; i < value_count; ++i) {
  216. // Subsequent frames in message contain event values
  217. zmq_msg_init (&msg);
  218. if (zmq_msg_recv (&msg, monitor, 0) == -1)
  219. return -1; // Interrupted, presumably
  220. assert (zmq_msg_more (&msg));
  221. if (value_ && value_ + i)
  222. memcpy (value_ + i, zmq_msg_data (&msg), sizeof (*value_));
  223. zmq_msg_close (&msg);
  224. }
  225. // Second-to-last frame in message contains local address
  226. zmq_msg_init (&msg);
  227. if (zmq_msg_recv (&msg, monitor, 0) == -1)
  228. return -1; // Interrupted, presumably
  229. assert (zmq_msg_more (&msg));
  230. if (local_address_) {
  231. uint8_t *data = (uint8_t *) zmq_msg_data (&msg);
  232. size_t size = zmq_msg_size (&msg);
  233. *local_address_ = (char *) malloc (size + 1);
  234. memcpy (*local_address_, data, size);
  235. (*local_address_)[size] = 0;
  236. }
  237. zmq_msg_close (&msg);
  238. // Last frame in message contains remote address
  239. zmq_msg_init (&msg);
  240. if (zmq_msg_recv (&msg, monitor, 0) == -1)
  241. return -1; // Interrupted, presumably
  242. assert (!zmq_msg_more (&msg));
  243. if (remote_address_) {
  244. uint8_t *data = (uint8_t *) zmq_msg_data (&msg);
  245. size_t size = zmq_msg_size (&msg);
  246. *remote_address_ = (char *) malloc (size + 1);
  247. memcpy (*remote_address_, data, size);
  248. (*remote_address_)[size] = 0;
  249. }
  250. zmq_msg_close (&msg);
  251. return event;
  252. }
  253. int main (void)
  254. {
  255. void *ctx = zmq_ctx_new ();
  256. assert (ctx);
  257. // We'll monitor these two sockets
  258. void *client = zmq_socket (ctx, ZMQ_DEALER);
  259. assert (client);
  260. void *server = zmq_socket (ctx, ZMQ_DEALER);
  261. assert (server);
  262. // Socket monitoring only works over inproc://
  263. int rc = zmq_socket_monitor_versioned (client, "tcp://127.0.0.1:9999", 0, 2);
  264. assert (rc == -1);
  265. assert (zmq_errno () == EPROTONOSUPPORT);
  266. // Monitor all events on client and server sockets
  267. rc = zmq_socket_monitor_versioned (client, "inproc://monitor-client", ZMQ_EVENT_ALL, 2);
  268. assert (rc == 0);
  269. rc = zmq_socket_monitor_versioned (server, "inproc://monitor-server", ZMQ_EVENT_ALL, 2);
  270. assert (rc == 0);
  271. // Create two sockets for collecting monitor events
  272. void *client_mon = zmq_socket (ctx, ZMQ_PAIR);
  273. assert (client_mon);
  274. void *server_mon = zmq_socket (ctx, ZMQ_PAIR);
  275. assert (server_mon);
  276. // Connect these to the inproc endpoints so they'll get events
  277. rc = zmq_connect (client_mon, "inproc://monitor-client");
  278. assert (rc == 0);
  279. rc = zmq_connect (server_mon, "inproc://monitor-server");
  280. assert (rc == 0);
  281. // Now do a basic ping test
  282. rc = zmq_bind (server, "tcp://127.0.0.1:9998");
  283. assert (rc == 0);
  284. rc = zmq_connect (client, "tcp://127.0.0.1:9998");
  285. assert (rc == 0);
  286. bounce (client, server);
  287. // Close client and server
  288. close_zero_linger (client);
  289. close_zero_linger (server);
  290. // Now collect and check events from both sockets
  291. int event = get_monitor_event (client_mon, NULL, NULL);
  292. if (event == ZMQ_EVENT_CONNECT_DELAYED)
  293. event = get_monitor_event (client_mon, NULL, NULL);
  294. assert (event == ZMQ_EVENT_CONNECTED);
  295. event = get_monitor_event (client_mon, NULL, NULL);
  296. assert (event == ZMQ_EVENT_MONITOR_STOPPED);
  297. // This is the flow of server events
  298. event = get_monitor_event (server_mon, NULL, NULL);
  299. assert (event == ZMQ_EVENT_LISTENING);
  300. event = get_monitor_event (server_mon, NULL, NULL);
  301. assert (event == ZMQ_EVENT_ACCEPTED);
  302. event = get_monitor_event (server_mon, NULL, NULL);
  303. assert (event == ZMQ_EVENT_CLOSED);
  304. event = get_monitor_event (server_mon, NULL, NULL);
  305. assert (event == ZMQ_EVENT_MONITOR_STOPPED);
  306. // Close down the sockets
  307. close_zero_linger (client_mon);
  308. close_zero_linger (server_mon);
  309. zmq_ctx_term (ctx);
  310. return 0 ;
  311. }
  312. ----
  313. SEE ALSO
  314. --------
  315. linkzmq:zmq[7]
  316. AUTHORS
  317. -------
  318. This page was written by the 0MQ community. To make a change please
  319. read the 0MQ Contribution Policy at <http://www.zeromq.org/docs:contributing>.