/dep/zmqpp/zmqpp/socket.cpp

https://gitlab.com/IlluminatiCore/IlluminatiCore · C++ · 762 lines · 629 code · 100 blank · 33 comment · 183 complexity · 03e8a6de962337fa66062548503cf796 MD5 · raw file

  1. /*
  2. * Created on: 9 Aug 2011
  3. * Author: Ben Gray (@benjamg)
  4. */
  5. #include <array>
  6. #include <cassert>
  7. #include <cstring>
  8. #include <functional>
  9. #include "context.hpp"
  10. #include "exception.hpp"
  11. #include "message.hpp"
  12. #include "socket.hpp"
  13. namespace zmqpp
  14. {
  15. const int socket::normal = 0;
  16. #if (ZMQ_VERSION_MAJOR == 2)
  17. const int socket::dont_wait = ZMQ_NOBLOCK;
  18. #else
  19. const int socket::dont_wait = ZMQ_DONTWAIT;
  20. #endif
  21. const int socket::send_more = ZMQ_SNDMORE;
  22. #ifdef ZMQ_EXPERIMENTAL_LABELS
  23. const int socket::send_label = ZMQ_SNDLABEL;
  24. #endif
  25. const int max_socket_option_buffer_size = 256;
  26. const int max_stream_buffer_size = 4096;
  27. socket::socket(const context& context, socket_type const type)
  28. : _socket(nullptr)
  29. , _type(type)
  30. , _recv_buffer()
  31. {
  32. _socket = zmq_socket(context, static_cast<int>(type));
  33. if(nullptr == _socket)
  34. {
  35. throw zmq_internal_exception();
  36. }
  37. zmq_msg_init(&_recv_buffer);
  38. }
  39. socket::~socket()
  40. {
  41. zmq_msg_close(&_recv_buffer);
  42. if (nullptr != _socket)
  43. {
  44. #ifndef NDEBUG // unused assert variable in release
  45. int result = zmq_close(_socket);
  46. assert(0 == result);
  47. #else
  48. zmq_close(_socket);
  49. #endif // NDEBUG
  50. _socket = nullptr;
  51. }
  52. }
  53. void socket::bind(endpoint_t const& endpoint)
  54. {
  55. int result = zmq_bind(_socket, endpoint.c_str());
  56. if (0 != result)
  57. {
  58. throw zmq_internal_exception();
  59. }
  60. }
  61. void socket::unbind(endpoint_t const& endpoint)
  62. {
  63. #if (ZMQ_VERSION_MAJOR > 3 || (ZMQ_VERSION_MAJOR == 3 && ZMQ_VERSION_MINOR >= 2))
  64. int result = zmq_unbind(_socket, endpoint.c_str());
  65. if (0 != result)
  66. {
  67. throw zmq_internal_exception();
  68. }
  69. #endif
  70. }
  71. void socket::connect(endpoint_t const& endpoint)
  72. {
  73. int result = zmq_connect(_socket, endpoint.c_str());
  74. if (0 != result)
  75. {
  76. throw zmq_internal_exception();
  77. }
  78. }
  79. void socket::disconnect(endpoint_t const& endpoint)
  80. {
  81. #if (ZMQ_VERSION_MAJOR > 3 || (ZMQ_VERSION_MAJOR == 3 && ZMQ_VERSION_MINOR >= 2))
  82. int result = zmq_disconnect(_socket, endpoint.c_str());
  83. if (0 != result)
  84. {
  85. throw zmq_internal_exception();
  86. }
  87. #endif
  88. }
  89. void socket::close()
  90. {
  91. int result = zmq_close(_socket);
  92. if (0 != result)
  93. {
  94. throw zmq_internal_exception();
  95. }
  96. _socket = nullptr;
  97. }
  98. bool socket::send(message& message, bool const dont_block /* = false */)
  99. {
  100. size_t parts = message.parts();
  101. if (parts == 0)
  102. {
  103. throw std::invalid_argument("sending requires messages have at least one part");
  104. }
  105. bool dont_wait = dont_block;
  106. for(size_t i = 0; i < parts; ++i)
  107. {
  108. int flag = socket::normal;
  109. if(dont_wait) { flag |= socket::dont_wait; }
  110. if(i < (parts - 1)) { flag |= socket::send_more; }
  111. #if (ZMQ_VERSION_MAJOR == 2)
  112. int result = zmq_send( _socket, &message.raw_msg(i), flag );
  113. #elif (ZMQ_VERSION_MAJOR < 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR < 2))
  114. int result = zmq_sendmsg( _socket, &message.raw_msg(i), flag );
  115. #else
  116. int result = zmq_msg_send( &message.raw_msg(i), _socket, flag );
  117. #endif
  118. if (result < 0)
  119. {
  120. // the zmq framework should not block if the first part is accepted
  121. // so we should only ever get this error on the first part
  122. if((0 == i) && (EAGAIN == zmq_errno()))
  123. {
  124. return false;
  125. }
  126. if(EINTR == zmq_errno())
  127. {
  128. if (0 == message.parts())
  129. {
  130. return false;
  131. }
  132. // If we have an interrupt but it's not on the first part then we
  133. // know we can safely send out the rest of the message as we can
  134. // enforce that it won't wait on a blocking action
  135. dont_wait = true;
  136. continue;
  137. }
  138. // sanity checking
  139. assert(EAGAIN != zmq_errno());
  140. throw zmq_internal_exception();
  141. }
  142. message.sent(i);
  143. }
  144. // Leave message reference in a stable state
  145. zmqpp::message local;
  146. std::swap(local, message);
  147. return true;
  148. }
  149. bool socket::receive(message& message, bool const dont_block /* = false */)
  150. {
  151. if (message.parts() > 0)
  152. {
  153. // swap and discard old message
  154. zmqpp::message local;
  155. std::swap(local, message);
  156. }
  157. int flags = (dont_block) ? socket::dont_wait : socket::normal;
  158. bool more = true;
  159. while(more)
  160. {
  161. #if (ZMQ_VERSION_MAJOR == 2)
  162. int result = zmq_recv( _socket, &_recv_buffer, flags );
  163. #elif (ZMQ_VERSION_MAJOR < 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR < 2))
  164. int result = zmq_recvmsg( _socket, &_recv_buffer, flags );
  165. #else
  166. int result = zmq_msg_recv( &_recv_buffer, _socket, flags );
  167. #endif
  168. if(result < 0)
  169. {
  170. if ((0 == message.parts()) && (EAGAIN == zmq_errno()))
  171. {
  172. return false;
  173. }
  174. if(EINTR == zmq_errno())
  175. {
  176. if (0 == message.parts())
  177. {
  178. return false;
  179. }
  180. // If we have an interrupt but it's not on the first part then we
  181. // know we can safely pull out the rest of the message as it will
  182. // not be blocking
  183. continue;
  184. }
  185. assert(EAGAIN != zmq_errno());
  186. throw zmq_internal_exception();
  187. }
  188. zmq_msg_t& dest = message.raw_new_msg();
  189. zmq_msg_move(&dest, &_recv_buffer);
  190. get(socket_option::receive_more, more);
  191. }
  192. return true;
  193. }
  194. bool socket::send(std::string const& string, int const flags /* = NORMAL */)
  195. {
  196. return send_raw(string.data(), string.size(), flags);
  197. }
  198. bool socket::receive(std::string& string, int const flags /* = NORMAL */)
  199. {
  200. #if (ZMQ_VERSION_MAJOR == 2)
  201. int result = zmq_recv( _socket, &_recv_buffer, flags );
  202. #elif (ZMQ_VERSION_MAJOR < 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR < 2))
  203. int result = zmq_recvmsg( _socket, &_recv_buffer, flags );
  204. #else
  205. int result = zmq_msg_recv( &_recv_buffer, _socket, flags );
  206. #endif
  207. if(result >= 0)
  208. {
  209. string.reserve(zmq_msg_size(&_recv_buffer));
  210. string.assign(static_cast<char*>(zmq_msg_data(&_recv_buffer)), zmq_msg_size(&_recv_buffer));
  211. return true;
  212. }
  213. if (EAGAIN == zmq_errno() || EINTR == zmq_errno())
  214. {
  215. return false;
  216. }
  217. throw zmq_internal_exception();
  218. }
  219. bool socket::send_raw(char const* buffer, int const length, int const flags /* = NORMAL */)
  220. {
  221. #if (ZMQ_VERSION_MAJOR == 2)
  222. zmq_msg_t msg;
  223. int result = zmq_msg_init_size(&msg, length);
  224. if (result != 0)
  225. {
  226. zmq_internal_exception();
  227. }
  228. memcpy(zmq_msg_data(&msg), buffer, length);
  229. result = zmq_send(_socket, &msg, flags);
  230. #else
  231. int result = zmq_send(_socket, buffer, length, flags);
  232. #endif
  233. if(result >= 0)
  234. {
  235. return true;
  236. }
  237. #if (ZMQ_VERSION_MAJOR == 2)
  238. // only actually need to close this on error
  239. zmq_msg_close(&msg);
  240. #endif
  241. if (EAGAIN == zmq_errno() || EINTR == zmq_errno())
  242. {
  243. return false;
  244. }
  245. throw zmq_internal_exception();
  246. }
  247. bool socket::receive_raw(char* buffer, int& length, int const flags /* = NORMAL */)
  248. {
  249. #if (ZMQ_VERSION_MAJOR == 2)
  250. int result = zmq_recv( _socket, &_recv_buffer, flags );
  251. #elif (ZMQ_VERSION_MAJOR < 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR < 2))
  252. int result = zmq_recvmsg( _socket, &_recv_buffer, flags );
  253. #else
  254. int result = zmq_msg_recv( &_recv_buffer, _socket, flags );
  255. #endif
  256. if(result >= 0)
  257. {
  258. length = zmq_msg_size(&_recv_buffer);
  259. memcpy(buffer, zmq_msg_data(&_recv_buffer), length);
  260. return true;
  261. }
  262. if (EAGAIN == zmq_errno() || EINTR == zmq_errno())
  263. {
  264. return false;
  265. }
  266. throw zmq_internal_exception();
  267. }
  268. // Helper
  269. void socket::subscribe(std::string const& topic)
  270. {
  271. set(socket_option::subscribe, topic);
  272. }
  273. void socket::unsubscribe(std::string const& topic)
  274. {
  275. set(socket_option::unsubscribe, topic);
  276. }
  277. bool socket::has_more_parts() const
  278. {
  279. return get<bool>(socket_option::receive_more);
  280. }
  281. // Set socket options for different types of option
  282. void socket::set(socket_option const option, int const value)
  283. {
  284. switch(option)
  285. {
  286. // unsigned 64bit Integers
  287. #if (ZMQ_VERSION_MAJOR == 2)
  288. case socket_option::high_water_mark:
  289. case socket_option::send_buffer_size:
  290. case socket_option::receive_buffer_size:
  291. #endif
  292. case socket_option::affinity:
  293. if (value < 0) { throw exception("attempting to set an unsigned 64 bit integer option with a negative integer"); }
  294. set(option, static_cast<uint64_t>(value));
  295. break;
  296. // 64bit Integers
  297. #if (ZMQ_VERSION_MAJOR == 2)
  298. case socket_option::rate:
  299. case socket_option::recovery_interval:
  300. case socket_option::recovery_interval_seconds:
  301. case socket_option::swap_size:
  302. #else
  303. case socket_option::max_messsage_size:
  304. #endif
  305. set(option, static_cast<int64_t>(value));
  306. break;
  307. // Boolean
  308. #if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 1))
  309. case socket_option::ipv4_only:
  310. #endif
  311. #if (ZMQ_VERSION_MAJOR == 2)
  312. case socket_option::multicast_loopback:
  313. #endif
  314. #if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 2))
  315. #if (ZMQ_VERSION_MINOR == 2)
  316. case socket_option::delay_attach_on_connect:
  317. #else
  318. case socket_option::immediate:
  319. #endif
  320. case socket_option::router_mandatory:
  321. case socket_option::xpub_verbose:
  322. #endif
  323. if (value == 0) { set(option, false); }
  324. else if (value == 1) { set(option, true); }
  325. else { throw exception("attempting to set a boolean option with a non 0 or 1 integer"); }
  326. break;
  327. // Default or Boolean
  328. #if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 2))
  329. case socket_option::tcp_keepalive:
  330. if (value < -1 || value > 1) { throw exception("attempting to set a default or boolean option with a non -1, 0 or 1 integer"); }
  331. if (0 != zmq_setsockopt(_socket, static_cast<int>(option), &value, sizeof(value)))
  332. {
  333. throw zmq_internal_exception();
  334. }
  335. break;
  336. #endif
  337. // Integers that require +ve numbers
  338. #if (ZMQ_VERSION_MAJOR == 2)
  339. case socket_option::reconnect_interval_max:
  340. #else
  341. case socket_option::reconnect_interval_max:
  342. case socket_option::send_buffer_size:
  343. case socket_option::recovery_interval:
  344. case socket_option::receive_buffer_size:
  345. case socket_option::send_high_water_mark:
  346. case socket_option::receive_high_water_mark:
  347. case socket_option::multicast_hops:
  348. case socket_option::rate:
  349. #endif
  350. case socket_option::backlog:
  351. if (value < 0) { throw exception("attempting to set a positive only integer option with a negative integer"); }
  352. // Integers
  353. case socket_option::reconnect_interval:
  354. case socket_option::linger:
  355. case socket_option::receive_timeout:
  356. case socket_option::send_timeout:
  357. #if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 2))
  358. case socket_option::tcp_keepalive_idle:
  359. case socket_option::tcp_keepalive_count:
  360. case socket_option::tcp_keepalive_interval:
  361. #endif
  362. if (0 != zmq_setsockopt(_socket, static_cast<int>(option), &value, sizeof(value)))
  363. {
  364. throw zmq_internal_exception();
  365. }
  366. break;
  367. default:
  368. throw exception("attempting to set a non signed integer option with a signed integer value");
  369. }
  370. }
  371. void socket::set(socket_option const option, bool const value)
  372. {
  373. switch(option)
  374. {
  375. #if (ZMQ_VERSION_MAJOR == 2)
  376. case socket_option::multicast_loopback:
  377. #endif
  378. #if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 1))
  379. case socket_option::ipv4_only:
  380. #endif
  381. #if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 2))
  382. #if (ZMQ_VERSION_MINOR == 2)
  383. case socket_option::delay_attach_on_connect:
  384. #else
  385. case socket_option::immediate:
  386. #endif
  387. case socket_option::router_mandatory:
  388. case socket_option::xpub_verbose:
  389. #endif
  390. {
  391. int ivalue = value ? 1 : 0;
  392. if (0 != zmq_setsockopt(_socket, static_cast<int>(option), &ivalue, sizeof(ivalue)))
  393. {
  394. throw zmq_internal_exception();
  395. }
  396. break;
  397. }
  398. default:
  399. throw exception("attempting to set a non boolean option with a boolean value");
  400. }
  401. }
  402. void socket::set(socket_option const option, uint64_t const value)
  403. {
  404. switch(option)
  405. {
  406. #if (ZMQ_VERSION_MAJOR == 2)
  407. // unsigned 64bit Integers
  408. case socket_option::high_water_mark:
  409. case socket_option::send_buffer_size:
  410. case socket_option::receive_buffer_size:
  411. #endif
  412. case socket_option::affinity:
  413. if (0 != zmq_setsockopt(_socket, static_cast<int>(option), &value, sizeof(value)))
  414. {
  415. throw zmq_internal_exception();
  416. }
  417. break;
  418. default:
  419. throw exception("attempting to set a non unsigned 64 bit integer option with a unsigned 64 bit integer value");
  420. }
  421. }
  422. void socket::set(socket_option const option, int64_t const value)
  423. {
  424. switch(option)
  425. {
  426. #if (ZMQ_VERSION_MAJOR == 2)
  427. case socket_option::rate:
  428. case socket_option::recovery_interval:
  429. case socket_option::recovery_interval_seconds:
  430. case socket_option::swap_size:
  431. #else
  432. case socket_option::max_messsage_size:
  433. #endif
  434. // zmq only allowed +ve int64_t options
  435. if (value < 0) { throw exception("attempting to set a positive only 64 bit integer option with a negative 64bit integer"); }
  436. if (0 != zmq_setsockopt(_socket, static_cast<int>(option), &value, sizeof(value)))
  437. {
  438. throw zmq_internal_exception();
  439. }
  440. break;
  441. default:
  442. throw exception("attempting to set a non 64 bit integer option with a 64 bit integer value");
  443. }
  444. }
  445. void socket::set(socket_option const option, char const* value, size_t const length)
  446. {
  447. switch(option)
  448. {
  449. case socket_option::identity:
  450. case socket_option::subscribe:
  451. case socket_option::unsubscribe:
  452. #if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 2))
  453. case socket_option::tcp_accept_filter:
  454. #endif
  455. if (0 != zmq_setsockopt(_socket, static_cast<int>(option), value, length))
  456. {
  457. throw zmq_internal_exception();
  458. }
  459. break;
  460. default:
  461. throw exception("attempting to set a non string option with a string value");
  462. }
  463. }
  464. // Get socket options, multiple versions for easy of use
  465. void socket::get(socket_option const option, int& value) const
  466. {
  467. size_t value_size = sizeof(int);
  468. switch(option)
  469. {
  470. #if (ZMQ_VERSION_MAJOR == 2)
  471. case socket_option::receive_more:
  472. case socket_option::multicast_loopback:
  473. value = static_cast<int>(get<int64_t>(option));
  474. break;
  475. #endif
  476. case socket_option::type:
  477. case socket_option::linger:
  478. case socket_option::backlog:
  479. case socket_option::reconnect_interval:
  480. case socket_option::reconnect_interval_max:
  481. case socket_option::receive_timeout:
  482. case socket_option::send_timeout:
  483. case socket_option::file_descriptor:
  484. case socket_option::events:
  485. #if (ZMQ_VERSION_MAJOR > 2)
  486. case socket_option::receive_more:
  487. case socket_option::send_buffer_size:
  488. case socket_option::receive_buffer_size:
  489. case socket_option::rate:
  490. case socket_option::recovery_interval:
  491. case socket_option::send_high_water_mark:
  492. case socket_option::receive_high_water_mark:
  493. case socket_option::multicast_hops:
  494. #endif
  495. #if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 1))
  496. case socket_option::ipv4_only:
  497. #endif
  498. #if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 2))
  499. #if (ZMQ_VERSION_MINOR == 2)
  500. case socket_option::delay_attach_on_connect:
  501. #else
  502. case socket_option::immediate:
  503. #endif
  504. case socket_option::tcp_keepalive:
  505. case socket_option::tcp_keepalive_idle:
  506. case socket_option::tcp_keepalive_count:
  507. case socket_option::tcp_keepalive_interval:
  508. #endif
  509. #ifdef ZMQ_EXPERIMENTAL_LABELS
  510. case socket_option::receive_label:
  511. #endif
  512. if (0 != zmq_getsockopt(_socket, static_cast<int>(option), &value, &value_size))
  513. {
  514. throw zmq_internal_exception();
  515. }
  516. // sanity check
  517. assert(value_size <= sizeof(int));
  518. break;
  519. default:
  520. throw exception("attempting to get a non integer option with an integer value");
  521. }
  522. }
  523. void socket::get(socket_option const option, bool& value) const
  524. {
  525. #if (ZMQ_VERSION_MAJOR == 2)
  526. int64_t int_value = 0;
  527. size_t value_size = sizeof(int64_t);
  528. #else
  529. int int_value = 0;
  530. size_t value_size = sizeof(int);
  531. #endif
  532. switch(option)
  533. {
  534. case socket_option::receive_more:
  535. #if (ZMQ_VERSION_MAJOR == 2)
  536. case socket_option::multicast_loopback:
  537. #endif
  538. #if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 1))
  539. case socket_option::ipv4_only:
  540. #endif
  541. #if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 2))
  542. #if (ZMQ_VERSION_MINOR == 2)
  543. case socket_option::delay_attach_on_connect:
  544. #else
  545. case socket_option::immediate:
  546. #endif
  547. #endif
  548. #ifdef ZMQ_EXPERIMENTAL_LABELS
  549. case socket_option::receive_label:
  550. #endif
  551. if (0 != zmq_getsockopt(_socket, static_cast<int>(option), &int_value, &value_size))
  552. {
  553. throw zmq_internal_exception();
  554. }
  555. value = (int_value == 1) ? true : false;
  556. break;
  557. default:
  558. throw exception("attempting to get a non boolean option with a boolean value");
  559. }
  560. }
  561. void socket::get(socket_option const option, uint64_t& value) const
  562. {
  563. size_t value_size = sizeof(uint64_t);
  564. switch(option)
  565. {
  566. #if (ZMQ_VERSION_MAJOR == 2)
  567. case socket_option::high_water_mark:
  568. case socket_option::send_buffer_size:
  569. case socket_option::receive_buffer_size:
  570. #endif
  571. case socket_option::affinity:
  572. if(0 != zmq_getsockopt(_socket, static_cast<int>(option), &value, &value_size))
  573. {
  574. throw zmq_internal_exception();
  575. }
  576. break;
  577. default:
  578. throw exception("attempting to get a non unsigned 64 bit integer option with an unsigned 64 bit integer value");
  579. }
  580. }
  581. void socket::get(socket_option const option, int64_t& value) const
  582. {
  583. size_t value_size = sizeof(int64_t);
  584. switch(option)
  585. {
  586. #if (ZMQ_VERSION_MAJOR == 2)
  587. case socket_option::rate:
  588. case socket_option::recovery_interval:
  589. case socket_option::recovery_interval_seconds:
  590. case socket_option::swap_size:
  591. case socket_option::receive_more:
  592. case socket_option::multicast_loopback:
  593. #else
  594. case socket_option::max_messsage_size:
  595. #endif
  596. if(0 != zmq_getsockopt(_socket, static_cast<int>(option), &value, &value_size))
  597. {
  598. throw zmq_internal_exception();
  599. }
  600. break;
  601. default:
  602. throw exception("attempting to get a non 64 bit integer option with an 64 bit integer value");
  603. }
  604. }
  605. void socket::get(socket_option const option, std::string& value) const
  606. {
  607. static std::array<char, max_socket_option_buffer_size> buffer;
  608. size_t size = max_socket_option_buffer_size;
  609. switch(option)
  610. {
  611. case socket_option::identity:
  612. #if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 2))
  613. case socket_option::last_endpoint:
  614. #endif
  615. if(0 != zmq_getsockopt(_socket, static_cast<int>(option), buffer.data(), &size))
  616. {
  617. throw zmq_internal_exception();
  618. }
  619. value.assign(buffer.data(), size);
  620. break;
  621. default:
  622. throw exception("attempting to get a non string option with a string value");
  623. }
  624. }
  625. socket::socket(socket&& source) NOEXCEPT
  626. : _socket(source._socket)
  627. , _type(source._type)
  628. , _recv_buffer()
  629. {
  630. // we steal the zmq_msg_t from the valid socket, we only init our own because it's cheap
  631. // and zmq_msg_move does a valid check
  632. zmq_msg_init(&_recv_buffer);
  633. zmq_msg_move(&_recv_buffer, &source._recv_buffer);
  634. // Clean up source a little, we will handle the deinit, it doesn't need to
  635. source._socket = nullptr;
  636. }
  637. socket& socket::operator=(socket&& source) NOEXCEPT
  638. {
  639. std::swap(_socket, source._socket);
  640. _type = source._type; // just clone?
  641. // we steal the zmq_msg_t from the valid socket, we only init our own because it's cheap
  642. // and zmq_msg_move does a valid check
  643. zmq_msg_init(&_recv_buffer);
  644. zmq_msg_move(&_recv_buffer, &source._recv_buffer);
  645. return *this;
  646. }
  647. socket::operator bool() const
  648. {
  649. return nullptr != _socket;
  650. }
  651. socket::operator void*() const
  652. {
  653. return _socket;
  654. }
  655. void socket::track_message(message const& /* message */, uint32_t const parts, bool& should_delete)
  656. {
  657. if (parts == 0)
  658. {
  659. should_delete = true;
  660. }
  661. }
  662. }