PageRenderTime 64ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/src/interface.cpp

https://github.com/brotchie/rzmq
C++ | 790 lines | 656 code | 107 blank | 27 comment | 151 complexity | aea4794e6672a53340710cdbab62a508 MD5 | raw file
  1. ///////////////////////////////////////////////////////////////////////////
  2. // Copyright (C) 2011 Whit Armstrong //
  3. // //
  4. // This program is free software: you can redistribute it and/or modify //
  5. // it under the terms of the GNU General Public License as published by //
  6. // the Free Software Foundation, either version 3 of the License, or //
  7. // (at your option) any later version. //
  8. // //
  9. // This program is distributed in the hope that it will be useful, //
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of //
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
  12. // GNU General Public License for more details. //
  13. // //
  14. // You should have received a copy of the GNU General Public License //
  15. // along with this program. If not, see <http://www.gnu.org/licenses/>. //
  16. ///////////////////////////////////////////////////////////////////////////
  17. #include <stdint.h>
  18. #include <string>
  19. #include <stdexcept>
  20. #include <zmq.hpp>
  21. #include "interface.h"
  22. int string_to_socket_type(const std::string s) {
  23. if(s == "ZMQ_PAIR") {
  24. return ZMQ_PAIR;
  25. } else if(s == "ZMQ_PUB") {
  26. return ZMQ_PUB;
  27. } else if(s == "ZMQ_SUB") {
  28. return ZMQ_SUB;
  29. } else if(s == "ZMQ_REQ") {
  30. return ZMQ_REQ;
  31. } else if(s == "ZMQ_REP") {
  32. return ZMQ_REP;
  33. } else if(s == "ZMQ_DEALER") {
  34. return ZMQ_DEALER;
  35. } else if(s == "ZMQ_ROUTER") {
  36. return ZMQ_ROUTER;
  37. } else if(s == "ZMQ_PULL") {
  38. return ZMQ_PULL;
  39. } else if(s == "ZMQ_PUSH") {
  40. return ZMQ_PUSH;
  41. } else if(s == "ZMQ_XPUB") {
  42. return ZMQ_XPUB;
  43. } else if(s == "ZMQ_XSUB") {
  44. return ZMQ_XSUB;
  45. } else {
  46. return -1;
  47. }
  48. }
  49. void* checkExternalPointer(SEXP xp_, const char* valid_tag) {
  50. if(xp_ == R_NilValue) {
  51. throw std::logic_error("External pointer is NULL.");
  52. }
  53. if(TYPEOF(xp_) != EXTPTRSXP) {
  54. throw std::logic_error("Not an external pointer.");
  55. }
  56. if(R_ExternalPtrTag(xp_)==R_NilValue) {
  57. throw std::logic_error("External pointer tag is NULL.");
  58. }
  59. const char* xp_tag = CHAR(PRINTNAME(R_ExternalPtrTag(xp_)));
  60. if(!xp_tag) {
  61. throw std::logic_error("External pointer tag is blank.");
  62. }
  63. if(strcmp(xp_tag,valid_tag) != 0) {
  64. throw std::logic_error("External pointer tag does not match.");
  65. }
  66. if(R_ExternalPtrAddr(xp_)==NULL) {
  67. throw std::logic_error("External pointer address is null.");
  68. }
  69. return R_ExternalPtrAddr(xp_);
  70. }
  71. static void contextFinalizer(SEXP context_) {
  72. zmq::context_t* context = reinterpret_cast<zmq::context_t*>(R_ExternalPtrAddr(context_));
  73. if(context) {
  74. delete context;
  75. R_ClearExternalPtr(context_);
  76. }
  77. }
  78. static void socketFinalizer(SEXP socket_) {
  79. zmq::socket_t* socket = reinterpret_cast<zmq::socket_t*>(checkExternalPointer(socket_,"zmq::socket_t*"));
  80. if(socket) {
  81. delete socket;
  82. R_ClearExternalPtr(socket_);
  83. }
  84. }
  85. SEXP initContext() {
  86. SEXP context_;
  87. zmq::context_t* context = new zmq::context_t(1);
  88. if(context) {
  89. PROTECT(context_ = R_MakeExternalPtr(reinterpret_cast<void*>(context),install("zmq::context_t*"),R_NilValue));
  90. R_RegisterCFinalizerEx(context_, contextFinalizer, TRUE);
  91. UNPROTECT(1);
  92. return context_;
  93. } else {
  94. return R_NilValue;
  95. }
  96. }
  97. SEXP initSocket(SEXP context_, SEXP socket_type_) {
  98. SEXP socket_;
  99. if(TYPEOF(socket_type_) != STRSXP) {
  100. REprintf("socket type must be a string.\n");
  101. return R_NilValue;
  102. }
  103. int socket_type = string_to_socket_type(CHAR(STRING_ELT(socket_type_,0)));
  104. if(socket_type < 0) {
  105. REprintf("socket type not found.\n");
  106. return R_NilValue;
  107. }
  108. zmq::context_t* context(NULL);
  109. try {
  110. context = reinterpret_cast<zmq::context_t*>(checkExternalPointer(context_,"zmq::context_t*"));
  111. } catch(std::logic_error &e) {
  112. REprintf("%s\n",e.what());
  113. return R_NilValue;
  114. }
  115. zmq::socket_t* socket = new zmq::socket_t(*context,socket_type);
  116. if(!socket) { REprintf("bad socket object.\n");return R_NilValue; }
  117. // for debugging
  118. //uint64_t hwm = 1;
  119. //socket->setsockopt(ZMQ_HWM, &hwm, sizeof (hwm));
  120. PROTECT(socket_ = R_MakeExternalPtr(reinterpret_cast<void*>(socket),install("zmq::socket_t*"),R_NilValue));
  121. R_RegisterCFinalizerEx(socket_, socketFinalizer, TRUE);
  122. UNPROTECT(1);
  123. return socket_;
  124. }
  125. SEXP bindSocket(SEXP socket_, SEXP address_) {
  126. SEXP ans; PROTECT(ans = allocVector(LGLSXP,1)); LOGICAL(ans)[0] = 1;
  127. if(TYPEOF(address_) != STRSXP) {
  128. REprintf("address type must be a string.\n");
  129. UNPROTECT(1);
  130. return R_NilValue;
  131. }
  132. try {
  133. zmq::socket_t* socket = reinterpret_cast<zmq::socket_t*>(checkExternalPointer(socket_,"zmq::socket_t*"));
  134. socket->bind(CHAR(STRING_ELT(address_,0)));
  135. } catch(std::exception& e) {
  136. REprintf("%s\n",e.what());
  137. LOGICAL(ans)[0] = 0;
  138. }
  139. UNPROTECT(1);
  140. return ans;
  141. }
  142. static short rzmq_build_event_bitmask(SEXP askevents) {
  143. short bitmask = 0;
  144. if(TYPEOF(askevents) == STRSXP) {
  145. for (int i = 0; i < LENGTH(askevents); i++) {
  146. const char *ask = translateChar(STRING_ELT(askevents, i));
  147. if (strcmp(ask, "read") == 0) {
  148. bitmask |= ZMQ_POLLIN;
  149. } else if (strcmp(ask, "write") == 0) {
  150. bitmask |= ZMQ_POLLOUT;
  151. } else if (strcmp(ask, "error") == 0) {
  152. bitmask |= ZMQ_POLLERR;
  153. } else {
  154. error("unrecognized requests poll event %s.", ask);
  155. }
  156. }
  157. } else {
  158. error("event list passed to poll must be a string or vector of strings");
  159. }
  160. return bitmask;
  161. }
  162. SEXP pollSocket(SEXP sockets_, SEXP events_, SEXP timeout_) {
  163. SEXP result;
  164. if(TYPEOF(timeout_) != INTSXP) {
  165. error("poll timeout must be an integer.");
  166. }
  167. if(TYPEOF(sockets_) != VECSXP || LENGTH(sockets_) == 0) {
  168. error("A non-empy list of sockets is required as first argument.");
  169. }
  170. int nsock = LENGTH(sockets_);
  171. PROTECT(result = allocVector(VECSXP, nsock));
  172. if (TYPEOF(events_) != VECSXP) {
  173. error("event list must be a list of strings or a list of vectors of strings.");
  174. }
  175. if(LENGTH(events_) != nsock) {
  176. error("event list must be the same length as socket list.");
  177. }
  178. zmq_pollitem_t *pitems = (zmq_pollitem_t*)R_alloc(nsock, sizeof(zmq_pollitem_t));
  179. if (pitems == NULL) {
  180. error("failed to allocate memory for zmq_pollitem_t array.");
  181. }
  182. try {
  183. for (int i = 0; i < nsock; i++) {
  184. zmq::socket_t* socket = reinterpret_cast<zmq::socket_t*>(checkExternalPointer(VECTOR_ELT(sockets_, i), "zmq::socket_t*"));
  185. pitems[i].socket = (void*)*socket;
  186. pitems[i].events = rzmq_build_event_bitmask(VECTOR_ELT(events_, i));
  187. }
  188. int rc = zmq::poll(pitems, nsock, *INTEGER(timeout_));
  189. if(rc >= 0) {
  190. for (int i = 0; i < nsock; i++) {
  191. SEXP events, names;
  192. // Pre count number of polled events so we can
  193. // allocate appropriately sized lists.
  194. short eventcount = 0;
  195. if (pitems[i].events & ZMQ_POLLIN) eventcount++;
  196. if (pitems[i].events & ZMQ_POLLOUT) eventcount++;
  197. if (pitems[i].events & ZMQ_POLLERR) eventcount++;
  198. PROTECT(events = allocVector(VECSXP, eventcount));
  199. PROTECT(names = allocVector(VECSXP, eventcount));
  200. eventcount = 0;
  201. if (pitems[i].events & ZMQ_POLLIN) {
  202. SET_VECTOR_ELT(events, eventcount, ScalarLogical(pitems[i].revents & ZMQ_POLLIN));
  203. SET_VECTOR_ELT(names, eventcount, mkChar("read"));
  204. eventcount++;
  205. }
  206. if (pitems[i].events & ZMQ_POLLOUT) {
  207. SET_VECTOR_ELT(names, eventcount, mkChar("write"));
  208. SET_VECTOR_ELT(events, eventcount, ScalarLogical(pitems[i].revents & ZMQ_POLLOUT));
  209. eventcount++;
  210. }
  211. if (pitems[i].events & ZMQ_POLLERR) {
  212. SET_VECTOR_ELT(names, eventcount, mkChar("error"));
  213. SET_VECTOR_ELT(events, eventcount, ScalarLogical(pitems[i].revents & ZMQ_POLLERR));
  214. }
  215. setAttrib(events, R_NamesSymbol, names);
  216. SET_VECTOR_ELT(result, i, events);
  217. }
  218. } else {
  219. error("polling zmq sockets failed.");
  220. }
  221. } catch(std::exception& e) {
  222. error(e.what());
  223. }
  224. // Release the result list (1), and per socket
  225. // events lists with associated names (2*nsock).
  226. UNPROTECT(1 + 2*nsock);
  227. return result;
  228. }
  229. SEXP connectSocket(SEXP socket_, SEXP address_) {
  230. SEXP ans; PROTECT(ans = allocVector(LGLSXP,1)); LOGICAL(ans)[0] = 1;
  231. if(TYPEOF(address_) != STRSXP) {
  232. REprintf("address type must be a string.\n");
  233. UNPROTECT(1);
  234. return R_NilValue;
  235. }
  236. try {
  237. zmq::socket_t* socket = reinterpret_cast<zmq::socket_t*>(checkExternalPointer(socket_,"zmq::socket_t*"));
  238. socket->connect(CHAR(STRING_ELT(address_,0)));
  239. } catch(std::exception& e) {
  240. REprintf("%s\n",e.what());
  241. LOGICAL(ans)[0] = 0;
  242. }
  243. UNPROTECT(1);
  244. return ans;
  245. }
  246. SEXP sendSocket(SEXP socket_, SEXP data_, SEXP send_more_) {
  247. SEXP ans; PROTECT(ans = allocVector(LGLSXP,1));
  248. bool status(false);
  249. if(TYPEOF(data_) != RAWSXP) {
  250. REprintf("data type must be raw (RAWSXP).\n");
  251. UNPROTECT(1);
  252. return R_NilValue;
  253. }
  254. if(TYPEOF(send_more_) != LGLSXP) {
  255. REprintf("send.more type must be logical (LGLSXP).\n");
  256. UNPROTECT(1);
  257. return R_NilValue;
  258. }
  259. zmq::socket_t* socket = reinterpret_cast<zmq::socket_t*>(checkExternalPointer(socket_,"zmq::socket_t*"));
  260. if(!socket) { REprintf("bad socket object.\n");return R_NilValue; }
  261. zmq::message_t msg (length(data_));
  262. memcpy(msg.data(), RAW(data_), length(data_));
  263. bool send_more = LOGICAL(send_more_)[0];
  264. try {
  265. if(send_more) {
  266. status = socket->send(msg,ZMQ_SNDMORE);
  267. } else {
  268. status = socket->send(msg);
  269. }
  270. } catch(std::exception& e) {
  271. REprintf("%s\n",e.what());
  272. }
  273. LOGICAL(ans)[0] = static_cast<int>(status);
  274. UNPROTECT(1);
  275. return ans;
  276. }
  277. SEXP sendNullMsg(SEXP socket_, SEXP send_more_) {
  278. SEXP ans; PROTECT(ans = allocVector(LGLSXP,1));
  279. bool status(false);
  280. if(TYPEOF(send_more_) != LGLSXP) {
  281. REprintf("send.more type must be logical (LGLSXP).\n");
  282. UNPROTECT(1);
  283. return R_NilValue;
  284. }
  285. zmq::socket_t* socket = reinterpret_cast<zmq::socket_t*>(checkExternalPointer(socket_,"zmq::socket_t*"));
  286. if(!socket) { REprintf("bad socket object.\n");return R_NilValue; }
  287. zmq::message_t msg(0);
  288. bool send_more = LOGICAL(send_more_)[0];
  289. try {
  290. if(send_more) {
  291. status = socket->send(msg,ZMQ_SNDMORE);
  292. } else {
  293. status = socket->send(msg);
  294. }
  295. } catch(std::exception& e) {
  296. REprintf("%s\n",e.what());
  297. }
  298. LOGICAL(ans)[0] = static_cast<int>(status);
  299. UNPROTECT(1);
  300. return ans;
  301. }
  302. SEXP receiveNullMsg(SEXP socket_) {
  303. SEXP ans; PROTECT(ans = allocVector(LGLSXP,1));
  304. bool status(false);
  305. zmq::socket_t* socket = reinterpret_cast<zmq::socket_t*>(checkExternalPointer(socket_,"zmq::socket_t*"));
  306. if(!socket) { REprintf("bad socket object.\n");return R_NilValue; }
  307. zmq::message_t msg;
  308. try {
  309. status = socket->recv(&msg);
  310. } catch(std::exception& e) {
  311. REprintf("%s\n",e.what());
  312. }
  313. LOGICAL(ans)[0] = static_cast<int>(status) && (msg.size() == 0);
  314. UNPROTECT(1);
  315. return ans;
  316. }
  317. SEXP receiveSocket(SEXP socket_) {
  318. SEXP ans;
  319. bool status(false);
  320. zmq::message_t msg;
  321. zmq::socket_t* socket = reinterpret_cast<zmq::socket_t*>(checkExternalPointer(socket_,"zmq::socket_t*"));
  322. if(!socket) { REprintf("bad socket object.\n");return R_NilValue; }
  323. try {
  324. status = socket->recv(&msg);
  325. } catch(std::exception& e) {
  326. REprintf("%s\n",e.what());
  327. }
  328. if(status) {
  329. PROTECT(ans = allocVector(RAWSXP,msg.size()));
  330. memcpy(RAW(ans),msg.data(),msg.size());
  331. UNPROTECT(1);
  332. return ans;
  333. }
  334. return R_NilValue;
  335. }
  336. SEXP receiveString(SEXP socket_) {
  337. SEXP ans;
  338. bool status(false);
  339. zmq::message_t msg;
  340. zmq::socket_t* socket = reinterpret_cast<zmq::socket_t*>(checkExternalPointer(socket_,"zmq::socket_t*"));
  341. if(!socket) { REprintf("bad socket object.\n");return R_NilValue; }
  342. try {
  343. status = socket->recv(&msg);
  344. } catch(std::exception& e) {
  345. REprintf("%s\n",e.what());
  346. }
  347. if(status) {
  348. PROTECT(ans = allocVector(STRSXP,1));
  349. char* string_msg = new char[msg.size() + 1];
  350. if(string_msg == NULL) {
  351. UNPROTECT(1);
  352. return R_NilValue;
  353. }
  354. memcpy(string_msg,msg.data(),msg.size());
  355. string_msg[msg.size()] = 0;
  356. SET_STRING_ELT(ans, 0, mkChar(string_msg));
  357. UNPROTECT(1);
  358. return ans;
  359. }
  360. return R_NilValue;
  361. }
  362. SEXP receiveInt(SEXP socket_) {
  363. SEXP ans;
  364. bool status(false);
  365. zmq::message_t msg;
  366. try {
  367. zmq::socket_t* socket = reinterpret_cast<zmq::socket_t*>(checkExternalPointer(socket_,"zmq::socket_t*"));
  368. status = socket->recv(&msg);
  369. } catch(std::exception& e) {
  370. REprintf("%s\n",e.what());
  371. }
  372. if(status) {
  373. if(msg.size() != sizeof(int)) {
  374. REprintf("bad integer size on remote machine.\n");
  375. return R_NilValue;
  376. }
  377. PROTECT(ans = allocVector(INTSXP,1));
  378. memcpy(INTEGER(ans),msg.data(),msg.size());
  379. UNPROTECT(1);
  380. return ans;
  381. }
  382. return R_NilValue;
  383. }
  384. SEXP receiveDouble(SEXP socket_) {
  385. SEXP ans;
  386. bool status(false);
  387. zmq::message_t msg;
  388. try {
  389. zmq::socket_t* socket = reinterpret_cast<zmq::socket_t*>(checkExternalPointer(socket_,"zmq::socket_t*"));
  390. status = socket->recv(&msg);
  391. } catch(std::exception& e) {
  392. REprintf("%s\n",e.what());
  393. }
  394. if(status) {
  395. if(msg.size() != sizeof(double)) {
  396. REprintf("bad double size on remote machine.\n");
  397. return R_NilValue;
  398. }
  399. PROTECT(ans = allocVector(REALSXP,1));
  400. memcpy(REAL(ans),msg.data(),msg.size());
  401. UNPROTECT(1);
  402. return ans;
  403. }
  404. return R_NilValue;
  405. }
  406. SEXP set_hwm(SEXP socket_, SEXP option_value_) {
  407. zmq::socket_t* socket = reinterpret_cast<zmq::socket_t*>(checkExternalPointer(socket_,"zmq::socket_t*"));
  408. if(!socket) { REprintf("bad socket object.\n");return R_NilValue; }
  409. if(TYPEOF(option_value_)!=INTSXP) { REprintf("option value must be an int.\n");return R_NilValue; }
  410. SEXP ans; PROTECT(ans = allocVector(LGLSXP,1)); LOGICAL(ans)[0] = 1;
  411. uint64_t option_value(INTEGER(option_value_)[0]);
  412. try {
  413. socket->setsockopt(ZMQ_HWM, &option_value, sizeof(uint64_t));
  414. } catch(std::exception& e) {
  415. REprintf("%s\n",e.what());
  416. LOGICAL(ans)[0] = 0;
  417. }
  418. UNPROTECT(1);
  419. return ans;
  420. }
  421. SEXP set_swap(SEXP socket_, SEXP option_value_) {
  422. zmq::socket_t* socket = reinterpret_cast<zmq::socket_t*>(checkExternalPointer(socket_,"zmq::socket_t*"));
  423. if(!socket) { REprintf("bad socket object.\n");return R_NilValue; }
  424. if(TYPEOF(option_value_)!=INTSXP) { REprintf("option value must be an int.\n");return R_NilValue; }
  425. SEXP ans; PROTECT(ans = allocVector(LGLSXP,1)); LOGICAL(ans)[0] = 1;
  426. int64_t option_value(INTEGER(option_value_)[0]);
  427. try {
  428. socket->setsockopt(ZMQ_SWAP, &option_value, sizeof(int64_t));
  429. } catch(std::exception& e) {
  430. REprintf("%s\n",e.what());
  431. LOGICAL(ans)[0] = 0;
  432. }
  433. UNPROTECT(1);
  434. return ans;
  435. }
  436. SEXP set_affinity(SEXP socket_, SEXP option_value_) {
  437. zmq::socket_t* socket = reinterpret_cast<zmq::socket_t*>(checkExternalPointer(socket_,"zmq::socket_t*"));
  438. if(!socket) { REprintf("bad socket object.\n");return R_NilValue; }
  439. if(TYPEOF(option_value_)!=INTSXP) { REprintf("option value must be an int.\n");return R_NilValue; }
  440. SEXP ans; PROTECT(ans = allocVector(LGLSXP,1)); LOGICAL(ans)[0] = 1;
  441. uint64_t option_value(INTEGER(option_value_)[0]);
  442. try {
  443. socket->setsockopt(ZMQ_AFFINITY, &option_value, sizeof(uint64_t));
  444. } catch(std::exception& e) {
  445. REprintf("%s\n",e.what());
  446. LOGICAL(ans)[0] = 0;
  447. }
  448. UNPROTECT(1);
  449. return ans;
  450. }
  451. SEXP set_identity(SEXP socket_, SEXP option_value_) {
  452. zmq::socket_t* socket = reinterpret_cast<zmq::socket_t*>(checkExternalPointer(socket_,"zmq::socket_t*"));
  453. if(!socket) { REprintf("bad socket object.\n");return R_NilValue; }
  454. if(TYPEOF(option_value_)!=STRSXP) { REprintf("option value must be a string.\n");return R_NilValue; }
  455. SEXP ans; PROTECT(ans = allocVector(LGLSXP,1)); LOGICAL(ans)[0] = 1;
  456. const char* option_value = CHAR(STRING_ELT(option_value_,0));
  457. try {
  458. socket->setsockopt(ZMQ_IDENTITY, option_value,strlen(option_value));
  459. } catch(std::exception& e) {
  460. REprintf("%s\n",e.what());
  461. LOGICAL(ans)[0] = 0;
  462. }
  463. UNPROTECT(1);
  464. return ans;
  465. }
  466. SEXP subscribe(SEXP socket_, SEXP option_value_) {
  467. zmq::socket_t* socket = reinterpret_cast<zmq::socket_t*>(checkExternalPointer(socket_,"zmq::socket_t*"));
  468. if(!socket) { REprintf("bad socket object.\n");return R_NilValue; }
  469. if(TYPEOF(option_value_)!=STRSXP) { REprintf("option value must be a string.\n");return R_NilValue; }
  470. SEXP ans; PROTECT(ans = allocVector(LGLSXP,1)); LOGICAL(ans)[0] = 1;
  471. const char* option_value = CHAR(STRING_ELT(option_value_,0));
  472. try {
  473. socket->setsockopt(ZMQ_SUBSCRIBE, option_value,strlen(option_value));
  474. } catch(std::exception& e) {
  475. REprintf("%s\n",e.what());
  476. LOGICAL(ans)[0] = 0;
  477. }
  478. UNPROTECT(1);
  479. return ans;
  480. }
  481. SEXP unsubscribe(SEXP socket_, SEXP option_value_) {
  482. zmq::socket_t* socket = reinterpret_cast<zmq::socket_t*>(checkExternalPointer(socket_,"zmq::socket_t*"));
  483. if(!socket) { REprintf("bad socket object.\n");return R_NilValue; }
  484. if(TYPEOF(option_value_)!=STRSXP) { REprintf("option value must be a string.\n");return R_NilValue; }
  485. SEXP ans; PROTECT(ans = allocVector(LGLSXP,1)); LOGICAL(ans)[0] = 1;
  486. const char* option_value = CHAR(STRING_ELT(option_value_,0));
  487. try {
  488. socket->setsockopt(ZMQ_UNSUBSCRIBE, option_value,strlen(option_value));
  489. } catch(std::exception& e) {
  490. REprintf("%s\n",e.what());
  491. LOGICAL(ans)[0] = 0;
  492. }
  493. UNPROTECT(1);
  494. return ans;
  495. }
  496. SEXP set_rate(SEXP socket_, SEXP option_value_) {
  497. zmq::socket_t* socket = reinterpret_cast<zmq::socket_t*>(checkExternalPointer(socket_,"zmq::socket_t*"));
  498. if(!socket) { REprintf("bad socket object.\n");return R_NilValue; }
  499. if(TYPEOF(option_value_)!=INTSXP) { REprintf("option value must be an int.\n");return R_NilValue; }
  500. SEXP ans; PROTECT(ans = allocVector(LGLSXP,1)); LOGICAL(ans)[0] = 1;
  501. int64_t option_value(INTEGER(option_value_)[0]);
  502. try {
  503. socket->setsockopt(ZMQ_RATE, &option_value, sizeof(int64_t));
  504. } catch(std::exception& e) {
  505. REprintf("%s\n",e.what());
  506. LOGICAL(ans)[0] = 0;
  507. }
  508. UNPROTECT(1);
  509. return ans;
  510. }
  511. SEXP set_recovery_ivl(SEXP socket_, SEXP option_value_) {
  512. zmq::socket_t* socket = reinterpret_cast<zmq::socket_t*>(checkExternalPointer(socket_,"zmq::socket_t*"));
  513. if(!socket) { REprintf("bad socket object.\n");return R_NilValue; }
  514. if(TYPEOF(option_value_)!=INTSXP) { REprintf("option value must be an int.\n");return R_NilValue; }
  515. SEXP ans; PROTECT(ans = allocVector(LGLSXP,1)); LOGICAL(ans)[0] = 1;
  516. int64_t option_value(INTEGER(option_value_)[0]);
  517. try {
  518. socket->setsockopt(ZMQ_RECOVERY_IVL, &option_value, sizeof(int64_t));
  519. } catch(std::exception& e) {
  520. REprintf("%s\n",e.what());
  521. LOGICAL(ans)[0] = 0;
  522. }
  523. UNPROTECT(1);
  524. return ans;
  525. }
  526. SEXP set_recovery_ivl_msec(SEXP socket_, SEXP option_value_) {
  527. zmq::socket_t* socket = reinterpret_cast<zmq::socket_t*>(checkExternalPointer(socket_,"zmq::socket_t*"));
  528. if(!socket) { REprintf("bad socket object.\n");return R_NilValue; }
  529. if(TYPEOF(option_value_)!=INTSXP) { REprintf("option value must be an int.\n");return R_NilValue; }
  530. SEXP ans; PROTECT(ans = allocVector(LGLSXP,1)); LOGICAL(ans)[0] = 1;
  531. int64_t option_value(INTEGER(option_value_)[0]);
  532. try {
  533. socket->setsockopt(ZMQ_RECOVERY_IVL_MSEC, &option_value, sizeof(int64_t));
  534. } catch(std::exception& e) {
  535. REprintf("%s\n",e.what());
  536. LOGICAL(ans)[0] = 0;
  537. }
  538. UNPROTECT(1);
  539. return ans;
  540. }
  541. SEXP set_mcast_loop(SEXP socket_, SEXP option_value_) {
  542. zmq::socket_t* socket = reinterpret_cast<zmq::socket_t*>(checkExternalPointer(socket_,"zmq::socket_t*"));
  543. if(!socket) { REprintf("bad socket object.\n");return R_NilValue; }
  544. if(TYPEOF(option_value_)!=LGLSXP) { REprintf("option value must be a logical.\n");return R_NilValue; }
  545. SEXP ans; PROTECT(ans = allocVector(LGLSXP,1)); LOGICAL(ans)[0] = 1;
  546. int64_t option_value(LOGICAL(option_value_)[0]);
  547. try {
  548. socket->setsockopt(ZMQ_MCAST_LOOP, &option_value, sizeof(int64_t));
  549. } catch(std::exception& e) {
  550. REprintf("%s\n",e.what());
  551. LOGICAL(ans)[0] = 0;
  552. }
  553. UNPROTECT(1);
  554. return ans;
  555. }
  556. SEXP set_sndbuf(SEXP socket_, SEXP option_value_) {
  557. zmq::socket_t* socket = reinterpret_cast<zmq::socket_t*>(checkExternalPointer(socket_,"zmq::socket_t*"));
  558. if(!socket) { REprintf("bad socket object.\n");return R_NilValue; }
  559. if(TYPEOF(option_value_)!=INTSXP) { REprintf("option value must be an int.\n");return R_NilValue; }
  560. SEXP ans; PROTECT(ans = allocVector(LGLSXP,1)); LOGICAL(ans)[0] = 1;
  561. uint64_t option_value(INTEGER(option_value_)[0]);
  562. try {
  563. socket->setsockopt(ZMQ_SNDBUF, &option_value, sizeof(uint64_t));
  564. } catch(std::exception& e) {
  565. REprintf("%s\n",e.what());
  566. LOGICAL(ans)[0] = 0;
  567. }
  568. UNPROTECT(1);
  569. return ans;
  570. }
  571. SEXP set_rcvbuf(SEXP socket_, SEXP option_value_) {
  572. zmq::socket_t* socket = reinterpret_cast<zmq::socket_t*>(checkExternalPointer(socket_,"zmq::socket_t*"));
  573. if(!socket) { REprintf("bad socket object.\n");return R_NilValue; }
  574. if(TYPEOF(option_value_)!=INTSXP) { REprintf("option value must be an int.\n");return R_NilValue; }
  575. SEXP ans; PROTECT(ans = allocVector(LGLSXP,1)); LOGICAL(ans)[0] = 1;
  576. uint64_t option_value(INTEGER(option_value_)[0]);
  577. try {
  578. socket->setsockopt(ZMQ_RCVBUF, &option_value, sizeof(uint64_t));
  579. } catch(std::exception& e) {
  580. REprintf("%s\n",e.what());
  581. LOGICAL(ans)[0] = 0;
  582. }
  583. UNPROTECT(1);
  584. return ans;
  585. }
  586. SEXP set_linger(SEXP socket_, SEXP option_value_) {
  587. zmq::socket_t* socket = reinterpret_cast<zmq::socket_t*>(checkExternalPointer(socket_,"zmq::socket_t*"));
  588. if(!socket) { REprintf("bad socket object.\n");return R_NilValue; }
  589. if(TYPEOF(option_value_)!=INTSXP) { REprintf("option value must be an int.\n");return R_NilValue; }
  590. SEXP ans; PROTECT(ans = allocVector(LGLSXP,1)); LOGICAL(ans)[0] = 1;
  591. int option_value(INTEGER(option_value_)[0]);
  592. try {
  593. socket->setsockopt(ZMQ_LINGER, &option_value, sizeof(int));
  594. } catch(std::exception& e) {
  595. REprintf("%s\n",e.what());
  596. LOGICAL(ans)[0] = 0;
  597. }
  598. UNPROTECT(1);
  599. return ans;
  600. }
  601. SEXP set_reconnect_ivl(SEXP socket_, SEXP option_value_) {
  602. zmq::socket_t* socket = reinterpret_cast<zmq::socket_t*>(checkExternalPointer(socket_,"zmq::socket_t*"));
  603. if(!socket) { REprintf("bad socket object.\n");return R_NilValue; }
  604. if(TYPEOF(option_value_)!=INTSXP) { REprintf("option value must be an int.\n");return R_NilValue; }
  605. SEXP ans; PROTECT(ans = allocVector(LGLSXP,1)); LOGICAL(ans)[0] = 1;
  606. int option_value(INTEGER(option_value_)[0]);
  607. try {
  608. socket->setsockopt(ZMQ_RECONNECT_IVL, &option_value, sizeof(int));
  609. } catch(std::exception& e) {
  610. REprintf("%s\n",e.what());
  611. LOGICAL(ans)[0] = 0;
  612. }
  613. UNPROTECT(1);
  614. return ans;
  615. }
  616. SEXP set_zmq_backlog(SEXP socket_, SEXP option_value_) {
  617. zmq::socket_t* socket = reinterpret_cast<zmq::socket_t*>(checkExternalPointer(socket_,"zmq::socket_t*"));
  618. if(!socket) { REprintf("bad socket object.\n");return R_NilValue; }
  619. if(TYPEOF(option_value_)!=INTSXP) { REprintf("option value must be an int.\n");return R_NilValue; }
  620. SEXP ans; PROTECT(ans = allocVector(LGLSXP,1)); LOGICAL(ans)[0] = 1;
  621. int option_value(INTEGER(option_value_)[0]);
  622. try {
  623. socket->setsockopt(ZMQ_BACKLOG, &option_value, sizeof(int));
  624. } catch(std::exception& e) {
  625. REprintf("%s\n",e.what());
  626. LOGICAL(ans)[0] = 0;
  627. }
  628. UNPROTECT(1);
  629. return ans;
  630. }
  631. SEXP set_reconnect_ivl_max(SEXP socket_, SEXP option_value_) {
  632. zmq::socket_t* socket = reinterpret_cast<zmq::socket_t*>(checkExternalPointer(socket_,"zmq::socket_t*"));
  633. if(!socket) { REprintf("bad socket object.\n");return R_NilValue; }
  634. if(TYPEOF(option_value_)!=INTSXP) { REprintf("option value must be an int.\n");return R_NilValue; }
  635. SEXP ans; PROTECT(ans = allocVector(LGLSXP,1)); LOGICAL(ans)[0] = 1;
  636. int option_value(INTEGER(option_value_)[0]);
  637. try {
  638. socket->setsockopt(ZMQ_RECONNECT_IVL_MAX, &option_value, sizeof(int));
  639. } catch(std::exception& e) {
  640. REprintf("%s\n",e.what());
  641. LOGICAL(ans)[0] = 0;
  642. }
  643. UNPROTECT(1);
  644. return ans;
  645. }
  646. SEXP get_rcvmore(SEXP socket_) {
  647. zmq::socket_t* socket = reinterpret_cast<zmq::socket_t*>(checkExternalPointer(socket_,"zmq::socket_t*"));
  648. if(!socket) { REprintf("bad socket object.\n");return R_NilValue; }
  649. int64_t option_value;
  650. size_t option_value_len = sizeof(option_value);
  651. try {
  652. socket->getsockopt(ZMQ_RCVMORE, &option_value, &option_value_len);
  653. } catch(std::exception& e) {
  654. REprintf("%s\n",e.what());
  655. return R_NilValue;
  656. }
  657. SEXP ans; PROTECT(ans = allocVector(LGLSXP,1));
  658. LOGICAL(ans)[0] = static_cast<int>(option_value);
  659. UNPROTECT(1);
  660. return ans;
  661. }
  662. // #define ZMQ_RCVMORE 13
  663. // #define ZMQ_FD 14
  664. // #define ZMQ_EVENTS 15
  665. // #define ZMQ_TYPE 16
  666. SEXP rzmq_serialize(SEXP data, SEXP rho) {
  667. static SEXP R_serialize_fun = findVar(install("serialize"), R_GlobalEnv);
  668. SEXP R_fcall, ans;
  669. if(!isEnvironment(rho)) error("'rho' should be an environment");
  670. PROTECT(R_fcall = lang3(R_serialize_fun, data, R_NilValue));
  671. PROTECT(ans = eval(R_fcall, rho));
  672. UNPROTECT(2);
  673. return ans;
  674. }
  675. SEXP rzmq_unserialize(SEXP data, SEXP rho) {
  676. static SEXP R_unserialize_fun = findVar(install("unserialize"), R_GlobalEnv);
  677. SEXP R_fcall, ans;
  678. if(!isEnvironment(rho)) error("'rho' should be an environment");
  679. PROTECT(R_fcall = lang2(R_unserialize_fun, data));
  680. PROTECT(ans = eval(R_fcall, rho));
  681. UNPROTECT(2);
  682. return ans;
  683. }