sq_zmq3.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728
  1. #include "squirrel.h"
  2. //#include "sqstdblobimpl.h"
  3. #include "zmq.h"
  4. #include <inttypes.h>
  5. #include <string.h>
  6. #include <stdio.h>
  7. SQ_OPT_STRING_STRLEN();
  8. static SQRESULT zmq_throwerror(HSQUIRRELVM v){
  9. return sq_throwerror(v, zmq_strerror(zmq_errno()));
  10. }
  11. static SQRESULT table_set_int(HSQUIRRELVM v, const SQChar *key, SQInteger value){
  12. sq_pushliteral(v, key);
  13. sq_pushinteger(v, value);
  14. return sq_rawset(v, -3);
  15. }
  16. static const SQChar sq_zmq3_ctx_TAG[] = _SC("sq_zmq3_ctx_tag");
  17. #define GET_zmq3_ctx_INSTANCE_VAR_AT(idx, Var) \
  18. SQ_GET_INSTANCE_VAR(v, idx, SQUserPointer, Var, sq_zmq3_ctx_TAG);\
  19. if(!Var) return sq_throwerror(v, _SC("zmq_ctx already destroyed"));
  20. #define GET_zmq3_ctx_INSTANCE() GET_zmq3_ctx_INSTANCE_VAR_AT(1, self)
  21. static const SQChar sq_zmq3_socket_TAG[] = _SC("sq_zmq3_socket_tag");
  22. #define GET_zmq3_socket_INSTANCE_VAR_AT(idx, Var) \
  23. SQ_GET_INSTANCE_VAR(v, idx, zmq_msg_t, Var, sq_zmq3_socket_TAG);\
  24. if(!Var) return sq_throwerror(v, _SC("socket already closed"));
  25. #define GET_zmq3_socket_INSTANCE() GET_zmq3_socket_INSTANCE_VAR_AT(1, self)
  26. static const SQChar sq_zmq3_msg_TAG[] = _SC("sq_zmq3_msg_tag");
  27. #define GET_zmq3_msg_INSTANCE_VAR_AT(idx, Var) \
  28. SQ_GET_INSTANCE_VAR(v, idx, zmq_msg_t, Var, sq_zmq3_msg_TAG);\
  29. if(!Var) return sq_throwerror(v, _SC("message already closed"));
  30. #define GET_zmq3_msg_INSTANCE() GET_zmq3_msg_INSTANCE_VAR_AT(1, self)
  31. static SQRESULT sq_zmq3_msg_releasehook(SQUserPointer p, SQInteger size)
  32. {
  33. zmq_msg_t *self = ((zmq_msg_t *)p);
  34. if(self) {
  35. int rc = zmq_msg_close(self);
  36. if(rc != 0) return rc;
  37. sq_free(self, sizeof(zmq_msg_t));
  38. }
  39. return 0;
  40. }
  41. static SQRESULT sq_zmq3_msg_constructor(HSQUIRRELVM v)
  42. {
  43. SQ_FUNC_VARS(v);
  44. zmq_msg_t *msg = (zmq_msg_t*)sq_malloc(sizeof(zmq_msg_t));
  45. int rc;
  46. switch(_top_){
  47. case 1:
  48. rc = zmq_msg_init(msg);
  49. break;
  50. case 2:{
  51. SQ_GET_INTEGER(v, 2, size);
  52. rc = zmq_msg_init_size(msg, size);
  53. }
  54. break;
  55. default:
  56. return sq_throwerror(v, _SC("zmq_msg accepts between 0 and 1 parameters"));
  57. }
  58. if(rc) return zmq_throwerror(v);
  59. sq_setinstanceup(v, 1, msg);
  60. sq_setreleasehook(v,1, sq_zmq3_msg_releasehook);
  61. return 1;
  62. }
  63. static SQRESULT sq_zmq3_msg_send(HSQUIRRELVM v)
  64. {
  65. SQ_FUNC_VARS_NO_TOP(v);
  66. GET_zmq3_msg_INSTANCE();
  67. GET_zmq3_socket_INSTANCE_VAR_AT(2, socket);
  68. SQ_GET_INTEGER(v, 3, flags);
  69. sq_pushinteger(v, zmq_msg_send(self, socket, flags));
  70. return 1;
  71. }
  72. static SQRESULT sq_zmq3_msg_recv(HSQUIRRELVM v)
  73. {
  74. SQ_FUNC_VARS_NO_TOP(v);
  75. GET_zmq3_msg_INSTANCE();
  76. GET_zmq3_socket_INSTANCE_VAR_AT(2, socket);
  77. SQ_GET_INTEGER(v, 3, flags);
  78. sq_pushinteger(v, zmq_msg_recv(self, socket, flags));
  79. return 1;
  80. }
  81. static SQRESULT sq_zmq3_msg_close(HSQUIRRELVM v)
  82. {
  83. SQ_FUNC_VARS_NO_TOP(v);
  84. GET_zmq3_msg_INSTANCE();
  85. int rc = sq_zmq3_msg_releasehook(self, 0);
  86. if(rc == 0) sq_setinstanceup(v, 1, 0); //invalidate the message
  87. sq_pushinteger(v, rc);
  88. return 1;
  89. }
  90. static SQRESULT sq_zmq3_msg_copy(HSQUIRRELVM v)
  91. {
  92. SQ_FUNC_VARS_NO_TOP(v);
  93. GET_zmq3_msg_INSTANCE();
  94. GET_zmq3_msg_INSTANCE_VAR_AT(2, src);
  95. sq_pushinteger(v, zmq_msg_copy(self, src));
  96. return 1;
  97. }
  98. static SQRESULT sq_zmq3_msg_data(HSQUIRRELVM v)
  99. {
  100. SQ_FUNC_VARS(v);
  101. GET_zmq3_msg_INSTANCE();
  102. if(_top_ > 1){
  103. SQ_GET_STRING(v, 2, data);
  104. if(data_size > zmq_msg_size(self)) return sq_throwerror(v, _SC("data size bigger than available space"));
  105. memcpy(zmq_msg_data(self), data, data_size);
  106. return 0;
  107. } else {
  108. sq_pushstring(v, (const SQChar*)zmq_msg_data(self), zmq_msg_size(self));
  109. }
  110. return 1;
  111. }
  112. static SQRESULT sq_zmq3_msg_size(HSQUIRRELVM v)
  113. {
  114. SQ_FUNC_VARS_NO_TOP(v);
  115. GET_zmq3_msg_INSTANCE();
  116. sq_pushinteger(v, zmq_msg_size(self));
  117. return 1;
  118. }
  119. static SQRESULT sq_zmq3_msg_more(HSQUIRRELVM v)
  120. {
  121. SQ_FUNC_VARS_NO_TOP(v);
  122. GET_zmq3_msg_INSTANCE();
  123. sq_pushinteger(v, zmq_msg_more(self));
  124. return 1;
  125. }
  126. static SQRESULT sq_zmq3_msg_set(HSQUIRRELVM v)
  127. {
  128. SQ_FUNC_VARS_NO_TOP(v);
  129. GET_zmq3_msg_INSTANCE();
  130. SQ_GET_INTEGER(v, 2, option);
  131. SQ_GET_INTEGER(v, 3, optval);
  132. sq_pushinteger(v, zmq_msg_set(self, option, optval));
  133. return 1;
  134. }
  135. static SQRESULT sq_zmq3_msg_get(HSQUIRRELVM v)
  136. {
  137. SQ_FUNC_VARS_NO_TOP(v);
  138. GET_zmq3_msg_INSTANCE();
  139. SQ_GET_INTEGER(v, 2, option);
  140. sq_pushinteger(v, zmq_msg_get(self, option));
  141. return 1;
  142. }
  143. #define _DECL_FUNC(name,nparams,tycheck) {_SC(#name), sq_zmq3_msg_##name,nparams,tycheck}
  144. static SQRegFunction sq_zmq3_msg_methods[] =
  145. {
  146. _DECL_FUNC(constructor, -1, _SC("x i|s i")),
  147. _DECL_FUNC(send, 3, _SC("xxi")),
  148. _DECL_FUNC(recv, 3, _SC("xxi")),
  149. _DECL_FUNC(close, 1, _SC("x")),
  150. _DECL_FUNC(copy, 2, _SC("xx")),
  151. _DECL_FUNC(data, -1, _SC("xs")),
  152. _DECL_FUNC(size, 1, _SC("x")),
  153. _DECL_FUNC(more, 1, _SC("x")),
  154. _DECL_FUNC(set, 3, _SC("xii")),
  155. _DECL_FUNC(get, 2, _SC("xi")),
  156. {0,0}
  157. };
  158. #undef _DECL_FUNC
  159. //socket
  160. static SQRESULT sq_zmq3_socket_releasehook(SQUserPointer p, SQInteger size)
  161. {
  162. void *self = ((void *)p);
  163. if(self) {
  164. return zmq_close(self);
  165. }
  166. return 0;
  167. }
  168. static SQRESULT sq_zmq3_socket_constructor(HSQUIRRELVM v)
  169. {
  170. SQ_FUNC_VARS_NO_TOP(v);
  171. GET_zmq3_ctx_INSTANCE_VAR_AT(2, ctx);
  172. SQ_GET_INTEGER(v, 3, type);
  173. switch(type){
  174. case ZMQ_PAIR :
  175. case ZMQ_PUB :
  176. case ZMQ_SUB :
  177. case ZMQ_REQ :
  178. case ZMQ_REP :
  179. case ZMQ_DEALER :
  180. case ZMQ_ROUTER :
  181. case ZMQ_PULL :
  182. case ZMQ_PUSH :
  183. case ZMQ_XPUB :
  184. case ZMQ_XSUB :
  185. break;
  186. default:
  187. return sq_throwerror(v, _SC("invalid socket type %d"), type);
  188. }
  189. void *socket = zmq_socket(ctx, type);
  190. if(!socket) return zmq_throwerror(v);
  191. sq_setinstanceup(v, 1, socket);
  192. sq_setreleasehook(v,1, sq_zmq3_socket_releasehook);
  193. return 1;
  194. }
  195. static SQRESULT sq_zmq3_socket_close(HSQUIRRELVM v)
  196. {
  197. SQ_FUNC_VARS_NO_TOP(v);
  198. GET_zmq3_socket_INSTANCE();
  199. int rc = sq_zmq3_socket_releasehook(self, 0);
  200. if(rc == 0) sq_setinstanceup(v, 1, 0);
  201. sq_pushinteger(v, rc);
  202. return 1;
  203. }
  204. static int check_socket_option(int option){
  205. switch(option){
  206. case ZMQ_AFFINITY :
  207. case ZMQ_IDENTITY :
  208. case ZMQ_SUBSCRIBE :
  209. case ZMQ_UNSUBSCRIBE :
  210. case ZMQ_RATE :
  211. case ZMQ_RECOVERY_IVL :
  212. case ZMQ_SNDBUF :
  213. case ZMQ_RCVBUF :
  214. case ZMQ_RCVMORE :
  215. case ZMQ_FD :
  216. case ZMQ_EVENTS :
  217. case ZMQ_TYPE :
  218. case ZMQ_LINGER :
  219. case ZMQ_RECONNECT_IVL :
  220. case ZMQ_BACKLOG :
  221. case ZMQ_RECONNECT_IVL_MAX :
  222. case ZMQ_MAXMSGSIZE :
  223. case ZMQ_SNDHWM :
  224. case ZMQ_RCVHWM :
  225. case ZMQ_MULTICAST_HOPS :
  226. case ZMQ_RCVTIMEO :
  227. case ZMQ_SNDTIMEO :
  228. case ZMQ_IPV4ONLY :
  229. case ZMQ_LAST_ENDPOINT :
  230. case ZMQ_ROUTER_MANDATORY :
  231. case ZMQ_TCP_KEEPALIVE :
  232. case ZMQ_TCP_KEEPALIVE_CNT :
  233. case ZMQ_TCP_KEEPALIVE_IDLE :
  234. case ZMQ_TCP_KEEPALIVE_INTVL :
  235. case ZMQ_TCP_ACCEPT_FILTER :
  236. case ZMQ_DELAY_ATTACH_ON_CONNECT :
  237. case ZMQ_XPUB_VERBOSE :
  238. break;
  239. default:
  240. return -1;
  241. }
  242. return 0;
  243. }
  244. static SQRESULT sq_zmq3_socket_getsetsockopt(HSQUIRRELVM v, bool isSet)
  245. {
  246. SQ_FUNC_VARS_NO_TOP(v);
  247. GET_zmq3_socket_INSTANCE();
  248. SQ_GET_INTEGER(v, 2, option);
  249. if(check_socket_option(option)) return sq_throwerror(v, _SC("invalid socket option %d"), option);
  250. SQInteger rc;
  251. switch (option) {
  252. case ZMQ_AFFINITY:
  253. case ZMQ_MAXMSGSIZE:
  254. {
  255. SQ_GET_INTEGER(v, 3, ioptval);
  256. int64_t optval = (int64_t) ioptval;
  257. size_t optvallen = sizeof(int64_t);
  258. if(isSet) rc = zmq_setsockopt(self, option, (void *) &optval, optvallen);
  259. else
  260. {
  261. rc = zmq_getsockopt(self, option, (void *) &optval, &optvallen);
  262. if(rc == 0) sq_pushinteger(v, optval);
  263. }
  264. }
  265. break;
  266. case ZMQ_TYPE:
  267. case ZMQ_RCVMORE:
  268. case ZMQ_EVENTS:
  269. case ZMQ_SNDHWM:
  270. case ZMQ_RCVHWM:
  271. case ZMQ_RATE:
  272. case ZMQ_RECOVERY_IVL:
  273. case ZMQ_SNDBUF:
  274. case ZMQ_RCVBUF:
  275. case ZMQ_LINGER:
  276. case ZMQ_RECONNECT_IVL:
  277. case ZMQ_RECONNECT_IVL_MAX:
  278. case ZMQ_BACKLOG:
  279. case ZMQ_MULTICAST_HOPS:
  280. case ZMQ_RCVTIMEO:
  281. case ZMQ_SNDTIMEO:
  282. case ZMQ_IPV4ONLY:
  283. case ZMQ_DELAY_ATTACH_ON_CONNECT:
  284. case ZMQ_TCP_KEEPALIVE:
  285. case ZMQ_TCP_KEEPALIVE_CNT:
  286. case ZMQ_TCP_KEEPALIVE_IDLE:
  287. case ZMQ_TCP_KEEPALIVE_INTVL:
  288. {
  289. if(isSet){
  290. SQ_GET_INTEGER(v, 3, ioptval);
  291. rc = zmq_setsockopt(self, option, (void *) &ioptval, sizeof(ioptval));
  292. }
  293. else
  294. {
  295. int ioptval;
  296. rc = zmq_setsockopt(self, option, (void *) &ioptval, sizeof(ioptval));
  297. if(rc == 0) sq_pushinteger(v, ioptval);
  298. }
  299. }
  300. break;
  301. case ZMQ_IDENTITY:
  302. case ZMQ_TCP_ACCEPT_FILTER:
  303. case ZMQ_SUBSCRIBE:
  304. case ZMQ_UNSUBSCRIBE:
  305. {
  306. SQ_GET_STRING(v, 3, optval);
  307. if(isSet) rc = zmq_setsockopt(self, option, (void *) optval, optval_size);
  308. else
  309. {
  310. char buf[256];
  311. size_t optvallen = sizeof(buf);
  312. memset(buf, 0, optvallen);
  313. rc = zmq_getsockopt(self, option, (void *)buf, &optvallen);
  314. buf[sizeof(buf)-1] = '\0';
  315. if (rc == 0) {
  316. sq_pushstring(v, buf, -1);
  317. return 1;
  318. }
  319. }
  320. }
  321. break;
  322. //case case ZMQ_EVENTS:
  323. //case case ZMQ_FD:
  324. //case case ZMQ_LAST_ENDPOINT:
  325. default:
  326. rc = -1;
  327. errno = EINVAL;
  328. }
  329. if (rc != 0) return sq_throwerror(v, zmq_strerror(rc));
  330. return 0;
  331. }
  332. static SQRESULT sq_zmq3_socket_setsockopt(HSQUIRRELVM v)
  333. {
  334. return sq_zmq3_socket_getsetsockopt(v, true);
  335. }
  336. static SQRESULT sq_zmq3_socket_getsockopt(HSQUIRRELVM v)
  337. {
  338. return sq_zmq3_socket_getsetsockopt(v, false);
  339. }
  340. static SQRESULT sq_zmq3_socket_bind(HSQUIRRELVM v)
  341. {
  342. SQ_FUNC_VARS_NO_TOP(v);
  343. GET_zmq3_socket_INSTANCE();
  344. SQ_GET_STRING(v, 2, addr);
  345. sq_pushinteger(v, zmq_bind(self, addr));
  346. return 1;
  347. }
  348. static SQRESULT sq_zmq3_socket_unbind(HSQUIRRELVM v)
  349. {
  350. SQ_FUNC_VARS_NO_TOP(v);
  351. GET_zmq3_socket_INSTANCE();
  352. SQ_GET_STRING(v, 2, addr);
  353. sq_pushinteger(v, zmq_unbind(self, addr));
  354. return 1;
  355. }
  356. static SQRESULT sq_zmq3_socket_connect(HSQUIRRELVM v)
  357. {
  358. SQ_FUNC_VARS_NO_TOP(v);
  359. GET_zmq3_socket_INSTANCE();
  360. SQ_GET_STRING(v, 2, addr);
  361. sq_pushinteger(v, zmq_connect(self, addr));
  362. return 1;
  363. }
  364. static SQRESULT sq_zmq3_socket_disconnect(HSQUIRRELVM v)
  365. {
  366. SQ_FUNC_VARS_NO_TOP(v);
  367. GET_zmq3_socket_INSTANCE();
  368. SQ_GET_STRING(v, 2, addr);
  369. sq_pushinteger(v, zmq_disconnect(self, addr));
  370. return 1;
  371. }
  372. static SQRESULT sq_zmq3_socket_send(HSQUIRRELVM v)
  373. {
  374. SQ_FUNC_VARS(v);
  375. GET_zmq3_socket_INSTANCE();
  376. SQ_GET_STRING(v, 2, data);
  377. /*
  378. SQ_OPT_INTEGER(v, 3, data_len, data_size);
  379. SQ_OPT_INTEGER(v, 4, flags, 0);
  380. sq_pushinteger(v, zmq_send(self, data, data_len ? data_len : data_size, flags));
  381. */
  382. SQ_OPT_INTEGER(v, 3, flags, 0);
  383. zmq_msg_t msg;
  384. if(zmq_msg_init_size(&msg, data_size)) return zmq_throwerror(v);
  385. memcpy(zmq_msg_data(&msg), data, data_size);
  386. int rc = zmq_sendmsg(self, &msg, flags);
  387. if(zmq_msg_close(&msg)) return zmq_throwerror(v);
  388. sq_pushinteger(v, rc);
  389. return 1;
  390. }
  391. static SQRESULT sq_zmq3_socket_sendmsg(HSQUIRRELVM v)
  392. {
  393. SQ_FUNC_VARS_NO_TOP(v);
  394. GET_zmq3_socket_INSTANCE();
  395. GET_zmq3_msg_INSTANCE_VAR_AT(2, msg)
  396. SQ_GET_INTEGER(v, 3, flags);
  397. sq_pushinteger(v, zmq_sendmsg(self, msg, flags));
  398. return 1;
  399. }
  400. static SQRESULT sq_zmq3_socket_recv(HSQUIRRELVM v)
  401. {
  402. SQ_FUNC_VARS(v);
  403. GET_zmq3_socket_INSTANCE();
  404. /*
  405. SQ_GET_INSTANCE_VAR(v, 2, SQBlob, blob, SQBlob::SQBlob_TAG);
  406. SQ_OPT_INTEGER(v, 3, size);
  407. SQ_GET_INTEGER(v, 4, flags);
  408. if(!blob->SetLen(size)) sq_throwerror(v, _SC("could not set blob size to %d"), size);
  409. SQInteger nbytes = zmq_recv(self, blob->GetBuf(), size, flags);
  410. blob->SetLen(nbytes);
  411. sq_pushinteger(v, nbytes);
  412. */
  413. SQ_OPT_INTEGER(v, 2, flags, 0);
  414. zmq_msg_t msg;
  415. if(zmq_msg_init(&msg)) return zmq_throwerror(v);
  416. int nbytes = zmq_recvmsg(self, &msg, flags);
  417. if(nbytes < 0) {
  418. // Best we can do in this case is try to close and hope for the best.
  419. zmq_msg_close(&msg);
  420. return zmq_throwerror(v);
  421. }
  422. sq_pushstring(v, (const SQChar*)zmq_msg_data(&msg), zmq_msg_size(&msg));
  423. if(zmq_msg_close(&msg)) {
  424. // Above string will be poped from the stack by the normalising code
  425. // upon sucessful return.
  426. return zmq_throwerror(v);
  427. }
  428. return 1;
  429. }
  430. static SQRESULT sq_zmq3_socket_recvmsg(HSQUIRRELVM v)
  431. {
  432. SQ_FUNC_VARS_NO_TOP(v);
  433. GET_zmq3_socket_INSTANCE();
  434. GET_zmq3_msg_INSTANCE_VAR_AT(2, msg)
  435. SQ_GET_INTEGER(v, 3, flags);
  436. sq_pushinteger(v, zmq_recvmsg(self, msg, flags));
  437. return 1;
  438. }
  439. #define _DECL_FUNC(name,nparams,tycheck) {_SC(#name), sq_zmq3_socket_##name,nparams,tycheck}
  440. static SQRegFunction sq_zmq3_socket_methods[] =
  441. {
  442. _DECL_FUNC(constructor, 3, _SC("xxi")),
  443. _DECL_FUNC(setsockopt, 3, _SC("xi s|i")),
  444. _DECL_FUNC(getsockopt, 2, _SC("xi")),
  445. _DECL_FUNC(close, 1, _SC("x")),
  446. _DECL_FUNC(bind, 2, _SC("xs")),
  447. _DECL_FUNC(unbind, 2, _SC("xs")),
  448. _DECL_FUNC(connect, 2, _SC("xs")),
  449. _DECL_FUNC(disconnect, 2, _SC("xs")),
  450. _DECL_FUNC(send, -2, _SC("xsi")),
  451. _DECL_FUNC(sendmsg, 3, _SC("xxi")),
  452. _DECL_FUNC(recv, -1, _SC("xi")),
  453. _DECL_FUNC(recvmsg, 3, _SC("xxi")),
  454. {0,0}
  455. };
  456. #undef _DECL_FUNC
  457. //zmq3 context
  458. static SQRESULT sq_zmq3_ctx_releasehook(SQUserPointer p, SQInteger size)
  459. {
  460. void *self = ((void *)p);
  461. if(self) {
  462. return zmq_ctx_destroy(self);
  463. }
  464. return 0;
  465. }
  466. static SQRESULT sq_zmq3_ctx_constructor(HSQUIRRELVM v)
  467. {
  468. void *self = zmq_ctx_new();
  469. sq_setinstanceup(v, 1, self);
  470. sq_setreleasehook(v,1, sq_zmq3_ctx_releasehook);
  471. return 1;
  472. }
  473. static SQRESULT sq_zmq3_ctx_version(HSQUIRRELVM v)
  474. {
  475. int major, minor, patch;
  476. zmq_version (&major, &minor, &patch);
  477. sq_newtable(v);
  478. table_set_int(v, _SC("major"), major);
  479. table_set_int(v, _SC("minor"), minor);
  480. table_set_int(v, _SC("patch"), patch);
  481. return 1;
  482. }
  483. static SQRESULT sq_zmq3_ctx_errno(HSQUIRRELVM v)
  484. {
  485. sq_pushinteger(v, zmq_errno());
  486. return 1;
  487. }
  488. static SQRESULT sq_zmq3_ctx_strerror(HSQUIRRELVM v)
  489. {
  490. SQ_FUNC_VARS_NO_TOP(v);
  491. GET_zmq3_ctx_INSTANCE();
  492. SQ_GET_INTEGER(v, 2, errnum);
  493. sq_pushstring(v, zmq_strerror(errnum), -1);
  494. return 1;
  495. }
  496. static int check_ctx_options(int option){
  497. switch(option){
  498. case ZMQ_IO_THREADS:
  499. case ZMQ_MAX_SOCKETS:
  500. return 0;
  501. };
  502. return -1;
  503. }
  504. static SQRESULT sq_zmq3_ctx_getset(HSQUIRRELVM v, bool isSet)
  505. {
  506. SQ_FUNC_VARS_NO_TOP(v);
  507. GET_zmq3_ctx_INSTANCE();
  508. SQ_GET_INTEGER(v, 2, option);
  509. SQ_GET_INTEGER(v, 3, optval);
  510. if(check_ctx_options(option)) return sq_throwerror(v, _SC("invalid context option \"%d\""), option);
  511. if(isSet) sq_pushinteger(v, zmq_ctx_set(self, option, optval));
  512. else sq_pushinteger(v, zmq_ctx_get(self, option));
  513. return 1;
  514. }
  515. static SQRESULT sq_zmq3_ctx_set(HSQUIRRELVM v)
  516. {
  517. return sq_zmq3_ctx_getset(v, true);
  518. }
  519. static SQRESULT sq_zmq3_ctx_get(HSQUIRRELVM v)
  520. {
  521. return sq_zmq3_ctx_getset(v, false);
  522. }
  523. static SQRESULT sq_zmq3_ctx_socket(HSQUIRRELVM v)
  524. {
  525. SQ_FUNC_VARS_NO_TOP(v);
  526. GET_zmq3_ctx_INSTANCE();
  527. SQ_GET_INTEGER(v, 2, type);
  528. sq_pushroottable(v);
  529. if(sq_getbyname(v, -1, _SC("zmq_socket"), -1) == SQ_OK){
  530. sq_pushroottable(v); //this
  531. sq_push(v, 1); //zmq_ctx
  532. sq_push(v, 2); //socket type
  533. if(sq_call(v, 3, SQTrue, SQFalse) == SQ_OK) return 1;
  534. }
  535. return SQ_ERROR;
  536. }
  537. static SQRESULT sq_zmq3_ctx_destroy(HSQUIRRELVM v)
  538. {
  539. SQ_FUNC_VARS_NO_TOP(v);
  540. GET_zmq3_ctx_INSTANCE();
  541. int rc = sq_zmq3_ctx_releasehook(self, 0);
  542. if(rc == 0) sq_setinstanceup(v, 1, 0);
  543. sq_pushinteger(v, rc);
  544. return 1;
  545. }
  546. #define _DECL_FUNC(name,nparams,tycheck) {_SC(#name), sq_zmq3_ctx_##name,nparams,tycheck}
  547. static SQRegFunction sq_zmq3_ctx_methods[] =
  548. {
  549. _DECL_FUNC(constructor, 1, _SC("x")),
  550. _DECL_FUNC(version, 1, _SC("x")),
  551. _DECL_FUNC(errno, 1, _SC("x")),
  552. _DECL_FUNC(strerror, 2, _SC("xi")),
  553. _DECL_FUNC(set, 3, _SC("xii")),
  554. _DECL_FUNC(get, 2, _SC("xi")),
  555. _DECL_FUNC(socket, 2, _SC("xi")),
  556. _DECL_FUNC(destroy, 1, _SC("x")),
  557. {0,0}
  558. };
  559. #undef _DECL_FUNC
  560. #define INT_CONST(v,num) sq_pushstring(v,_SC(#num),-1);sq_pushinteger(v,ZMQ_##num);sq_newslot(v,-3,SQTrue);
  561. #ifdef __cplusplus
  562. extern "C" {
  563. #endif
  564. SQRESULT sqstd_register_sq_zmq3(HSQUIRRELVM v)
  565. {
  566. sq_pushliteral(v,_SC("zmq_ctx"));
  567. sq_newclass(v,SQFalse);
  568. sq_settypetag(v,-1,(void*)sq_zmq3_ctx_TAG);
  569. sq_insert_reg_funcs(v, sq_zmq3_ctx_methods);
  570. INT_CONST(v,IO_THREADS);
  571. INT_CONST(v,MAX_SOCKETS);
  572. INT_CONST(v,IO_THREADS_DFLT);
  573. INT_CONST(v,MAX_SOCKETS_DFLT);
  574. sq_newslot(v,-3,SQTrue);
  575. sq_pushliteral(v,_SC("zmq_socket"));
  576. sq_newclass(v,SQFalse);
  577. sq_settypetag(v,-1,(void*)sq_zmq3_socket_TAG);
  578. sq_insert_reg_funcs(v, sq_zmq3_socket_methods);
  579. INT_CONST(v,PAIR);
  580. INT_CONST(v,PUB);
  581. INT_CONST(v,SUB);
  582. INT_CONST(v,REQ);
  583. INT_CONST(v,REP);
  584. INT_CONST(v,DEALER);
  585. INT_CONST(v,ROUTER);
  586. INT_CONST(v,PULL);
  587. INT_CONST(v,PUSH);
  588. INT_CONST(v,XPUB);
  589. INT_CONST(v,XSUB);
  590. INT_CONST(v,AFFINITY );
  591. INT_CONST(v,IDENTITY );
  592. INT_CONST(v,SUBSCRIBE );
  593. INT_CONST(v,UNSUBSCRIBE );
  594. INT_CONST(v,RATE );
  595. INT_CONST(v,RECOVERY_IVL );
  596. INT_CONST(v,SNDBUF );
  597. INT_CONST(v,RCVBUF );
  598. INT_CONST(v,RCVMORE );
  599. INT_CONST(v,FD );
  600. INT_CONST(v,EVENTS );
  601. INT_CONST(v,TYPE );
  602. INT_CONST(v,LINGER );
  603. INT_CONST(v,RECONNECT_IVL );
  604. INT_CONST(v,BACKLOG );
  605. INT_CONST(v,RECONNECT_IVL_MAX );
  606. INT_CONST(v,MAXMSGSIZE );
  607. INT_CONST(v,SNDHWM );
  608. INT_CONST(v,RCVHWM );
  609. INT_CONST(v,MULTICAST_HOPS );
  610. INT_CONST(v,RCVTIMEO );
  611. INT_CONST(v,SNDTIMEO );
  612. INT_CONST(v,IPV4ONLY );
  613. INT_CONST(v,LAST_ENDPOINT );
  614. INT_CONST(v,ROUTER_MANDATORY );
  615. INT_CONST(v,TCP_KEEPALIVE );
  616. INT_CONST(v,TCP_KEEPALIVE_CNT );
  617. INT_CONST(v,TCP_KEEPALIVE_IDLE );
  618. INT_CONST(v,TCP_KEEPALIVE_INTVL );
  619. INT_CONST(v,TCP_ACCEPT_FILTER );
  620. INT_CONST(v,DELAY_ATTACH_ON_CONNECT );
  621. INT_CONST(v,XPUB_VERBOSE );
  622. INT_CONST(v,EVENT_CONNECTED);
  623. INT_CONST(v,EVENT_CONNECT_DELAYED);
  624. INT_CONST(v,EVENT_CONNECT_RETRIED);
  625. INT_CONST(v,EVENT_LISTENING);
  626. INT_CONST(v,EVENT_BIND_FAILED);
  627. INT_CONST(v,EVENT_ACCEPTED);
  628. INT_CONST(v,EVENT_ACCEPT_FAILED);
  629. INT_CONST(v,EVENT_CLOSED);
  630. INT_CONST(v,EVENT_CLOSE_FAILED);
  631. INT_CONST(v,EVENT_DISCONNECTED);
  632. INT_CONST(v,EVENT_ALL);
  633. sq_newslot(v,-3,SQTrue);
  634. sq_pushliteral(v,_SC("zmq_msg"));
  635. sq_newclass(v,SQFalse);
  636. sq_settypetag(v,-1,(void*)sq_zmq3_msg_TAG);
  637. sq_insert_reg_funcs(v, sq_zmq3_msg_methods);
  638. INT_CONST(v,MORE);
  639. INT_CONST(v,DONTWAIT);
  640. INT_CONST(v,SNDMORE);
  641. sq_newslot(v,-3,SQTrue);
  642. return 1;
  643. }
  644. #ifdef __cplusplus
  645. }
  646. #endif