PageRenderTime 59ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/liquidfeedback/moonbridge/moonbridge_io.c

https://gitlab.com/fuzzynemesis/hajaannu
C | 1757 lines | 1663 code | 93 blank | 1 comment | 385 complexity | 93cd59e7d9df21a409781dc4e44f4ea6 MD5 | raw file
Possible License(s): Apache-2.0

Large files files are truncated, but you can click here to view the full file

  1. #ifndef __has_include
  2. #define __has_include(x) 0
  3. #endif
  4. #include <stdlib.h>
  5. #include <stdint.h>
  6. #include <string.h>
  7. #include <errno.h>
  8. #include <unistd.h>
  9. #include <signal.h>
  10. #include <fcntl.h>
  11. #include <sys/stat.h>
  12. #include <sys/socket.h>
  13. #include <sys/un.h>
  14. #include <netinet/in.h>
  15. #include <netinet/tcp.h>
  16. #include <sys/select.h>
  17. #include <time.h>
  18. #include <netdb.h>
  19. #include <arpa/inet.h>
  20. #include <sys/types.h>
  21. #include <sys/wait.h>
  22. #if defined(__linux__) || __has_include(<bsd/unistd.h>)
  23. #include <bsd/unistd.h>
  24. #endif
  25. #include <lua.h>
  26. #include <lauxlib.h>
  27. #include <lualib.h>
  28. #include <assert.h>
  29. #define MOONBR_IO_MAXSTRERRORLEN 80
  30. #define MOONBR_IO_READBUFLEN 4096
  31. #define MOONBR_IO_WRITEBUFLEN 4096
  32. #define MOONBR_IO_LISTEN_BACKLOG 1024
  33. #define MOONBR_IO_STRERROR_R_MSG "Error detail unavailable due to noncompliant strerror_r() implementation"
  34. #define moonbr_io_errmsg() \
  35. char errmsg[MOONBR_IO_MAXSTRERRORLEN] = MOONBR_IO_STRERROR_R_MSG; \
  36. strerror_r(errno, errmsg, MOONBR_IO_MAXSTRERRORLEN)
  37. #define MOONBR_IO_HANDLE_MT_REGKEY "moonbridge_io_handle"
  38. #define MOONBR_IO_HANDLE_PUBLIC_MT_REGKEY "moonbridge_io_handle_public"
  39. #define MOONBR_IO_LISTENER_MT_REGKEY "moonbridge_io_listener"
  40. #define MOONBR_IO_CHILD_MT_REGKEY "moonbridge_io_child"
  41. #define MOONBR_IO_CHILD_PT_REGKEY "moonbridge_io_child_pt"
  42. typedef struct {
  43. int fd;
  44. int issock;
  45. sa_family_t addrfam;
  46. int finished;
  47. int closed;
  48. int nonblocking;
  49. int nopush;
  50. int readerr;
  51. int readbufin;
  52. int readbufout;
  53. int writeerr;
  54. size_t writeleft;
  55. size_t flushedleft;
  56. #if LUA_VERSION_NUM >= 503
  57. lua_Integer writeqin;
  58. lua_Integer writeqout;
  59. #else
  60. int writeqin;
  61. int writeqout;
  62. #endif
  63. size_t writeqoff;
  64. int writebufin;
  65. int writebufout;
  66. char readbuf[MOONBR_IO_READBUFLEN];
  67. char writebuf[MOONBR_IO_WRITEBUFLEN];
  68. } moonbr_io_handle_t;
  69. typedef struct {
  70. int fd;
  71. sa_family_t addrfam;
  72. int nonblocking;
  73. } moonbr_io_listener_t;
  74. typedef struct {
  75. pid_t pid;
  76. } moonbr_io_child_t;
  77. static int moonbr_io_yield(lua_State *L) {
  78. return lua_yield(L, lua_gettop(L));
  79. }
  80. #if LUA_VERSION_NUM >= 503
  81. static int moonbr_io_cont_returnall(lua_State *L, int status, lua_KContext ctx) {
  82. #else
  83. static int moonbr_io_cont_returnall(lua_State *L) {
  84. #endif
  85. return lua_gettop(L);
  86. }
  87. #define moonbr_io_yield_wrapper(yieldfunc, callfunc) \
  88. static int yieldfunc(lua_State *L) { \
  89. int args; \
  90. lua_pushcfunction(L, callfunc); \
  91. lua_insert(L, 1); \
  92. args = lua_gettop(L); \
  93. lua_pushcfunction(L, moonbr_io_yield); \
  94. lua_insert(L, 3); \
  95. lua_callk(L, args, LUA_MULTRET, 0, moonbr_io_cont_returnall); \
  96. return lua_gettop(L); \
  97. }
  98. static void moonbr_io_handle_set_nonblocking(lua_State *L, moonbr_io_handle_t *handle, int nonblocking) {
  99. int flags;
  100. if (handle->nonblocking == nonblocking) return;
  101. flags = fcntl(handle->fd, F_GETFL, 0);
  102. if (flags == -1) {
  103. moonbr_io_errmsg();
  104. close(handle->fd);
  105. handle->fd = -1;
  106. handle->closed = 1;
  107. luaL_error(L, "Unexpected error in fcntl call: %s", errmsg);
  108. }
  109. if (nonblocking) flags |= O_NONBLOCK;
  110. else flags &= ~O_NONBLOCK;
  111. if (fcntl(handle->fd, F_SETFL, flags) == -1) {
  112. moonbr_io_errmsg();
  113. close(handle->fd);
  114. handle->fd = -1;
  115. handle->closed = 1;
  116. luaL_error(L, "Unexpected error in fcntl call: %s", errmsg);
  117. }
  118. handle->nonblocking = nonblocking;
  119. }
  120. static void moonbr_io_handle_set_linger(lua_State *L, moonbr_io_handle_t *handle, int timeout) {
  121. struct linger lingerval = { 0, };
  122. if (!handle->issock) return;
  123. if (timeout >= 0) {
  124. lingerval.l_onoff = 1;
  125. lingerval.l_linger = timeout;
  126. }
  127. if (setsockopt(handle->fd, SOL_SOCKET, SO_LINGER, &lingerval, sizeof(lingerval))) {
  128. moonbr_io_errmsg();
  129. close(handle->fd);
  130. handle->fd = -1;
  131. handle->closed = 1;
  132. luaL_error(L, "Unexpected error while setting SO_LINGER with setsockopt: %s", errmsg);
  133. }
  134. }
  135. static inline void moonbr_io_handle_set_nopush(lua_State *L, moonbr_io_handle_t *handle, int nopush) {
  136. #if defined(TCP_NOPUSH) || defined(TCP_CORK)
  137. if (
  138. !(handle->addrfam == AF_INET6 || handle->addrfam == AF_INET) ||
  139. handle->nopush == nopush
  140. ) return;
  141. #if defined(TCP_NOPUSH)
  142. if (setsockopt(handle->fd, IPPROTO_TCP, TCP_NOPUSH, &nopush, sizeof(nopush))) {
  143. #elif defined(TCP_CORK)
  144. if (setsockopt(handle->fd, IPPROTO_TCP, TCP_CORK, &nopush, sizeof(nopush))) {
  145. #endif
  146. moonbr_io_errmsg();
  147. close(handle->fd);
  148. handle->fd = -1;
  149. handle->closed = 1;
  150. #if defined(TCP_NOPUSH)
  151. luaL_error(L, "Unexpected error while setting TCP_NOPUSH with setsockopt: %s", errmsg);
  152. #elif defined(TCP_CORK)
  153. luaL_error(L, "Unexpected error while setting TCP_CORK with setsockopt: %s", errmsg);
  154. #endif
  155. }
  156. handle->nopush = nopush;
  157. #else
  158. #warning Neither TCP_NOPUSH nor TCP_CORK is available
  159. #endif
  160. }
  161. static int moonbr_io_read_impl(lua_State *L, int nonblocking, int drain) {
  162. moonbr_io_handle_t *handle;
  163. lua_Integer maxread;
  164. const char *terminatorstr;
  165. size_t terminatorlen;
  166. char terminator = 0; /* initialize to avoid compiler warning */
  167. luaL_Buffer luabuf;
  168. size_t luabufcnt = 0;
  169. int remaining;
  170. char *terminatorpos;
  171. ssize_t bytesread;
  172. handle = luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY);
  173. maxread = luaL_optinteger(L, 2, -1);
  174. terminatorstr = luaL_optlstring(L, 3, "", &terminatorlen);
  175. if (terminatorlen) {
  176. luaL_argcheck(L, terminatorlen == 1, 3, "single byte expected");
  177. terminator = terminatorstr[0];
  178. }
  179. lua_settop(L, 1); /* return handle on drain, terminator string may be garbage collected */
  180. if (handle->closed) luaL_error(L, "Attempt to read from a closed I/O handle");
  181. if (handle->readerr) {
  182. lua_pushnil(L);
  183. lua_pushliteral(L, "Previous read error");
  184. return 2;
  185. }
  186. if (handle->fd < 0) {
  187. /* fake EOF to simulate shutdown */
  188. if (!drain) lua_pushliteral(L, "");
  189. else lua_pushinteger(L, 0);
  190. lua_pushliteral(L, "eof");
  191. return 2;
  192. }
  193. handle->readerr = 1;
  194. moonbr_io_handle_set_nonblocking(L, handle, nonblocking);
  195. if (!drain) luaL_buffinit(L, &luabuf);
  196. while (1) {
  197. remaining = -1;
  198. terminatorpos = NULL;
  199. if (
  200. maxread >= 0 &&
  201. handle->readbufin - handle->readbufout >= (size_t)maxread - luabufcnt
  202. ) {
  203. remaining = (size_t)maxread - luabufcnt;
  204. if (terminatorlen) {
  205. terminatorpos = memchr(
  206. handle->readbuf + handle->readbufout,
  207. terminator,
  208. remaining
  209. );
  210. }
  211. } else if (terminatorlen) {
  212. terminatorpos = memchr(
  213. handle->readbuf + handle->readbufout,
  214. terminator,
  215. handle->readbufin - handle->readbufout
  216. );
  217. }
  218. if (terminatorpos) remaining = 1 + (
  219. terminatorpos - (handle->readbuf + handle->readbufout)
  220. );
  221. if (remaining >= 0) {
  222. if (!drain) {
  223. luaL_addlstring(
  224. &luabuf,
  225. handle->readbuf + handle->readbufout,
  226. remaining
  227. );
  228. luaL_pushresult(&luabuf);
  229. } else {
  230. lua_pushinteger(L, luabufcnt + remaining);
  231. }
  232. if (terminatorpos) lua_pushliteral(L, "term");
  233. else lua_pushliteral(L, "maxlen");
  234. handle->readbufout += remaining;
  235. if (handle->readbufout == handle->readbufin) {
  236. handle->readbufin = 0;
  237. handle->readbufout = 0;
  238. }
  239. handle->readerr = 0;
  240. return 2;
  241. }
  242. if (!drain) luaL_addlstring(
  243. &luabuf,
  244. handle->readbuf + handle->readbufout,
  245. handle->readbufin - handle->readbufout
  246. );
  247. luabufcnt += handle->readbufin - handle->readbufout;
  248. handle->readbufout = 0;
  249. do {
  250. bytesread = read(handle->fd, handle->readbuf, MOONBR_IO_READBUFLEN);
  251. } while (bytesread < 0 && (errno == EINTR));
  252. if (
  253. bytesread == 0 || (
  254. nonblocking &&
  255. bytesread < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)
  256. )
  257. ) {
  258. handle->readbufin = 0;
  259. if (!drain) luaL_pushresult(&luabuf);
  260. else lua_pushinteger(L, luabufcnt);
  261. if (bytesread == 0) lua_pushliteral(L, "eof");
  262. else lua_pushliteral(L, "block");
  263. handle->readerr = 0;
  264. return 2;
  265. }
  266. if (bytesread < 0) {
  267. moonbr_io_errmsg();
  268. lua_pushnil(L);
  269. lua_pushstring(L, errmsg);
  270. return 2;
  271. }
  272. handle->readbufin = bytesread;
  273. }
  274. }
  275. static int moonbr_io_read(lua_State *L) {
  276. return moonbr_io_read_impl(L, 0, 0);
  277. }
  278. static int moonbr_io_read_nb(lua_State *L) {
  279. return moonbr_io_read_impl(L, 1, 0);
  280. }
  281. static int moonbr_io_drain(lua_State *L) {
  282. return moonbr_io_read_impl(L, 0, 1);
  283. }
  284. static int moonbr_io_drain_nb(lua_State *L) {
  285. return moonbr_io_read_impl(L, 1, 1);
  286. }
  287. #if LUA_VERSION_NUM >= 503
  288. static int moonbr_io_read_cont(lua_State *L, int status, lua_KContext ctx) {
  289. #else
  290. static int moonbr_io_read_cont(lua_State *L) {
  291. #endif
  292. lua_Integer remaining;
  293. size_t len;
  294. #if !(LUA_VERSION_NUM >= 503)
  295. int ctx = 0;
  296. lua_getctx(L, &ctx);
  297. #endif
  298. remaining = lua_tointeger(L, 3);
  299. while (1) {
  300. lua_pushcfunction(L, moonbr_io_read_nb);
  301. lua_pushvalue(L, 1);
  302. lua_pushvalue(L, 3);
  303. lua_pushvalue(L, 4);
  304. lua_call(L, 3, 2);
  305. if (lua_isnil(L, -2)) return 2;
  306. lua_insert(L, -2);
  307. len = lua_rawlen(L, -1);
  308. if (ctx == 0) {
  309. lua_replace(L, 5);
  310. ctx = 1;
  311. } else if (ctx == 1) {
  312. lua_pushvalue(L, 5);
  313. lua_newtable(L);
  314. lua_replace(L, 5);
  315. lua_rawseti(L, 5, 2);
  316. lua_rawseti(L, 5, 1);
  317. ctx = 2;
  318. } else {
  319. lua_rawseti(L, 5, lua_rawlen(L, 5) + 1);
  320. }
  321. if (strcmp(lua_tostring(L, -1), "block") != 0) break;
  322. lua_pop(L, 1);
  323. if (remaining >= 0 && len) {
  324. remaining -= len;
  325. lua_pushinteger(L, remaining);
  326. lua_replace(L, 3);
  327. }
  328. lua_pushvalue(L, 2);
  329. lua_callk(L, 0, 0, ctx, moonbr_io_read_cont);
  330. }
  331. if (ctx == 1) {
  332. lua_pushvalue(L, 5);
  333. } else {
  334. luaL_Buffer buf;
  335. lua_Integer i, chunkcount;
  336. chunkcount = lua_rawlen(L, 5);
  337. luaL_buffinit(L, &buf);
  338. for (i=1; i<=chunkcount && i>0; i++) {
  339. lua_rawgeti(L, 5, i);
  340. luaL_addvalue(&buf);
  341. }
  342. luaL_pushresult(&buf);
  343. }
  344. lua_pushvalue(L, -2);
  345. return 2;
  346. }
  347. static int moonbr_io_read_call(lua_State *L) {
  348. lua_settop(L, 4);
  349. lua_pushnil(L);
  350. #if LUA_VERSION_NUM >= 503
  351. return moonbr_io_read_cont(L, 0, 0);
  352. #else
  353. return moonbr_io_read_cont(L);
  354. #endif
  355. }
  356. moonbr_io_yield_wrapper(moonbr_io_read_yield, moonbr_io_read_call);
  357. #if LUA_VERSION_NUM >= 503
  358. static int moonbr_io_drain_cont(lua_State *L, int status, lua_KContext ctx) {
  359. #else
  360. static int moonbr_io_drain_cont(lua_State *L) {
  361. #endif
  362. lua_Integer remaining, len;
  363. size_t totallen = 0;
  364. #if !(LUA_VERSION_NUM >= 503)
  365. int ctx = 0;
  366. lua_getctx(L, &ctx);
  367. #endif
  368. remaining = lua_tointeger(L, 3);
  369. while (1) {
  370. lua_pushcfunction(L, moonbr_io_drain_nb);
  371. lua_pushvalue(L, 1);
  372. lua_pushvalue(L, 3);
  373. lua_pushvalue(L, 4);
  374. lua_call(L, 3, 2);
  375. if (lua_isnil(L, -2)) return 2;
  376. lua_insert(L, -2);
  377. len = lua_tointeger(L, -1);
  378. lua_pop(L, 1);
  379. totallen += len;
  380. if (strcmp(lua_tostring(L, -1), "block") != 0) break;
  381. lua_pop(L, 1);
  382. if (remaining >= 0 && len) {
  383. remaining -= len;
  384. lua_pushinteger(L, remaining);
  385. lua_replace(L, 3);
  386. }
  387. lua_pushvalue(L, 2);
  388. lua_callk(L, 0, 0, ctx, moonbr_io_drain_cont);
  389. }
  390. lua_pushinteger(L, totallen);
  391. lua_pushvalue(L, -2);
  392. return 2;
  393. }
  394. static int moonbr_io_drain_call(lua_State *L) {
  395. #if LUA_VERSION_NUM >= 503
  396. return moonbr_io_drain_cont(L, 0, 0);
  397. #else
  398. return moonbr_io_drain_cont(L);
  399. #endif
  400. }
  401. moonbr_io_yield_wrapper(moonbr_io_drain_yield, moonbr_io_drain_call);
  402. static int moonbr_io_write_impl(lua_State *L, int nonblocking, int flush) {
  403. moonbr_io_handle_t *handle;
  404. int i, top;
  405. const char *str;
  406. size_t strlen;
  407. ssize_t written;
  408. handle = luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY);
  409. if (handle->closed) luaL_error(L, "Attempt to write to a closed I/O handle");
  410. if (handle->finished) luaL_error(L, "Attempt to write to a finished I/O handle");
  411. if (handle->writeerr) {
  412. lua_pushnil(L);
  413. lua_pushliteral(L, "Previous write error");
  414. return 2;
  415. }
  416. handle->writeerr = 1;
  417. moonbr_io_handle_set_nonblocking(L, handle, nonblocking);
  418. top = lua_gettop(L);
  419. lua_getuservalue(L, 1);
  420. lua_getfield(L, -1, "writequeue");
  421. for (i=2; i<=top; i++) {
  422. luaL_checklstring(L, i, &strlen);
  423. lua_pushvalue(L, i);
  424. lua_rawseti(L, -2, handle->writeqin++);
  425. handle->writeleft += strlen;
  426. }
  427. if (flush) handle->flushedleft = handle->writeleft;
  428. while (handle->writeqout != handle->writeqin) {
  429. lua_rawgeti(L, -1, handle->writeqout);
  430. str = lua_tolstring(L, -1, &strlen);
  431. while (handle->writeqoff < strlen) {
  432. if (
  433. strlen - handle->writeqoff <
  434. MOONBR_IO_WRITEBUFLEN - handle->writebufin
  435. ) {
  436. memcpy(
  437. handle->writebuf + handle->writebufin,
  438. str + handle->writeqoff,
  439. strlen - handle->writeqoff
  440. );
  441. handle->writebufin += strlen - handle->writeqoff;
  442. break;
  443. } else {
  444. memcpy(
  445. handle->writebuf + handle->writebufin,
  446. str + handle->writeqoff,
  447. MOONBR_IO_WRITEBUFLEN - handle->writebufin
  448. );
  449. handle->writeqoff += MOONBR_IO_WRITEBUFLEN - handle->writebufin;
  450. handle->writebufin = MOONBR_IO_WRITEBUFLEN;
  451. while (handle->writebufout < MOONBR_IO_WRITEBUFLEN) {
  452. moonbr_io_handle_set_nopush(L, handle, 1);
  453. written = write(
  454. handle->fd,
  455. handle->writebuf + handle->writebufout,
  456. MOONBR_IO_WRITEBUFLEN - handle->writebufout
  457. );
  458. if (written < 0) {
  459. if (nonblocking && (errno == EAGAIN || errno == EWOULDBLOCK)) {
  460. goto moonbr_io_write_impl_block;
  461. } else if (errno != EINTR) {
  462. moonbr_io_errmsg();
  463. lua_pushnil(L);
  464. lua_pushstring(L, errmsg);
  465. return 2;
  466. }
  467. } else {
  468. handle->writebufout += written;
  469. handle->writeleft -= written;
  470. if (handle->flushedleft) {
  471. if (written >= handle->flushedleft) {
  472. handle->flushedleft = 0;
  473. moonbr_io_handle_set_nopush(L, handle, 0);
  474. } else {
  475. handle->flushedleft -= written;
  476. }
  477. }
  478. }
  479. }
  480. handle->writebufin = 0;
  481. handle->writebufout = 0;
  482. }
  483. }
  484. handle->writeqoff = 0;
  485. lua_pop(L, 1);
  486. lua_pushnil(L);
  487. lua_rawseti(L, -2, handle->writeqout++);
  488. }
  489. while (handle->flushedleft) {
  490. moonbr_io_handle_set_nopush(L, handle, 1);
  491. written = write(
  492. handle->fd,
  493. handle->writebuf + handle->writebufout,
  494. handle->writebufin - handle->writebufout
  495. );
  496. if (written < 0) {
  497. if (nonblocking && (errno == EAGAIN || errno == EWOULDBLOCK)) {
  498. goto moonbr_io_write_impl_block;
  499. } else if (errno != EINTR) {
  500. moonbr_io_errmsg();
  501. lua_pushnil(L);
  502. lua_pushstring(L, errmsg);
  503. return 2;
  504. }
  505. } else {
  506. handle->writebufout += written;
  507. handle->writeleft -= written;
  508. if (handle->flushedleft) {
  509. if (written >= handle->flushedleft) {
  510. handle->flushedleft = 0;
  511. moonbr_io_handle_set_nopush(L, handle, 0);
  512. } else {
  513. handle->flushedleft -= written;
  514. }
  515. }
  516. }
  517. }
  518. if (handle->writebufout == handle->writebufin) {
  519. handle->writebufin = 0;
  520. handle->writebufout = 0;
  521. }
  522. if (nonblocking) lua_pushinteger(L, 0);
  523. else lua_pushvalue(L, 1);
  524. handle->writeerr = 0;
  525. return 1;
  526. moonbr_io_write_impl_block:
  527. lua_pushinteger(L, handle->writeleft);
  528. handle->writeerr = 0;
  529. return 1;
  530. }
  531. static int moonbr_io_write(lua_State *L) {
  532. return moonbr_io_write_impl(L, 0, 0);
  533. }
  534. static int moonbr_io_write_nb(lua_State *L) {
  535. return moonbr_io_write_impl(L, 1, 0);
  536. }
  537. static int moonbr_io_flush(lua_State *L) {
  538. return moonbr_io_write_impl(L, 0, 1);
  539. }
  540. static int moonbr_io_flush_nb(lua_State *L) {
  541. return moonbr_io_write_impl(L, 1, 1);
  542. }
  543. #if LUA_VERSION_NUM >= 503
  544. static int moonbr_io_write_cont(lua_State *L, int status, lua_KContext ctx) {
  545. #else
  546. static int moonbr_io_write_cont(lua_State *L) {
  547. #endif
  548. while (1) {
  549. lua_pushcfunction(L, moonbr_io_write_nb);
  550. lua_pushvalue(L, 1);
  551. lua_call(L, 1, 2);
  552. if (lua_isnil(L, -2)) return 2;
  553. if (!lua_tointeger(L, -2)) {
  554. lua_pushvalue(L, 1);
  555. return 1;
  556. }
  557. lua_pop(L, 2);
  558. lua_pushvalue(L, 2);
  559. lua_callk(L, 0, 0, 0, moonbr_io_write_cont);
  560. }
  561. }
  562. static int moonbr_io_write_call(lua_State *L) {
  563. lua_pushcfunction(L, moonbr_io_write_nb);
  564. lua_insert(L, 3);
  565. lua_pushvalue(L, 1);
  566. lua_insert(L, 4);
  567. lua_call(L, lua_gettop(L) - 3, 2);
  568. if (lua_isnil(L, -2)) return 2;
  569. if (!lua_tointeger(L, -2)) {
  570. lua_pushvalue(L, 1);
  571. return 1;
  572. }
  573. #if LUA_VERSION_NUM >= 503
  574. return moonbr_io_write_cont(L, 0, 0);
  575. #else
  576. return moonbr_io_write_cont(L);
  577. #endif
  578. }
  579. moonbr_io_yield_wrapper(moonbr_io_write_yield, moonbr_io_write_call);
  580. static int moonbr_io_flush_call(lua_State *L) {
  581. lua_pushcfunction(L, moonbr_io_flush_nb);
  582. lua_insert(L, 3);
  583. lua_pushvalue(L, 1);
  584. lua_insert(L, 4);
  585. lua_call(L, lua_gettop(L) - 3, 2);
  586. if (lua_isnil(L, -2)) return 2;
  587. if (!lua_tointeger(L, -2)) {
  588. lua_pushvalue(L, 1);
  589. return 1;
  590. }
  591. #if LUA_VERSION_NUM >= 503
  592. return moonbr_io_write_cont(L, 0, 0);
  593. #else
  594. return moonbr_io_write_cont(L);
  595. #endif
  596. }
  597. moonbr_io_yield_wrapper(moonbr_io_flush_yield, moonbr_io_flush_call);
  598. static int moonbr_io_finish(lua_State *L) {
  599. moonbr_io_handle_t *handle;
  600. handle = luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY);
  601. if (handle->closed) luaL_error(L, "Attempt to finish a closed I/O handle");
  602. if (handle->finished) luaL_error(L, "Attempt to finish a finished I/O handle");
  603. if (handle->writeleft) {
  604. lua_pushcfunction(L, moonbr_io_flush);
  605. lua_pushvalue(L, 1);
  606. if (lua_pcall(L, 1, 2, 0)) {
  607. handle->finished = 1;
  608. lua_error(L);
  609. }
  610. if (!lua_toboolean(L, -2)) {
  611. handle->finished = 1;
  612. return 2;
  613. }
  614. }
  615. handle->finished = 1;
  616. if (handle->addrfam == AF_INET6 || handle->addrfam == AF_INET) {
  617. if (shutdown(handle->fd, SHUT_WR)) {
  618. moonbr_io_errmsg();
  619. lua_pushnil(L);
  620. lua_pushstring(L, errmsg);
  621. return 2;
  622. }
  623. } else {
  624. if (close(handle->fd)) {
  625. moonbr_io_errmsg();
  626. handle->fd = -1;
  627. lua_pushnil(L);
  628. lua_pushstring(L, errmsg);
  629. return 2;
  630. }
  631. handle->fd = -1; /* fake EOF on read */
  632. }
  633. lua_pushboolean(L, 1);
  634. return 1;
  635. }
  636. static int moonbr_io_close_impl(lua_State *L, int reset) {
  637. moonbr_io_handle_t *handle;
  638. handle = luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY);
  639. if (handle->closed) luaL_error(L, "Attempt to close a closed I/O handle");
  640. if (!reset) {
  641. if (handle->writeleft) {
  642. lua_pushcfunction(L, moonbr_io_flush);
  643. lua_pushvalue(L, 1);
  644. if (lua_pcall(L, 1, 2, 0)) {
  645. handle->closed = 1;
  646. close(handle->fd);
  647. handle->fd = -1;
  648. lua_error(L);
  649. }
  650. handle->closed = 1;
  651. if (!lua_toboolean(L, -2)) {
  652. close(handle->fd);
  653. handle->fd = -1;
  654. return 2;
  655. }
  656. } else {
  657. handle->closed = 1;
  658. moonbr_io_handle_set_linger(L, handle, -1);
  659. }
  660. } else {
  661. handle->closed = 1;
  662. }
  663. if (handle->fd >= 0) {
  664. if (close(handle->fd)) {
  665. moonbr_io_errmsg();
  666. handle->fd = -1;
  667. lua_pushnil(L);
  668. lua_pushstring(L, errmsg);
  669. return 2;
  670. }
  671. handle->fd = -1;
  672. }
  673. lua_pushboolean(L, 1);
  674. return 1;
  675. }
  676. static int moonbr_io_close(lua_State *L) {
  677. return moonbr_io_close_impl(L, 0);
  678. }
  679. static int moonbr_io_reset(lua_State *L) {
  680. return moonbr_io_close_impl(L, 1);
  681. }
  682. static int moonbr_io_handlegc(lua_State *L) {
  683. moonbr_io_handle_t *handle;
  684. handle = luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY);
  685. if (handle->fd >= 0) {
  686. lua_pushcfunction(L, moonbr_io_reset);
  687. lua_pushvalue(L, 1);
  688. lua_pushinteger(L, 0);
  689. lua_call(L, 2, 0);
  690. }
  691. return 0;
  692. }
  693. void moonbr_io_closehandle(lua_State *L, int idx, int reset) {
  694. moonbr_io_handle_t *handle;
  695. handle = luaL_checkudata(L, idx, MOONBR_IO_HANDLE_MT_REGKEY);
  696. if (!handle->closed) {
  697. lua_pushcfunction(L, reset ? moonbr_io_reset : moonbr_io_close);
  698. lua_pushvalue(L, idx < 0 ? idx-1 : idx);
  699. lua_call(L, 1, 0);
  700. }
  701. }
  702. static int moonbr_io_pushhandle_impl(lua_State *L) {
  703. int *fd;
  704. moonbr_io_handle_t *handle;
  705. struct sockaddr addr;
  706. socklen_t addrlen;
  707. fd = lua_touserdata(L, 1);
  708. handle = lua_newuserdata(L, sizeof(moonbr_io_handle_t));
  709. handle->fd = -1; /* avoid closing incomplete handle */
  710. addrlen = sizeof(addr);
  711. if (getsockname(*fd, &addr, &addrlen)) {
  712. if (errno != ENOTSOCK) {
  713. moonbr_io_errmsg();
  714. luaL_error(L, "Unexpected error when examining socket: %s", errmsg);
  715. }
  716. handle->issock = 0;
  717. } else {
  718. handle->issock = 1;
  719. handle->addrfam = addr.sa_family;
  720. }
  721. handle->finished = 0;
  722. handle->closed = 0;
  723. handle->nonblocking = -1;
  724. handle->nopush = -1;
  725. handle->readerr = 0;
  726. handle->readbufin = 0;
  727. handle->readbufout = 0;
  728. handle->writeerr = 0;
  729. handle->writeleft = 0;
  730. handle->flushedleft = 0;
  731. handle->writeqin = 0;
  732. handle->writeqout = 0;
  733. handle->writeqoff = 0;
  734. handle->writebufin = 0;
  735. handle->writebufout = 0;
  736. handle->fd = *fd; /* required for set_linger call */
  737. moonbr_io_handle_set_linger(L, handle, 0);
  738. handle->fd = -1; /* avoid closing incomplete handle */
  739. luaL_getmetatable(L, MOONBR_IO_HANDLE_MT_REGKEY);
  740. lua_setmetatable(L, -2);
  741. lua_newtable(L); // uservalue
  742. lua_newtable(L);
  743. lua_setfield(L, -2, "writequeue");
  744. lua_newtable(L); // public
  745. if (handle->addrfam == AF_INET6) {
  746. struct sockaddr_in6 addr_in6;
  747. char addrstrbuf[INET6_ADDRSTRLEN];
  748. const char *addrstr;
  749. addrlen = sizeof(addr_in6);
  750. if (getsockname(*fd, (struct sockaddr *)&addr_in6, &addrlen)) {
  751. moonbr_io_errmsg();
  752. luaL_error(L, "Could not determine local IP address/port: %s", errmsg);
  753. }
  754. if (addrlen > sizeof(addr_in6)) {
  755. luaL_error(L, "Could not determine local IP address/port: buffer size exceeded");
  756. }
  757. addrstr = inet_ntop(AF_INET6, addr_in6.sin6_addr.s6_addr, addrstrbuf, sizeof(addrstrbuf));
  758. if (!addrstr) {
  759. moonbr_io_errmsg();
  760. luaL_error(L, "Could not format local IP address: %s", errmsg);
  761. } else {
  762. lua_pushstring(L, addrstr);
  763. lua_setfield(L, -2, "local_ip6");
  764. }
  765. lua_pushinteger(L, ntohs(addr_in6.sin6_port));
  766. lua_setfield(L, -2, "local_tcpport");
  767. if (getpeername(*fd, (struct sockaddr *)&addr_in6, &addrlen)) {
  768. moonbr_io_errmsg();
  769. luaL_error(L, "Could not determine remote IP address/port: %s", errmsg);
  770. }
  771. if (addrlen > sizeof(addr_in6)) {
  772. luaL_error(L, "Could not determine remote IP address/port: buffer size exceeded");
  773. }
  774. addrstr = inet_ntop(AF_INET6, addr_in6.sin6_addr.s6_addr, addrstrbuf, sizeof(addrstrbuf));
  775. if (!addrstr) {
  776. moonbr_io_errmsg();
  777. luaL_error(L, "Could not format remote IP address: %s", errmsg);
  778. } else {
  779. lua_pushstring(L, addrstr);
  780. lua_setfield(L, -2, "remote_ip6");
  781. }
  782. lua_pushinteger(L, ntohs(addr_in6.sin6_port));
  783. lua_setfield(L, -2, "remote_tcpport");
  784. } else if (handle->addrfam == AF_INET) {
  785. struct sockaddr_in addr_in;
  786. char addrstrbuf[INET_ADDRSTRLEN];
  787. const char *addrstr;
  788. addrlen = sizeof(addr_in);
  789. if (getsockname(*fd, (struct sockaddr *)&addr_in, &addrlen)) {
  790. moonbr_io_errmsg();
  791. luaL_error(L, "Could not determine local IP address/port: %s", errmsg);
  792. }
  793. if (addrlen > sizeof(addr_in)) {
  794. luaL_error(L, "Could not determine local IP address/port: buffer size exceeded");
  795. }
  796. addrstr = inet_ntop(AF_INET, &addr_in.sin_addr.s_addr, addrstrbuf, sizeof(addrstrbuf));
  797. if (!addrstr) {
  798. moonbr_io_errmsg();
  799. luaL_error(L, "Could not format local IP address: %s", errmsg);
  800. } else {
  801. lua_pushstring(L, addrstr);
  802. lua_setfield(L, -2, "local_ip4");
  803. }
  804. lua_pushinteger(L, ntohs(addr_in.sin_port));
  805. lua_setfield(L, -2, "local_tcpport");
  806. if (getpeername(*fd, (struct sockaddr *)&addr_in, &addrlen)) {
  807. moonbr_io_errmsg();
  808. luaL_error(L, "Could not determine remote IP address/port: %s", errmsg);
  809. }
  810. if (addrlen > sizeof(addr_in)) {
  811. luaL_error(L, "Could not determine remote IP address/port: buffer size exceeded");
  812. }
  813. addrstr = inet_ntop(AF_INET, &addr_in.sin_addr.s_addr, addrstrbuf, sizeof(addrstrbuf));
  814. if (!addrstr) {
  815. moonbr_io_errmsg();
  816. luaL_error(L, "Could not format remote IP address: %s", errmsg);
  817. } else {
  818. lua_pushstring(L, addrstr);
  819. lua_setfield(L, -2, "remote_ip4");
  820. }
  821. lua_pushinteger(L, ntohs(addr_in.sin_port));
  822. lua_setfield(L, -2, "remote_tcpport");
  823. }
  824. luaL_getmetatable(L, MOONBR_IO_HANDLE_PUBLIC_MT_REGKEY);
  825. lua_setmetatable(L, -2);
  826. lua_setfield(L, -2, "public");
  827. lua_setuservalue(L, -2);
  828. handle->fd = *fd;
  829. *fd = -1; /* closing is now handled by garbage collection */
  830. return 1;
  831. }
  832. void moonbr_io_pushhandle(lua_State *L, int fd) {
  833. lua_pushcfunction(L, moonbr_io_pushhandle_impl);
  834. lua_pushlightuserdata(L, &fd);
  835. if (lua_pcall(L, 1, 1, 0)) {
  836. if (fd != -1) close(fd);
  837. lua_error(L);
  838. }
  839. }
  840. static int moonbr_io_handleindex(lua_State *L) {
  841. luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY);
  842. luaL_checkany(L, 2);
  843. lua_getuservalue(L, 1);
  844. lua_getfield(L, -1, "public");
  845. lua_pushvalue(L, 2);
  846. lua_gettable(L, -2);
  847. return 1;
  848. }
  849. static int moonbr_io_handlenewindex(lua_State *L) {
  850. luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY);
  851. luaL_checkany(L, 2);
  852. luaL_checkany(L, 3);
  853. lua_getuservalue(L, 1);
  854. lua_getfield(L, -1, "public");
  855. lua_pushvalue(L, 2);
  856. lua_pushvalue(L, 3);
  857. lua_settable(L, -3);
  858. return 0;
  859. }
  860. static int moonbr_io_localconnect_impl(lua_State *L, int nonblocking) {
  861. const char *path;
  862. struct sockaddr_un sockaddr = { .sun_family = AF_LOCAL };
  863. const int path_maxlen = sizeof(struct sockaddr_un) - (
  864. (void *)sockaddr.sun_path - (void *)&sockaddr
  865. ) - 1; /* one byte for termination */
  866. int sock;
  867. path = luaL_checkstring(L, 1);
  868. if (strlen(path) > path_maxlen) luaL_error(L, "Path too long; only %i characters allowed", path_maxlen);
  869. strcpy(sockaddr.sun_path, path);
  870. sock = socket(
  871. PF_LOCAL,
  872. SOCK_STREAM | SOCK_CLOEXEC | (nonblocking ? SOCK_NONBLOCK : 0),
  873. 0
  874. );
  875. if (sock < 0) {
  876. moonbr_io_errmsg();
  877. lua_pushnil(L);
  878. lua_pushstring(L, errmsg);
  879. return 2;
  880. }
  881. if (connect(sock, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) {
  882. if (!nonblocking && errno == EINTR) {
  883. moonbr_io_errmsg();
  884. close(sock);
  885. lua_pushnil(L);
  886. lua_pushstring(L, errmsg);
  887. return 2;
  888. } else if (!(nonblocking && (errno == EINPROGRESS || errno == EINTR))) {
  889. moonbr_io_errmsg();
  890. lua_pushnil(L);
  891. lua_pushstring(L, errmsg);
  892. return 2;
  893. }
  894. }
  895. moonbr_io_pushhandle(L, sock);
  896. return 1;
  897. }
  898. static int moonbr_io_localconnect(lua_State *L) {
  899. return moonbr_io_localconnect_impl(L, 0);
  900. }
  901. static int moonbr_io_localconnect_nb(lua_State *L) {
  902. return moonbr_io_localconnect_impl(L, 1);
  903. }
  904. static int moonbr_io_tcpconnect_impl(lua_State *L, int nonblocking) {
  905. const char *host, *port;
  906. struct addrinfo hints = { 0, };
  907. struct addrinfo *res, *addrinfo;
  908. int errcode;
  909. int sock;
  910. host = luaL_checkstring(L, 1);
  911. port = luaL_checkstring(L, 2);
  912. hints.ai_family = AF_UNSPEC;
  913. hints.ai_socktype = SOCK_STREAM;
  914. hints.ai_protocol = IPPROTO_TCP;
  915. hints.ai_flags = AI_ADDRCONFIG;
  916. errcode = getaddrinfo(host, port, &hints, &res);
  917. if (errcode) {
  918. freeaddrinfo(res);
  919. if (errcode == EAI_SYSTEM) {
  920. moonbr_io_errmsg();
  921. lua_pushnil(L);
  922. lua_pushfstring(L, "%s: %s", gai_strerror(errcode), errmsg);
  923. } else {
  924. lua_pushnil(L);
  925. lua_pushstring(L, gai_strerror(errcode));
  926. }
  927. return 2;
  928. }
  929. for (addrinfo=res; addrinfo; addrinfo=addrinfo->ai_next) {
  930. if (addrinfo->ai_family == AF_INET6) goto moonbr_io_tcpconnect_found;
  931. }
  932. for (addrinfo=res; addrinfo; addrinfo=addrinfo->ai_next) {
  933. if (addrinfo->ai_family == AF_INET) goto moonbr_io_tcpconnect_found;
  934. }
  935. addrinfo = res;
  936. moonbr_io_tcpconnect_found:
  937. sock = socket(
  938. addrinfo->ai_family, /* NOTE: not correctly using PF_* but AF_* constants here */
  939. addrinfo->ai_socktype | SOCK_CLOEXEC | (nonblocking ? SOCK_NONBLOCK : 0),
  940. addrinfo->ai_protocol
  941. );
  942. if (sock < 0) {
  943. moonbr_io_errmsg();
  944. freeaddrinfo(res);
  945. lua_pushnil(L);
  946. lua_pushstring(L, errmsg);
  947. return 2;
  948. }
  949. if (connect(sock, addrinfo->ai_addr, addrinfo->ai_addrlen)) {
  950. freeaddrinfo(res);
  951. if (!nonblocking && errno == EINTR) {
  952. moonbr_io_errmsg();
  953. close(sock);
  954. lua_pushnil(L);
  955. lua_pushstring(L, errmsg);
  956. return 2;
  957. } else if (!(nonblocking && (errno == EINPROGRESS || errno == EINTR))) {
  958. moonbr_io_errmsg();
  959. lua_pushnil(L);
  960. lua_pushstring(L, errmsg);
  961. return 2;
  962. }
  963. } else {
  964. freeaddrinfo(res);
  965. }
  966. moonbr_io_pushhandle(L, sock);
  967. return 1;
  968. }
  969. static int moonbr_io_tcpconnect(lua_State *L) {
  970. return moonbr_io_tcpconnect_impl(L, 0);
  971. }
  972. static int moonbr_io_tcpconnect_nb(lua_State *L) {
  973. return moonbr_io_tcpconnect_impl(L, 1);
  974. }
  975. static int moonbr_io_locallisten(lua_State *L) {
  976. moonbr_io_listener_t *listener;
  977. const char *path;
  978. struct stat sb;
  979. struct sockaddr_un sockaddr = { .sun_family = AF_LOCAL };
  980. const int path_maxlen = sizeof(struct sockaddr_un) - (
  981. (void *)sockaddr.sun_path - (void *)&sockaddr
  982. ) - 1; /* one byte for termination */
  983. int sock;
  984. path = luaL_checkstring(L, 1);
  985. if (strlen(path) > path_maxlen) luaL_error(L, "Path too long; only %i characters allowed", path_maxlen);
  986. strcpy(sockaddr.sun_path, path);
  987. if (stat(path, &sb) == 0) {
  988. if (S_ISSOCK(sb.st_mode)) unlink(path);
  989. }
  990. listener = lua_newuserdata(L, sizeof(moonbr_io_listener_t));
  991. listener->fd = -1;
  992. luaL_setmetatable(L, MOONBR_IO_LISTENER_MT_REGKEY);
  993. sock = socket(
  994. PF_LOCAL,
  995. SOCK_STREAM | SOCK_CLOEXEC,
  996. 0
  997. );
  998. if (sock < 0) {
  999. moonbr_io_errmsg();
  1000. lua_pushnil(L);
  1001. lua_pushstring(L, errmsg);
  1002. return 2;
  1003. }
  1004. if (bind(sock, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) {
  1005. moonbr_io_errmsg();
  1006. close(sock);
  1007. lua_pushnil(L);
  1008. lua_pushstring(L, errmsg);
  1009. return 2;
  1010. }
  1011. if (listen(sock, MOONBR_IO_LISTEN_BACKLOG)) {
  1012. moonbr_io_errmsg();
  1013. close(sock);
  1014. lua_pushnil(L);
  1015. lua_pushstring(L, errmsg);
  1016. return 2;
  1017. }
  1018. listener->fd = sock;
  1019. listener->addrfam = AF_LOCAL;
  1020. listener->nonblocking = -1;
  1021. return 1;
  1022. }
  1023. static int moonbr_io_tcplisten(lua_State *L) {
  1024. moonbr_io_listener_t *listener;
  1025. const char *host, *port;
  1026. struct addrinfo hints = { 0, };
  1027. struct addrinfo *res, *addrinfo;
  1028. int errcode;
  1029. int sock;
  1030. host = luaL_optstring(L, 1, NULL);
  1031. port = luaL_checkstring(L, 2);
  1032. listener = lua_newuserdata(L, sizeof(moonbr_io_listener_t));
  1033. listener->fd = -1;
  1034. luaL_setmetatable(L, MOONBR_IO_LISTENER_MT_REGKEY);
  1035. hints.ai_family = AF_UNSPEC;
  1036. hints.ai_socktype = SOCK_STREAM;
  1037. hints.ai_protocol = IPPROTO_TCP;
  1038. hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
  1039. errcode = getaddrinfo(host, port, &hints, &res);
  1040. if (errcode) {
  1041. freeaddrinfo(res);
  1042. if (errcode == EAI_SYSTEM) {
  1043. moonbr_io_errmsg();
  1044. lua_pushnil(L);
  1045. lua_pushfstring(L, "%s: %s", gai_strerror(errcode), errmsg);
  1046. } else {
  1047. lua_pushnil(L);
  1048. lua_pushstring(L, gai_strerror(errcode));
  1049. }
  1050. return 2;
  1051. }
  1052. for (addrinfo=res; addrinfo; addrinfo=addrinfo->ai_next) {
  1053. if (addrinfo->ai_family == AF_INET6) goto moonbr_io_tcpconnect_found;
  1054. }
  1055. for (addrinfo=res; addrinfo; addrinfo=addrinfo->ai_next) {
  1056. if (addrinfo->ai_family == AF_INET) goto moonbr_io_tcpconnect_found;
  1057. }
  1058. addrinfo = res;
  1059. moonbr_io_tcpconnect_found:
  1060. listener->addrfam = addrinfo->ai_family;
  1061. sock = socket(
  1062. addrinfo->ai_family, /* NOTE: not correctly using PF_* but AF_* constants here */
  1063. addrinfo->ai_socktype | SOCK_CLOEXEC,
  1064. addrinfo->ai_protocol
  1065. );
  1066. if (sock < 0) {
  1067. moonbr_io_errmsg();
  1068. freeaddrinfo(res);
  1069. lua_pushnil(L);
  1070. lua_pushstring(L, errmsg);
  1071. return 2;
  1072. }
  1073. {
  1074. static const int reuseval = 1;
  1075. if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuseval, sizeof(reuseval))) {
  1076. moonbr_io_errmsg();
  1077. freeaddrinfo(res);
  1078. close(sock);
  1079. lua_pushnil(L);
  1080. lua_pushfstring(L, "Error while setting SO_REUSEADDR with setsockopt: %s", errmsg);
  1081. return 2;
  1082. }
  1083. }
  1084. if (bind(sock, addrinfo->ai_addr, addrinfo->ai_addrlen)) {
  1085. moonbr_io_errmsg();
  1086. freeaddrinfo(res);
  1087. close(sock);
  1088. lua_pushnil(L);
  1089. lua_pushstring(L, errmsg);
  1090. return 2;
  1091. }
  1092. freeaddrinfo(res);
  1093. if (listen(sock, MOONBR_IO_LISTEN_BACKLOG)) {
  1094. moonbr_io_errmsg();
  1095. close(sock);
  1096. lua_pushnil(L);
  1097. lua_pushstring(L, errmsg);
  1098. return 2;
  1099. }
  1100. listener->fd = sock;
  1101. listener->nonblocking = -1;
  1102. return 1;
  1103. }
  1104. static int moonbr_io_accept_impl(lua_State *L, int nonblocking) {
  1105. moonbr_io_listener_t *listener;
  1106. int fd;
  1107. listener = luaL_checkudata(L, 1, MOONBR_IO_LISTENER_MT_REGKEY);
  1108. if (listener->fd < 0) luaL_error(L, "Attempt to use a closed listener");
  1109. if (listener->nonblocking != nonblocking) {
  1110. int flags;
  1111. flags = fcntl(listener->fd, F_GETFL, 0);
  1112. if (flags == -1) {
  1113. moonbr_io_errmsg();
  1114. close(listener->fd);
  1115. listener->fd = -1;
  1116. luaL_error(L, "Unexpected error in fcntl call: %s", errmsg);
  1117. }
  1118. if (nonblocking) flags |= O_NONBLOCK;
  1119. else flags &= ~O_NONBLOCK;
  1120. if (fcntl(listener->fd, F_SETFL, flags) == -1) {
  1121. moonbr_io_errmsg();
  1122. close(listener->fd);
  1123. listener->fd = -1;
  1124. luaL_error(L, "Unexpected error in fcntl call: %s", errmsg);
  1125. }
  1126. listener->nonblocking = nonblocking;
  1127. }
  1128. while (1) {
  1129. #if defined(__linux__) && !defined(_GNU_SOURCE)
  1130. fd = accept(listener->fd, NULL, NULL);
  1131. if (fd != -1) {
  1132. if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
  1133. moonbr_io_errmsg();
  1134. close(listener->fd);
  1135. listener->fd = -1;
  1136. close(fd);
  1137. luaL_error(L, "Unexpected error in fcntl call: %s", errmsg);
  1138. }
  1139. }
  1140. #else
  1141. fd = accept4(listener->fd, NULL, NULL, SOCK_CLOEXEC);
  1142. #endif
  1143. if (fd < 0) {
  1144. if (nonblocking && (errno == EAGAIN || errno == EWOULDBLOCK)) {
  1145. lua_pushboolean(L, 0);
  1146. lua_pushliteral(L, "No incoming connection pending");
  1147. return 2;
  1148. } else if (errno != EINTR) {
  1149. moonbr_io_errmsg();
  1150. lua_pushnil(L);
  1151. lua_pushstring(L, errmsg);
  1152. return 2;
  1153. }
  1154. } else {
  1155. moonbr_io_pushhandle(L, fd);
  1156. return 1;
  1157. }
  1158. }
  1159. }
  1160. static int moonbr_io_accept(lua_State *L) {
  1161. return moonbr_io_accept_impl(L, 0);
  1162. }
  1163. static int moonbr_io_accept_nb(lua_State *L) {
  1164. return moonbr_io_accept_impl(L, 1);
  1165. }
  1166. static int moonbr_io_unlisten(lua_State *L) {
  1167. moonbr_io_listener_t *listener;
  1168. struct sockaddr_un addr;
  1169. socklen_t addrlen;
  1170. struct stat sb;
  1171. listener = luaL_checkudata(L, 1, MOONBR_IO_LISTENER_MT_REGKEY);
  1172. if (listener->fd < 0) luaL_error(L, "Attempt to close a closed listener");
  1173. addrlen = sizeof(addr);
  1174. if (getsockname(listener->fd, (struct sockaddr *)&addr, &addrlen)) addrlen = 0;
  1175. if (close(listener->fd)) {
  1176. moonbr_io_errmsg();
  1177. listener->fd = -1;
  1178. if (addrlen && addrlen <= sizeof(addr)) {
  1179. if (stat(addr.sun_path, &sb) == 0) {
  1180. if (S_ISSOCK(sb.st_mode)) unlink(addr.sun_path);
  1181. }
  1182. }
  1183. lua_pushnil(L);
  1184. lua_pushstring(L, errmsg);
  1185. return 2;
  1186. }
  1187. listener->fd = -1;
  1188. if (addrlen && addrlen <= sizeof(addr)) {
  1189. if (stat(addr.sun_path, &sb) == 0) {
  1190. if (S_ISSOCK(sb.st_mode)) unlink(addr.sun_path);
  1191. }
  1192. }
  1193. lua_pushboolean(L, 1);
  1194. return 1;
  1195. }
  1196. static int moonbr_io_listenergc(lua_State *L) {
  1197. moonbr_io_listener_t *listener;
  1198. listener = luaL_checkudata(L, 1, MOONBR_IO_LISTENER_MT_REGKEY);
  1199. if (listener->fd >= 0) close(listener->fd);
  1200. listener->fd = -1;
  1201. return 0;
  1202. }
  1203. static int moonbr_io_exec(lua_State *L) {
  1204. char **argv;
  1205. int i, argc;
  1206. int sockin[2], sockout[2], sockerr[2];
  1207. volatile int errorcond = 0;
  1208. volatile char errmsgbuf[MOONBR_IO_MAXSTRERRORLEN] = MOONBR_IO_STRERROR_R_MSG;
  1209. moonbr_io_child_t *child;
  1210. argc = lua_gettop(L);
  1211. argv = lua_newuserdata(L, (argc + 1) * sizeof(char *));
  1212. for (i=0; i<argc; i++) argv[i] = (char *)luaL_checkstring(L, i+1);
  1213. argv[argc] = NULL;
  1214. child = lua_newuserdata(L, sizeof(moonbr_io_child_t));
  1215. child->pid = 0;
  1216. lua_newtable(L);
  1217. lua_setuservalue(L, -2);
  1218. luaL_getmetatable(L, MOONBR_IO_CHILD_MT_REGKEY);
  1219. lua_setmetatable(L, -2);
  1220. if (socketpair(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, sockin)) {
  1221. moonbr_io_errmsg();
  1222. lua_pushnil(L);
  1223. lua_pushfstring(L, "Could not create socket pair: %s", errmsg);
  1224. return 2;
  1225. }
  1226. if (socketpair(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, sockout)) {
  1227. moonbr_io_errmsg();
  1228. close(sockin[0]);
  1229. close(sockin[1]);
  1230. lua_pushnil(L);
  1231. lua_pushfstring(L, "Could not create socket pair: %s", errmsg);
  1232. return 2;
  1233. }
  1234. if (socketpair(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, sockerr)) {
  1235. moonbr_io_errmsg();
  1236. close(sockin[0]);
  1237. close(sockin[1]);
  1238. close(sockout[0]);
  1239. close(sockout[1]);
  1240. lua_pushnil(L);
  1241. lua_pushfstring(L, "Could not create socket pair: %s", errmsg);
  1242. return 2;
  1243. }
  1244. child->pid = vfork();
  1245. if (child->pid == -1) {
  1246. moonbr_io_errmsg();
  1247. close(sockin[0]);
  1248. close(sockin[1]);
  1249. close(sockout[0]);
  1250. close(sockout[1]);
  1251. close(sockerr[0]);
  1252. close(sockerr[1]);
  1253. lua_pushnil(L);
  1254. lua_pushfstring(L, "Could not fork: %s", errmsg);
  1255. return 2;
  1256. }
  1257. if (!child->pid) {
  1258. if (dup2(sockin[1], 0) == -1) goto moonbr_io_exec_error1;
  1259. if (dup2(sockout[1], 1) == -1) goto moonbr_io_exec_error1;
  1260. if (dup2(sockerr[1], 2) == -1) goto moonbr_io_exec_error1;
  1261. closefrom(4);
  1262. if (fcntl(0, F_SETFD, 0) == -1) goto moonbr_io_exec_error1;
  1263. if (fcntl(1, F_SETFD, 0) == -1) goto moonbr_io_exec_error1;
  1264. if (fcntl(2, F_SETFD, 0) == -1) goto moonbr_io_exec_error1;
  1265. if (execvp(argv[0], argv)) {
  1266. errorcond = 2;
  1267. strerror_r(errno, (char *)errmsgbuf, MOONBR_IO_MAXSTRERRORLEN);
  1268. _exit(0);
  1269. }
  1270. moonbr_io_exec_error1:
  1271. errorcond = 1;
  1272. strerror_r(errno, (char *)errmsgbuf, MOONBR_IO_MAXSTRERRORLEN);
  1273. _exit(0);
  1274. }
  1275. close(sockin[1]);
  1276. close(sockout[1]);
  1277. close(sockerr[1]);
  1278. if (errorcond) {
  1279. int status;
  1280. close(sockin[0]);
  1281. close(sockout[0]);
  1282. close(sockerr[0]);
  1283. while (waitpid(child->pid, &status, 0) == -1) {
  1284. if (errno != EINTR) {
  1285. moonbr_io_errmsg();
  1286. luaL_error(L, "Error in waitpid call after unsuccessful exec: %s", errmsg);
  1287. }
  1288. }
  1289. child->pid = 0;
  1290. lua_pushnil(L);
  1291. if (errorcond == 2) lua_pushfstring(L, "Could not execute: %s", errmsgbuf);
  1292. else lua_pushfstring(L, "Error in fork: %s", errmsgbuf);
  1293. return 2;
  1294. }
  1295. lua_pushcfunction(L, moonbr_io_pushhandle_impl);
  1296. lua_pushlightuserdata(L, &sockin[0]);
  1297. if (lua_pcall(L, 1, 1, 0)) {
  1298. if (sockin[0] != -1) close(sockin[0]);
  1299. close(sockout[0]);
  1300. close(sockerr[0]);
  1301. goto moonbr_io_exec_error2;
  1302. }
  1303. lua_setfield(L, -2, "stdin");
  1304. lua_pushcfunction(L, moonbr_io_pushhandle_impl);
  1305. lua_pushlightuserdata(L, &sockout[0]);
  1306. if (lua_pcall(L, 1, 1, 0)) {
  1307. if (sockout[0] != -1) close(sockout[0]);
  1308. close(sockerr[0]);
  1309. goto moonbr_io_exec_error2;
  1310. }
  1311. lua_setfield(L, -2, "stdout");
  1312. lua_pushcfunction(L, moonbr_io_pushhandle_impl);
  1313. lua_pushlightuserdata(L, &sockerr[0]);
  1314. if (lua_pcall(L, 1, 1, 0)) {
  1315. if (sockerr[0] != -1) close(sockerr[0]);
  1316. goto moonbr_io_exec_error2;
  1317. }
  1318. lua_setfield(L, -2, "stderr");
  1319. return 1;
  1320. moonbr_io_exec_error2:
  1321. {
  1322. int status;
  1323. while (waitpid(child->pid, &status, 0) == -1) {
  1324. if (errno != EINTR) {
  1325. moonbr_io_errmsg();
  1326. luaL_error(L, "Error in waitpid call after error creating socket handles: %s", errmsg);
  1327. }
  1328. }
  1329. }
  1330. child->pid = 0;
  1331. return lua_error(L);
  1332. }
  1333. static int moonbr_io_childindex(lua_State *L) {
  1334. luaL_checkudata(L, 1, MOONBR_IO_CHILD_MT_REGKEY);
  1335. luaL_checkany(L, 2);
  1336. lua_getuservalue(L, 1);
  1337. lua_pushvalue(L, 2);
  1338. lua_gettable(L, -2);
  1339. if (lua_isnil(L, -1)) {
  1340. luaL_getmetatable(L, MOONBR_IO_CHILD_PT_REGKEY);
  1341. lua_pushvalue(L, 2);
  1342. lua_gettable(L, -2);
  1343. }
  1344. return 1;
  1345. }
  1346. static int moonbr_io_childnewindex(lua_State *L) {
  1347. luaL_checkudata(L, 1, MOONBR_IO_CHILD_MT_REGKEY);
  1348. luaL_checkany(L, 2);
  1349. luaL_checkany(L, 3);
  1350. lua_getuservalue(L, 1);
  1351. lua_pushvalue(L, 2);
  1352. lua_pushvalue(L, 3);
  1353. lua_settable(L, -3);
  1354. return 0;
  1355. }
  1356. static int moonbr_io_childgc(lua_State *L) {
  1357. moonbr_io_child_t *child;
  1358. child = luaL_checkudata(L, 1, MOONBR_IO_CHILD_MT_REGKEY);
  1359. if (child->pid) {
  1360. int status;
  1361. if (kill(child->pid, SIGKILL)) {
  1362. moonbr_io_errmsg();
  1363. luaL_error(L, "Error in kill call during garbage collection: %s", errmsg);
  1364. }
  1365. while (waitpid(child->pid, &status, 0) == -1) {
  1366. if (errno != EINTR) {
  1367. moonbr_io_errmsg();
  1368. luaL_error(L, "Error in waitpid call during garbage collection: %s", errmsg);
  1369. }
  1370. }
  1371. }
  1372. return 0;
  1373. }
  1374. static int moonbr_io_kill(lua_State *L) {
  1375. moonbr_io_child_t *child;
  1376. int sig;
  1377. child = luaL_checkudata(L, 1, MOONBR_IO_CHILD_MT_REGKEY);
  1378. sig = luaL_optinteger(L, 2, SIGTERM);
  1379. if (!child->pid) luaL_error(L, "Attempt to kill an already collected child process");
  1380. if (kill(child->pid, sig)) {
  1381. moonbr_io_errmsg();
  1382. luaL_error(L, "Error in kill call: %s", errmsg);
  1383. }
  1384. lua_settop(L, 1);
  1385. return 1;
  1386. }
  1387. static int moonbr_io_wait_impl(lua_State *L, int nonblocking) {
  1388. moonbr_io_child_t *child;
  1389. pid_t waitedpid;
  1390. int status;
  1391. child = luaL_checkudata(L, 1, MOONBR_IO_CHILD_MT_REGKEY);
  1392. if (!child->pid) luaL_error(L, "Attempt to wait for an already collected child process");
  1393. while ((waitedpid = waitpid(child->pid, &status, nonblocking ? WNOHANG : 0)) == -1) {
  1394. if (errno != EINTR) {
  1395. moonbr_io_errmsg();
  1396. luaL_error(L, "Error in waitpid call: %s", errmsg);
  1397. }
  1398. }
  1399. if (!waitedpid) {
  1400. lua_pushboolean(L, 0);
  1401. lua_pushliteral(L, "Process is still running");
  1402. return 2;
  1403. } else {
  1404. child->pid = 0;
  1405. if (WIFEXITED(status)) {
  1406. lua_pushinteger(L, WEXITSTATUS(status));
  1407. } else if (WIFSIGNALED(status)) {
  1408. lua_pushinteger(L, -WTERMSIG(status));
  1409. } else {
  1410. luaL_error(L, "Unexpected status value returned by waitpid call");
  1411. }
  1412. return 1;
  1413. }
  1414. }
  1415. static int moonbr_io_wait(lua_State *L) {
  1416. return moonbr_io_wait_impl(L, 0);
  1417. }
  1418. static int moonbr_io_wait_nb(lua_State *L) {
  1419. return moonbr_io_wait_impl(L, 1);
  1420. }
  1421. #if LUA_VERSION_NUM >= 503
  1422. static int moonbr_io_wait_cont(lua_State *L, int status, lua_KContext ctx) {
  1423. #else
  1424. static int moonbr_io_wait_cont(lua_State *L) {
  1425. #endif
  1426. #if !(LUA_VERSION_NUM >= 503)
  1427. int ctx = 0;
  1428. lua_getctx(L, &ctx);
  1429. #endif
  1430. while (1) {
  1431. lua_pushcfunction(L, moonbr_io_wait_nb);
  1432. lua_pushvalue(L, 1);
  1433. lua_call(L, 1, 1);
  1434. if (!lua_isnil(L, -1)) break;
  1435. lua_pushvalue(L, 2);
  1436. lua_callk(L, 0, 0, ctx, moonbr_io_wait_cont);
  1437. }
  1438. return 1;
  1439. }
  1440. static int moonbr_io_wait_call(lua_State *L) {
  1441. lua_settop(L, 2);
  1442. #if LUA_VERSION_NUM >= 503
  1443. return moonbr_io_wait_cont(L, 0, 0);
  1444. #else
  1445. return moonbr_io_wait_cont(L);
  1446. #endif
  1447. }
  1448. moonbr_io_yield_wrapper(moonbr_io_wait_yield, moonbr_io_wait_call);
  1449. static int moonbr_io_poll(lua_State *L) {
  1450. moonbr_io_handle_t *handle;
  1451. moonbr_io_listener_t *listener;
  1452. int fd, isnum;
  1453. int nfds = 0;
  1454. fd_set readfds, writefds, exceptfds;
  1455. struct timeval timeout = {0, };
  1456. int status;
  1457. FD_ZERO(&readfds);
  1458. FD_ZERO(&writefds);
  1459. FD_ZERO(&exceptfds);
  1460. if (!lua_isnoneornil(L, 1)) {
  1461. luaL_checktype(L, 1, LUA_TTABLE);
  1462. for (lua_pushnil(L); lua_next(L, 1); lua_pop(L, 1)) {
  1463. if (lua_toboolean(L, -1)) {
  1464. handle = luaL_testudata(L, -2, MOONBR_IO_HANDLE_MT_REGKEY);
  1465. if (handle) {
  1466. if (handle->closed) luaL_error(L, "Attempt to poll a closed connection");
  1467. fd = handle->fd;
  1468. if (
  1469. fd < 0 || /* fake EOF to simulate shutdown if fd < 0 */
  1470. handle->readbufin != handle->readbufout /* data pending in buffer */
  1471. ) {
  1472. lua_pushboolean(L, 1);
  1473. return 1;
  1474. }
  1475. } else {
  1476. listener = luaL_testudata(L, -2, MOONBR_IO_LISTENER_MT_REGKEY);
  1477. if (listener) {
  1478. fd = listener->fd;
  1479. if (fd < 0) luaL_error(L, "Attempt to poll a closed listener");
  1480. } else {
  1481. fd = lua_tointegerx(L, -2, &isnum);
  1482. if (!isnum) luaL_error(L, "Expected integer (file descriptor), I/O handle, or listener in table key");
  1483. }
  1484. }
  1485. if (fd < 0 || fd >= FD_SETSIZE) luaL_error(L, "File descriptor out of valid range");
  1486. FD_SET(fd, &readfds);
  1487. if (fd+1 > nfds) nfds = fd+1;
  1488. }
  1489. }
  1490. }
  1491. if (!lua_isnoneornil(L, 2)) {
  1492. luaL_checktype(L, 2, LUA_TTABLE);
  1493. for (lua_pushnil(L); lua_next(L, 2); lua_pop(L, 1)) {
  1494. if (lua_toboolean(L, -1)) {
  1495. handle = luaL_testudata(L, -2, MOONBR_IO_HANDLE_MT_REGKEY);
  1496. if (handle) {
  1497. if (handle->closed) luaL_error(L, "Attempt to poll a closed connection");
  1498. if (handle->finished) luaL_error(L, "Attempt to write-poll a finished connection");
  1499. fd = handle->fd;
  1500. } else {
  1501. listener = luaL_testudata(L, -2, MOONBR_IO_LISTENER_MT_REGKEY);
  1502. if (listener) luaL_error(L, "Attempt to write-poll a listener");
  1503. fd = lua_tointegerx(L, -2, &isnum);
  1504. if (!isnum) luaL_error(L, "Expected integer (file descriptor) or I/O handle in table key");
  1505. }
  1506. if (fd < 0 || fd >= FD_SETSIZE) luaL_error(L, "File descriptor out of valid range");
  1507. FD_SET(fd, &writefds);
  1508. if (fd+1 > nfds) nfds = fd+1;
  1509. }
  1510. }
  1511. }
  1512. if (!lua_isnoneornil(L, 3)) {
  1513. lua_Number n;
  1514. n = lua_tonumberx(L, 3, &isnum);
  1515. if (isnum && n<0) {
  1516. lua_pushboolean(L, 0);
  1517. lua_pushliteral(L, "Negative timeout");
  1518. return 2;
  1519. } else if (isnum && n>=0 && n<100000000) {
  1520. timeout.tv_sec = n;
  1521. timeout.tv_usec = 1e6 * (n - timeout.tv_sec);
  1522. } else {
  1523. luaL_argcheck(L, 0, 3, "not a valid timeout");
  1524. }
  1525. status = select(nfds, &readfds, &writefds, &exceptfds, &timeout);
  1526. } else {
  1527. status = select(nfds, &readfds, &writefds, &exceptfds, NULL);
  1528. }
  1529. if (status == -1) {
  1530. if (errno == EINTR) {
  1531. lua_pushnil(L);
  1532. lua_pushliteral(L, "Signal received while polling file descriptors");
  1533. return 2;
  1534. } else {
  1535. moonbr_io_errmsg();
  1536. return luaL_error(L, "Unexpected error during \"select\" system call: %s", errmsg);
  1537. }
  1538. } else if (status == 0) {
  1539. lua_pushboolean(L, 0);
  1540. lua_pushliteral(L, "Timeout while polling file descriptors");
  1541. return 2;
  1542. } else {
  1543. lua_pushboolean(L, 1);
  1544. return 1;
  1545. }
  1546. }
  1547. static int moonbr_io_timeref(lua_State *L) {
  1548. lua_Number sub;
  1549. struct timespec tp;
  1550. sub = luaL_optnumber(L, 1, 0);
  1551. if (clock_gettime(CLOCK_MONOTONIC, &tp)) {
  1552. return luaL_error(L, "Could not access CLOCK_MONOTONIC");
  1553. }
  1554. lua_pushnumber(L, tp.tv_sec + tp.tv_nsec / 1.0e9 - sub);
  1555. return 1;
  1556. }
  1557. static const struct luaL_Reg moonbr_io_handle_methods[] = {
  1558. {"read", moonbr_io_read},
  1559. {"read_nb", moonbr_io_read_nb},
  1560. {"read_call", moonbr_io_read_call},
  1561. {"read_yield", moonbr_io_read_yield},
  1562. {"drain", moonbr_io_drain},
  1563. {"drain_nb", moonbr_io_drain_nb},
  1564. {"drain_call", moonbr_io_drain_call},
  1565. {"drain_yield", moonbr_io_drain_yield},
  1566. {"write", moonbr_io_write},
  1567. {"write_nb", moonbr_io_write_nb},
  1568. {"write_call", moonbr_io_write_call},
  1569. {"write_yield", moonbr_io_write_yield},
  1570. {"flush", moonbr_io_flush},
  1571. {"flush_nb", moonbr_io_flush_nb},
  1572. {"flush_call", moonbr_io_flush_call},
  1573. {"flush_yield", moonbr_io_flush_yield},
  1574. {"finish", moonbr_io_finish},
  1575. {"close", moonbr_io_close},
  1576. {"reset", moonbr_io_reset},
  1577. {NULL, NULL}
  1578. };
  1579. static const struct luaL_Reg moonbr_io_handle_metamethods[] = {
  1580. {"__index", moonbr_io_handleindex},
  1581. {"__newindex", moonbr_io_handlenewindex},
  1582. {"__gc", moonbr_io_handlegc},
  1583. {NULL, NULL}
  1584. };
  1585. static const struct luaL_Reg moonbr_io_listener_methods[] = {
  1586. {"accept", moonbr_io_accept},
  1587. {"accept_nb", moonbr_io_accept_nb},
  1588. {"close", moonbr_io_unlisten},
  1589. {NULL, NULL}
  1590. };
  1591. static const struct luaL_Reg moonbr_io_listener_metamethods[] = {
  1592. {"__gc", moonbr_io_listenergc},
  1593. {NULL, NULL}
  1594. };
  1595. static const struct luaL_Reg moonbr_io_child_methods[] = {
  1596. {"kill", moonbr_io_kill},
  1597. {"wait", moonbr_io_wait},
  1598. {"wait_nb", moonbr_io_wait_nb},
  1599. {"wait_call", moonbr_io_wait_call},
  1600. {"wait_yield", moonbr_io_wait_yield},
  1601. {NULL, NULL}
  1602. };
  1603. static const struct luaL_Reg moonbr_io_child_metamethods[] = {
  1604. {"__index", moonbr_io_childindex},
  1605. {"__newindex", moonbr_io_childnewindex},
  1606. {"__gc", moonbr_io_childgc},
  1607. {NULL, NULL}
  1608. };
  1609. static const struct luaL_Reg moonbr_io_module_funcs[] = {
  1610. {"localconnect", moonbr_io_localconnect},
  1611. {"localconnect_nb", moonbr_io_localconnect_nb},
  1612. {"tcpconnect", moonbr_io_tcpconnect},
  1613. {"tcpconnect_nb", moonbr_io_tcpconnect_nb},
  1614. {"locallisten", moonbr_io_locallisten},
  1615. {"tcplisten", moonbr_io_tcplisten},
  1616. {"exec", moonbr_io_exec},
  1617. {"poll", moonbr_io_poll},
  1618. {"timeref", moonbr_io_timeref},
  1619. {NULL, NULL}
  1620. };
  1621. int luaopen_moonbridge_io(lua_State *L) {
  1622. signal(SIGPIPE, SIG_IGN); /* generate I/O errors instead of signal 13 */
  1623. lua_newtable(L); // module
  1624. lua_newtable(L); // public metatable
  1625. lua_newtable(L); // handle methods
  1626. luaL_setfuncs(L, moonbr_io_handle_methods, 0);
  1627. lua_pushvalue(L, -1);
  1628. lua_setfield(L, -4, "handle_pt");
  1629. lua_setfield(L, -2, "__index");
  1630. lua_setfield(L, LUA_REGISTRYINDEX, MOONBR_IO_HANDLE_PUBLIC_MT_REGKEY);
  1631. lua_newtable(L); // handle metatable
  1632. luaL_setfuncs(L, moonbr_io_handle_metamethods, 0);
  1633. lua_pushvalue(L, -1);
  1634. lua_setfield(L, -3, "handle_mt");
  1635. lua_setfield(L, LUA_REGISTRYINDEX, MOONBR_IO_HANDLE_

Large files files are truncated, but you can click here to view the full file