unixdgram.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. /*=========================================================================*\
  2. * Unix domain socket dgram submodule
  3. * LuaSocket toolkit
  4. \*=========================================================================*/
  5. #include "luasocket.h"
  6. #include "auxiliar.h"
  7. #include "socket.h"
  8. #include "options.h"
  9. #include "unix.h"
  10. #include <string.h>
  11. #include <stdlib.h>
  12. #ifdef _WIN32
  13. #include <afunix.h>
  14. #else
  15. #include <sys/un.h>
  16. #endif
  17. #define UNIXDGRAM_DATAGRAMSIZE 8192
  18. /* provide a SUN_LEN macro if sys/un.h doesn't (e.g. Android) */
  19. #ifndef SUN_LEN
  20. #define SUN_LEN(ptr) \
  21. ((size_t) (((struct sockaddr_un *) 0)->sun_path) \
  22. + strlen ((ptr)->sun_path))
  23. #endif
  24. /*=========================================================================*\
  25. * Internal function prototypes
  26. \*=========================================================================*/
  27. static int global_create(lua_State *L);
  28. static int meth_connect(lua_State *L);
  29. static int meth_bind(lua_State *L);
  30. static int meth_send(lua_State *L);
  31. static int meth_receive(lua_State *L);
  32. static int meth_close(lua_State *L);
  33. static int meth_setoption(lua_State *L);
  34. static int meth_settimeout(lua_State *L);
  35. static int meth_gettimeout(lua_State *L);
  36. static int meth_getfd(lua_State *L);
  37. static int meth_setfd(lua_State *L);
  38. static int meth_dirty(lua_State *L);
  39. static int meth_receivefrom(lua_State *L);
  40. static int meth_sendto(lua_State *L);
  41. static int meth_getsockname(lua_State *L);
  42. static const char *unixdgram_tryconnect(p_unix un, const char *path);
  43. static const char *unixdgram_trybind(p_unix un, const char *path);
  44. /* unixdgram object methods */
  45. static luaL_Reg unixdgram_methods[] = {
  46. {"__gc", meth_close},
  47. {"__tostring", auxiliar_tostring},
  48. {"bind", meth_bind},
  49. {"close", meth_close},
  50. {"connect", meth_connect},
  51. {"dirty", meth_dirty},
  52. {"getfd", meth_getfd},
  53. {"send", meth_send},
  54. {"sendto", meth_sendto},
  55. {"receive", meth_receive},
  56. {"receivefrom", meth_receivefrom},
  57. {"setfd", meth_setfd},
  58. {"setoption", meth_setoption},
  59. {"setpeername", meth_connect},
  60. {"setsockname", meth_bind},
  61. {"getsockname", meth_getsockname},
  62. {"settimeout", meth_settimeout},
  63. {"gettimeout", meth_gettimeout},
  64. {NULL, NULL}
  65. };
  66. /* socket option handlers */
  67. static t_opt optset[] = {
  68. {"reuseaddr", opt_set_reuseaddr},
  69. {NULL, NULL}
  70. };
  71. /* functions in library namespace */
  72. static luaL_Reg func[] = {
  73. {"dgram", global_create},
  74. {NULL, NULL}
  75. };
  76. /*-------------------------------------------------------------------------*\
  77. * Initializes module
  78. \*-------------------------------------------------------------------------*/
  79. int unixdgram_open(lua_State *L)
  80. {
  81. /* create classes */
  82. auxiliar_newclass(L, "unixdgram{connected}", unixdgram_methods);
  83. auxiliar_newclass(L, "unixdgram{unconnected}", unixdgram_methods);
  84. /* create class groups */
  85. auxiliar_add2group(L, "unixdgram{connected}", "unixdgram{any}");
  86. auxiliar_add2group(L, "unixdgram{unconnected}", "unixdgram{any}");
  87. auxiliar_add2group(L, "unixdgram{connected}", "select{able}");
  88. auxiliar_add2group(L, "unixdgram{unconnected}", "select{able}");
  89. luaL_setfuncs(L, func, 0);
  90. return 0;
  91. }
  92. /*=========================================================================*\
  93. * Lua methods
  94. \*=========================================================================*/
  95. static const char *unixdgram_strerror(int err)
  96. {
  97. /* a 'closed' error on an unconnected means the target address was not
  98. * accepted by the transport layer */
  99. if (err == IO_CLOSED) return "refused";
  100. else return socket_strerror(err);
  101. }
  102. static int meth_send(lua_State *L)
  103. {
  104. p_unix un = (p_unix) auxiliar_checkclass(L, "unixdgram{connected}", 1);
  105. p_timeout tm = &un->tm;
  106. size_t count, sent = 0;
  107. int err;
  108. const char *data = luaL_checklstring(L, 2, &count);
  109. timeout_markstart(tm);
  110. err = socket_send(&un->sock, data, count, &sent, tm);
  111. if (err != IO_DONE) {
  112. lua_pushnil(L);
  113. lua_pushstring(L, unixdgram_strerror(err));
  114. return 2;
  115. }
  116. lua_pushnumber(L, (lua_Number) sent);
  117. return 1;
  118. }
  119. /*-------------------------------------------------------------------------*\
  120. * Send data through unconnected unixdgram socket
  121. \*-------------------------------------------------------------------------*/
  122. static int meth_sendto(lua_State *L)
  123. {
  124. p_unix un = (p_unix) auxiliar_checkclass(L, "unixdgram{unconnected}", 1);
  125. size_t count, sent = 0;
  126. const char *data = luaL_checklstring(L, 2, &count);
  127. const char *path = luaL_checkstring(L, 3);
  128. p_timeout tm = &un->tm;
  129. int err;
  130. struct sockaddr_un remote;
  131. size_t len = strlen(path);
  132. if (len >= sizeof(remote.sun_path)) {
  133. lua_pushnil(L);
  134. lua_pushstring(L, "path too long");
  135. return 2;
  136. }
  137. memset(&remote, 0, sizeof(remote));
  138. strcpy(remote.sun_path, path);
  139. remote.sun_family = AF_UNIX;
  140. timeout_markstart(tm);
  141. #ifdef UNIX_HAS_SUN_LEN
  142. remote.sun_len = sizeof(remote.sun_family) + sizeof(remote.sun_len)
  143. + len + 1;
  144. err = socket_sendto(&un->sock, data, count, &sent, (SA *) &remote, remote.sun_len, tm);
  145. #else
  146. err = socket_sendto(&un->sock, data, count, &sent, (SA *) &remote,
  147. sizeof(remote.sun_family) + len, tm);
  148. #endif
  149. if (err != IO_DONE) {
  150. lua_pushnil(L);
  151. lua_pushstring(L, unixdgram_strerror(err));
  152. return 2;
  153. }
  154. lua_pushnumber(L, (lua_Number) sent);
  155. return 1;
  156. }
  157. static int meth_receive(lua_State *L) {
  158. p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
  159. char buf[UNIXDGRAM_DATAGRAMSIZE];
  160. size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf));
  161. char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf;
  162. int err;
  163. p_timeout tm = &un->tm;
  164. timeout_markstart(tm);
  165. if (!dgram) {
  166. lua_pushnil(L);
  167. lua_pushliteral(L, "out of memory");
  168. return 2;
  169. }
  170. err = socket_recv(&un->sock, dgram, wanted, &got, tm);
  171. /* Unlike STREAM, recv() of zero is not closed, but a zero-length packet. */
  172. if (err != IO_DONE && err != IO_CLOSED) {
  173. lua_pushnil(L);
  174. lua_pushstring(L, unixdgram_strerror(err));
  175. if (wanted > sizeof(buf)) free(dgram);
  176. return 2;
  177. }
  178. lua_pushlstring(L, dgram, got);
  179. if (wanted > sizeof(buf)) free(dgram);
  180. return 1;
  181. }
  182. /*-------------------------------------------------------------------------*\
  183. * Receives data and sender from a DGRAM socket
  184. \*-------------------------------------------------------------------------*/
  185. static int meth_receivefrom(lua_State *L) {
  186. p_unix un = (p_unix) auxiliar_checkclass(L, "unixdgram{unconnected}", 1);
  187. char buf[UNIXDGRAM_DATAGRAMSIZE];
  188. size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf));
  189. char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf;
  190. struct sockaddr_un addr;
  191. socklen_t addr_len = sizeof(addr);
  192. int err;
  193. p_timeout tm = &un->tm;
  194. timeout_markstart(tm);
  195. if (!dgram) {
  196. lua_pushnil(L);
  197. lua_pushliteral(L, "out of memory");
  198. return 2;
  199. }
  200. addr.sun_path[0] = '\0';
  201. err = socket_recvfrom(&un->sock, dgram, wanted, &got, (SA *) &addr,
  202. &addr_len, tm);
  203. /* Unlike STREAM, recv() of zero is not closed, but a zero-length packet. */
  204. if (err != IO_DONE && err != IO_CLOSED) {
  205. lua_pushnil(L);
  206. lua_pushstring(L, unixdgram_strerror(err));
  207. if (wanted > sizeof(buf)) free(dgram);
  208. return 2;
  209. }
  210. lua_pushlstring(L, dgram, got);
  211. /* the path may be empty, when client send without bind */
  212. lua_pushstring(L, addr.sun_path);
  213. if (wanted > sizeof(buf)) free(dgram);
  214. return 2;
  215. }
  216. /*-------------------------------------------------------------------------*\
  217. * Just call option handler
  218. \*-------------------------------------------------------------------------*/
  219. static int meth_setoption(lua_State *L) {
  220. p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
  221. return opt_meth_setoption(L, optset, &un->sock);
  222. }
  223. /*-------------------------------------------------------------------------*\
  224. * Select support methods
  225. \*-------------------------------------------------------------------------*/
  226. static int meth_getfd(lua_State *L) {
  227. p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
  228. lua_pushnumber(L, (int) un->sock);
  229. return 1;
  230. }
  231. /* this is very dangerous, but can be handy for those that are brave enough */
  232. static int meth_setfd(lua_State *L) {
  233. p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
  234. un->sock = (t_socket) luaL_checknumber(L, 2);
  235. return 0;
  236. }
  237. static int meth_dirty(lua_State *L) {
  238. p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
  239. (void) un;
  240. lua_pushboolean(L, 0);
  241. return 1;
  242. }
  243. /*-------------------------------------------------------------------------*\
  244. * Binds an object to an address
  245. \*-------------------------------------------------------------------------*/
  246. static const char *unixdgram_trybind(p_unix un, const char *path) {
  247. struct sockaddr_un local;
  248. size_t len = strlen(path);
  249. if (len >= sizeof(local.sun_path)) return "path too long";
  250. memset(&local, 0, sizeof(local));
  251. strcpy(local.sun_path, path);
  252. local.sun_family = AF_UNIX;
  253. size_t addrlen = SUN_LEN(&local);
  254. #ifdef UNIX_HAS_SUN_LEN
  255. local.sun_len = addrlen + 1;
  256. #endif
  257. int err = socket_bind(&un->sock, (SA *) &local, addrlen);
  258. if (err != IO_DONE) socket_destroy(&un->sock);
  259. return socket_strerror(err);
  260. }
  261. static int meth_bind(lua_State *L)
  262. {
  263. p_unix un = (p_unix) auxiliar_checkclass(L, "unixdgram{unconnected}", 1);
  264. const char *path = luaL_checkstring(L, 2);
  265. const char *err = unixdgram_trybind(un, path);
  266. if (err) {
  267. lua_pushnil(L);
  268. lua_pushstring(L, err);
  269. return 2;
  270. }
  271. lua_pushnumber(L, 1);
  272. return 1;
  273. }
  274. static int meth_getsockname(lua_State *L)
  275. {
  276. p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
  277. struct sockaddr_un peer = {0};
  278. socklen_t peer_len = sizeof(peer);
  279. if (getsockname(un->sock, (SA *) &peer, &peer_len) < 0) {
  280. lua_pushnil(L);
  281. lua_pushstring(L, socket_strerror(errno));
  282. return 2;
  283. }
  284. lua_pushstring(L, peer.sun_path);
  285. return 1;
  286. }
  287. /*-------------------------------------------------------------------------*\
  288. * Turns a master unixdgram object into a client object.
  289. \*-------------------------------------------------------------------------*/
  290. static const char *unixdgram_tryconnect(p_unix un, const char *path)
  291. {
  292. struct sockaddr_un remote;
  293. size_t len = strlen(path);
  294. if (len >= sizeof(remote.sun_path)) return "path too long";
  295. memset(&remote, 0, sizeof(remote));
  296. strcpy(remote.sun_path, path);
  297. remote.sun_family = AF_UNIX;
  298. timeout_markstart(&un->tm);
  299. size_t addrlen = SUN_LEN(&remote);
  300. #ifdef UNIX_HAS_SUN_LEN
  301. remote.sun_len = addrlen + 1;
  302. #endif
  303. int err = socket_connect(&un->sock, (SA *) &remote, addrlen, &un->tm);
  304. if (err != IO_DONE) socket_destroy(&un->sock);
  305. return socket_strerror(err);
  306. }
  307. static int meth_connect(lua_State *L)
  308. {
  309. p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
  310. const char *path = luaL_checkstring(L, 2);
  311. const char *err = unixdgram_tryconnect(un, path);
  312. if (err) {
  313. lua_pushnil(L);
  314. lua_pushstring(L, err);
  315. return 2;
  316. }
  317. /* turn unconnected object into a connected object */
  318. auxiliar_setclass(L, "unixdgram{connected}", 1);
  319. lua_pushnumber(L, 1);
  320. return 1;
  321. }
  322. /*-------------------------------------------------------------------------*\
  323. * Closes socket used by object
  324. \*-------------------------------------------------------------------------*/
  325. static int meth_close(lua_State *L)
  326. {
  327. p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
  328. socket_destroy(&un->sock);
  329. lua_pushnumber(L, 1);
  330. return 1;
  331. }
  332. /*-------------------------------------------------------------------------*\
  333. * Just call tm methods
  334. \*-------------------------------------------------------------------------*/
  335. static int meth_settimeout(lua_State *L)
  336. {
  337. p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
  338. return timeout_meth_settimeout(L, &un->tm);
  339. }
  340. static int meth_gettimeout(lua_State *L)
  341. {
  342. p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
  343. return timeout_meth_gettimeout(L, &un->tm);
  344. }
  345. /*=========================================================================*\
  346. * Library functions
  347. \*=========================================================================*/
  348. /*-------------------------------------------------------------------------*\
  349. * Creates a master unixdgram object
  350. \*-------------------------------------------------------------------------*/
  351. static int global_create(lua_State *L)
  352. {
  353. t_socket sock;
  354. int err = socket_create(&sock, AF_UNIX, SOCK_DGRAM, 0);
  355. /* try to allocate a system socket */
  356. if (err == IO_DONE) {
  357. /* allocate unixdgram object */
  358. p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix));
  359. /* set its type as master object */
  360. auxiliar_setclass(L, "unixdgram{unconnected}", -1);
  361. /* initialize remaining structure fields */
  362. socket_setnonblocking(&sock);
  363. un->sock = sock;
  364. io_init(&un->io, (p_send) socket_send, (p_recv) socket_recv,
  365. (p_error) socket_ioerror, &un->sock);
  366. timeout_init(&un->tm, -1, -1);
  367. buffer_init(&un->buf, &un->io, &un->tm);
  368. return 1;
  369. } else {
  370. lua_pushnil(L);
  371. lua_pushstring(L, socket_strerror(err));
  372. return 2;
  373. }
  374. }