PageRenderTime 45ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/zmqpp/socket.hpp

https://github.com/datasift/zmqpp
C++ Header | 517 lines | 114 code | 55 blank | 348 comment | 9 complexity | b3fb7d7432c4ae6975b1410c42db4e05 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-3.0
  1. /**
  2. * \file
  3. *
  4. * \date 9 Aug 2011
  5. * \author Ben Gray (\@benjamg)
  6. */
  7. #ifndef ZMQPP_SOCKET_HPP_
  8. #define ZMQPP_SOCKET_HPP_
  9. #include <cstring>
  10. #include <string>
  11. #include <list>
  12. #include <zmq.h>
  13. #include "compatibility.hpp"
  14. #include "socket_types.hpp"
  15. #include "socket_options.hpp"
  16. namespace zmqpp
  17. {
  18. class context;
  19. class message;
  20. typedef std::string endpoint_t;
  21. typedef context context_t;
  22. typedef message message_t;
  23. /*!
  24. * The socket class represents the zmq sockets.
  25. *
  26. * A socket can be bound and/or connected to as many endpoints as required
  27. * with the sole exception of a ::pair socket.
  28. *
  29. * The routing is handled by zmq based on the type set.
  30. *
  31. * The bound side of an inproc connection must occur first and inproc can only
  32. * connect to other inproc sockets of the same context.
  33. *
  34. * This class is c++0x move supporting and cannot be copied.
  35. */
  36. class socket
  37. {
  38. public:
  39. static const int normal = 0; /*!< /brief default send type, no flags set */
  40. #if (ZMQ_VERSION_MAJOR == 2)
  41. static const int dont_wait = ZMQ_NOBLOCK; /*!< /brief don't block if sending is not currently possible */
  42. #else
  43. static const int dont_wait = ZMQ_DONTWAIT; /*!< /brief don't block if sending is not currently possible */
  44. #endif
  45. static const int send_more = ZMQ_SNDMORE; /*!< /brief more parts will follow this one */
  46. #ifdef ZMQ_EXPERIMENTAL_LABELS
  47. static const int send_label = ZMQ_SNDLABEL; /*!< /brief this message part is an internal zmq label */
  48. #endif
  49. /*!
  50. * Create a socket for a given type.
  51. *
  52. * \param context the zmq context under which the socket will live
  53. * \param type a valid ::socket_type for the socket
  54. */
  55. socket( context_t const& context, socket_type const& type );
  56. /*!
  57. * Create a socket for a given type.
  58. *
  59. * \param context the zmq context under which the socket will live
  60. * \param type a valid ::socket_type for the socket
  61. * \param label a human-readable label describing the socket
  62. */
  63. socket( context_t const& context, socket_type const& type, std::string const& label );
  64. /*!
  65. * This will close any socket still open before returning
  66. */
  67. ~socket();
  68. /*!
  69. * Get the type of the socket, this works on zmqpp types and not the zmq internal types.
  70. * Use the socket::get method if you wish to intergoate the zmq internal ones.
  71. *
  72. * \return the type of the socket
  73. */
  74. socket_type type() const { return _type; }
  75. /*!
  76. * Get the descriptive label on the socket.
  77. *
  78. * \return the label on the socket
  79. */
  80. std::string const& label() const { return _label; }
  81. /*!
  82. * Asynchronously binds to an endpoint.
  83. *
  84. * \param endpoint the zmq endpoint to bind to
  85. */
  86. void bind(endpoint_t const& endpoint);
  87. /*!
  88. * Unbinds from a previously bound endpoint.
  89. *
  90. * \param endpoint the zmq endpoint to bind to
  91. */
  92. void unbind(endpoint_t const& endpoint);
  93. /*!
  94. * Asynchronously connects to an endpoint.
  95. * If the endpoint is not inproc then zmq will happily keep trying
  96. * to connect until there is something there.
  97. *
  98. * Inproc sockets must have a valid target already bound before connection
  99. * will work.
  100. *
  101. * \param endpoint the zmq endpoint to connect to
  102. */
  103. void connect(endpoint_t const& endpoint);
  104. /*!
  105. * Asynchronously connects to multiple endpoints.
  106. * If the endpoint is not inproc then zmq will happily keep trying
  107. * to connect until there is something there.
  108. *
  109. * Inproc sockets must have a valid target already bound before connection
  110. * will work.
  111. *
  112. * This is a helper function that wraps the single item connect in a loop
  113. *
  114. * \param connections_begin the starting iterator for zmq endpoints.
  115. * \param connections_end the final iterator for zmq endpoints.
  116. */
  117. template<typename InputIterator>
  118. void connect(InputIterator const& connections_begin, InputIterator const& connections_end)
  119. {
  120. for(InputIterator it = connections_begin; it != connections_end; ++it)
  121. {
  122. connect(*it);
  123. }
  124. }
  125. /*!
  126. * Disconnects a previously connected endpoint.
  127. *
  128. * \param endpoint the zmq endpoint to disconnect from
  129. */
  130. void disconnect(endpoint_t const& endpoint);
  131. /*!
  132. * Disconnects from multiple previously connected endpoints.
  133. *
  134. * This is a helper function that wraps the single item disconnect in a loop
  135. *
  136. * \param disconnections_begin the starting iterator for zmq endpoints.
  137. * \param disconnections_end the final iterator for zmq endpoints.
  138. */
  139. template<typename InputIterator>
  140. void disconnect(InputIterator const& disconnections_begin, InputIterator const& disconnections_end)
  141. {
  142. for(InputIterator it = disconnections_begin; it != disconnections_end; ++it)
  143. {
  144. disconnect(*it);
  145. }
  146. }
  147. /*!
  148. * Closes the internal zmq socket and marks this instance
  149. * as invalid.
  150. */
  151. void close();
  152. /*!
  153. * Sends the message over the connection, this may be a multipart message.
  154. *
  155. * If dont_block is true and we are unable to add a new message then this
  156. * function will return false.
  157. *
  158. * \param message message to send
  159. * \param dont_block boolean to dictate if we wait while sending.
  160. * \return true if message sent, false if it would have blocked
  161. */
  162. bool send(message_t& message, bool const dont_block = false);
  163. /*!
  164. * Gets a message from the connection, this may be a multipart message.
  165. *
  166. * If dont_block is true and we are unable to get a message then this
  167. * function will return false.
  168. *
  169. * \param message reference to fill with received data
  170. * \param dont_block boolean to dictate if we wait for data.
  171. * \return true if message sent, false if it would have blocked
  172. */
  173. bool receive(message_t& message, bool const dont_block = false);
  174. /*!
  175. * Sends the byte data held by the string as the next message part.
  176. *
  177. * If the socket::DONT_WAIT flag and we are unable to add a new message to
  178. * socket then this function will return false.
  179. *
  180. * \param string message part to send
  181. * \param flags message send flags
  182. * \return true if message part sent, false if it would have blocked
  183. */
  184. bool send(std::string const& string, int const flags = normal);
  185. /*!
  186. * If there is a message ready then get the next part as a string
  187. *
  188. * If the socket::DONT_WAIT flag and there is no message ready to receive
  189. * then this function will return false.
  190. *
  191. * \param string message part to receive into
  192. * \param flags message receive flags
  193. * \return true if message part received, false if it would have blocked
  194. */
  195. bool receive(std::string& string, int const flags = normal);
  196. /*!
  197. * Sends the byte data pointed to by buffer as the next part of the message.
  198. *
  199. * If the socket::DONT_WAIT flag and we are unable to add a new message to
  200. * socket then this function will return false.
  201. *
  202. * \param buffer byte buffer pointer to start writing from
  203. * \param length max length of the buffer
  204. * \param flags message send flags
  205. * \return true if message part sent, false if it would have blocked
  206. */
  207. bool send_raw(char const* buffer, int const length, int const flags = normal);
  208. /*!
  209. * \warning If the buffer is not large enough for the message part then the
  210. * data will be truncated. The rest of the part is lost forever.
  211. *
  212. * If there is a message ready then get the next part of it as a raw
  213. * byte buffer.
  214. *
  215. * If the socket::DONT_WAIT flag and there is no message ready to receive
  216. * then this function will return false.
  217. *
  218. * \param buffer byte buffer pointer to start writing to
  219. * \param length max length of the buffer
  220. * \param flags message receive flags
  221. * \return true if message part received, false if it would have blocked
  222. */
  223. bool receive_raw(char* buffer, int& length, int const flags = normal);
  224. /*!
  225. *
  226. * Subscribe to a topic
  227. *
  228. * Helper function that is equivalent of calling
  229. * \code
  230. * set(zmqpp::socket_option::subscribe, topic);
  231. * \endcode
  232. *
  233. * This method is only useful for subscribe type sockets.
  234. *
  235. * \param topic the topic to subscribe to.
  236. */
  237. void subscribe(std::string const& topic);
  238. /*!
  239. * Subscribe to a topic
  240. *
  241. * Helper function that is equivalent of a loop calling
  242. * \code
  243. * set(zmqpp::socket_option::subscribe, topic);
  244. * \endcode
  245. *
  246. * This method is only useful for subscribe type sockets.
  247. *
  248. * Generally this will be used with stl collections using begin() and
  249. * end() functions to get the iterators.
  250. * For this reason the end loop runs until the end iterator, not inclusive
  251. * of it.
  252. *
  253. * \param topics_begin the starting iterator for topics.
  254. * \param topics_end the final iterator for topics.
  255. */
  256. template<typename InputIterator>
  257. void subscribe(InputIterator const& topics_begin, InputIterator const& topics_end)
  258. {
  259. for(InputIterator it = topics_begin; it != topics_end; ++it)
  260. {
  261. subscribe(*it);
  262. }
  263. }
  264. /*!
  265. * Unsubscribe from a topic
  266. *
  267. * Helper function that is equivalent of calling
  268. * \code
  269. * set(zmqpp::socket_option::unsubscribe, topic);
  270. * \endcode
  271. *
  272. * This method is only useful for subscribe type sockets.
  273. *
  274. * \param topic the topic to unsubscribe from.
  275. */
  276. void unsubscribe(std::string const& topic);
  277. /*!
  278. * Unsubscribe from a topic
  279. *
  280. * Helper function that is equivalent of a loop calling
  281. * \code
  282. * set(zmqpp::socket_option::unsubscribe, topic);
  283. * \endcode
  284. *
  285. * This method is only useful for subscribe type sockets.
  286. *
  287. * Generally this will be used with stl collections using begin() and
  288. * end() functions to get the iterators.
  289. * For this reason the end loop runs until the end iterator, not inclusive
  290. * of it.
  291. *
  292. * \param topics_begin the starting iterator for topics.
  293. * \param topics_end the final iterator for topics.
  294. */
  295. template<typename InputIterator>
  296. void unsubscribe(InputIterator const& topics_begin, InputIterator const& topics_end)
  297. {
  298. for(InputIterator it = topics_begin; it != topics_end; ++it)
  299. {
  300. unsubscribe(*it);
  301. }
  302. }
  303. /*!
  304. * If the last receive part call to the socket resulted
  305. * in a label or a non-terminating part of a multipart
  306. * message this will return true.
  307. *
  308. * \return true if there are more parts
  309. */
  310. bool has_more_parts() const;
  311. /*!
  312. * Set the value of an option in the underlaying zmq socket.
  313. *
  314. * \param option a valid ::socket_option
  315. * \param value to set the option to
  316. */
  317. void set(socket_option const option, int const value);
  318. /*!
  319. * Set the value of an option in the underlaying zmq socket.
  320. *
  321. * \since 2.0.0 (built against 0mq version 3.1.x or later)
  322. *
  323. * \param option a valid ::socket_option
  324. * \param value to set the option to
  325. */
  326. void set(socket_option const option, bool const value);
  327. /*!
  328. * Set the value of an option in the underlaying zmq socket.
  329. *
  330. * \param option a valid ::socket_option
  331. * \param value to set the option to
  332. */
  333. void set(socket_option const option, uint64_t const value);
  334. /*!
  335. * Set the value of an option in the underlaying zmq socket.
  336. *
  337. * \param option a valid ::socket_option
  338. * \param value to set the option to
  339. */
  340. void set(socket_option const option, int64_t const value);
  341. /*!
  342. * Set the value of an option in the underlaying zmq socket.
  343. *
  344. * \param option a valid ::socket_option
  345. * \param pointer to raw byte value to set the option to
  346. * \param length the size of the raw byte value
  347. */
  348. void set(socket_option const option, char const* value, size_t const length);
  349. /*!
  350. * Set the value of an option in the underlaying zmq socket.
  351. *
  352. * \param option a valid ::socket_option
  353. * \param pointer to null terminated cstring value to set the option to
  354. */
  355. inline void set(socket_option const option, char const* value) { set(option, value, strlen(value)); }
  356. /*!
  357. * Set the value of an option in the underlaying zmq socket.
  358. *
  359. * \param option a valid ::socket_option
  360. * \param value to set the option to
  361. */
  362. inline void set(socket_option const option, std::string const value) { set(option, value.c_str(), value.length()); }
  363. /*!
  364. * Get a socket option from the underlaying zmq socket.
  365. *
  366. * \param option a valid ::socket_option
  367. * \param value referenced int to return value in
  368. */
  369. void get(socket_option const option, int& value) const;
  370. /*!
  371. * Get a socket option from the underlaying zmq socket.
  372. *
  373. * \param option a valid ::socket_option
  374. * \param value referenced bool to return value in
  375. */
  376. void get(socket_option const option, bool& value) const;
  377. /*!
  378. * Get a socket option from the underlaying zmq socket.
  379. *
  380. * \param option a valid ::socket_option
  381. * \param value referenced uint64_t to return value in
  382. */
  383. void get(socket_option const option, uint64_t& value) const;
  384. /*!
  385. * Get a socket option from the underlaying zmq socket.
  386. *
  387. * \param option a valid ::socket_option
  388. * \param value referenced uint64_t to return value in
  389. */
  390. void get(socket_option const option, int64_t& value) const;
  391. /*!
  392. * Get a socket option from the underlaying zmq socket.
  393. *
  394. * \param option a valid ::socket_option
  395. * \param value referenced std::string to return value in
  396. */
  397. void get(socket_option const option, std::string& value) const;
  398. /*!
  399. * For those that don't want to get into a referenced value this templated method
  400. * will return the value instead.
  401. *
  402. * \param option a valid ::socket_option
  403. * \return socket option value
  404. */
  405. template<typename Type>
  406. Type get(socket_option const option) const
  407. {
  408. Type value = Type();
  409. get(option, value);
  410. return value;
  411. }
  412. /*!
  413. * Move constructor
  414. *
  415. * Moves the internals of source to this object, there is no guarantee
  416. * that source will be left in a valid state.
  417. *
  418. * This constructor is noexcept and so will not throw exceptions
  419. *
  420. * \param source target socket to steal internals from
  421. */
  422. socket(socket&& source) noexcept;
  423. /*!
  424. * Move operator
  425. *
  426. * Moves the internals of source to this object, there is no guarantee
  427. * that source will be left in a valid state.
  428. *
  429. * This function is noexcept and so will not throw exceptions
  430. *
  431. * \param source target socket to steal internals from
  432. * \return socket reference to this
  433. */
  434. socket& operator=(socket&& source) noexcept;
  435. /*!
  436. * Check the socket is still valid
  437. *
  438. * This tests the internal state of the socket.
  439. * If creation failed for some reason or if the move functions were used
  440. * to move the socket internals to another instance this will return false.
  441. *
  442. * \return true if the socket is valid
  443. */
  444. operator bool() const;
  445. /*!
  446. * Access to the raw 0mq context
  447. *
  448. * \return void pointer to the underlying 0mq socket
  449. */
  450. operator void*() const;
  451. private:
  452. void* _socket;
  453. socket_type _type;
  454. std::string _label;
  455. zmq_msg_t _recv_buffer;
  456. // No copy
  457. socket(socket const&) noexcept ZMQPP_EXPLICITLY_DELETED;
  458. socket& operator=(socket const&) noexcept ZMQPP_EXPLICITLY_DELETED;
  459. void track_message(message_t const&, uint32_t const, bool&);
  460. };
  461. }
  462. #endif /* ZMQPP_SOCKET_HPP_ */