minisock.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  1. // Copyright (c) 2018 Phil Leblanc -- see LICENSE file
  2. // ---------------------------------------------------------------------
  3. /*
  4. minisock - A minimal Lua socket library for unix / tcp / udp connections
  5. Functions:
  6. bind create a socket; bind it to a host address and port; listen
  7. accept accept incoming connections
  8. connect create a socket; connect to a (host, port)
  9. write write to an open connection
  10. read read from an open connection (with a timeout)
  11. close close a socket
  12. getpeername get the address of the peer a socket is connected to
  13. getsockname get the address a socket is bound to
  14. getaddrinfo get a list of addresses corresponding to a hostname and port
  15. getnameinfo get the hostname and port for a socket
  16. msleep sleep for some time in milliseconds
  17. bind() and connect() use raw sockaddr structures passed as a string.
  18. Hostname/port translation to a sockaddr is left to the application.
  19. It can be done with function getaddrinfo().
  20. The sockaddr structure, returned as a string by getpeername, getsockname,
  21. bind, accept and connect (second return value), is the raw, binary value.
  22. It can be parsed by getnameinfo.
  23. sockaddr strings can also easily be parsed with string.unpack:
  24. eg. for a IPv4 address:
  25. family, port, ip1, ip2, ip3, ip4 = string.unpack("<H>HBBBB", sockaddr)
  26. ipaddr = table.concat({ip1, ip2, ip3, ip4}, '.')
  27. */
  28. // ---------------------------------------------------------------------
  29. #include <sys/types.h>
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <unistd.h>
  33. #include <string.h>
  34. #include <sys/socket.h>
  35. #include <netdb.h>
  36. #include <poll.h>
  37. #include <errno.h>
  38. // for ll_msleep()
  39. #include <time.h>
  40. #include "lua.h"
  41. #include "lauxlib.h"
  42. #include "lualib.h"
  43. // ---------------------------------------------------------------------
  44. #define ll_VERSION "0.5"
  45. #define BUFSIZE 8192
  46. #define BACKLOG 32
  47. #define UDPMAXSIZE 2048
  48. #define ADDRMAXSIZE 128
  49. // default timeout: 10 seconds
  50. #define DEFAULT_TIMEOUT 10000
  51. int ll_bind(lua_State *L) {
  52. // create a server socket, bind, then listen
  53. // Lua args: server sockaddr as a binary string
  54. // return server socket file descriptor as integer or nil, errmsg
  55. //
  56. const char * addr;
  57. size_t addr_len;
  58. int sfd;
  59. int r;
  60. int family; // AF_UNIX=1, AF_INET=2, AF_INET6=10
  61. addr = luaL_checklstring(L, 1, &addr_len);
  62. family = (int) addr[0]; // first byte of sockaddr
  63. sfd = socket(family, SOCK_STREAM, 0); // 0 for default protocol
  64. if (sfd < 0) {
  65. lua_pushnil (L);
  66. lua_pushfstring (L, "socket() error %d", errno);
  67. return 2;
  68. }
  69. // set REUSEADDR option if socket is AF_INET[6]
  70. int reuseopt = 1;
  71. if (family == 2 || family == 10) {
  72. setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuseopt,
  73. sizeof(int));
  74. }
  75. r = bind(sfd, (struct sockaddr *) addr, addr_len);
  76. if (r < 0) {
  77. close(sfd);
  78. lua_pushnil (L);
  79. lua_pushfstring (L, "bind error %d", errno);
  80. return 2;
  81. }
  82. r = listen(sfd, BACKLOG);
  83. if (r < 0) {
  84. lua_pushnil (L);
  85. lua_pushfstring (L, "listen error: %d", errno);
  86. return 2;
  87. }
  88. // success, return server socket fd
  89. lua_pushinteger (L, sfd);
  90. return 1;
  91. } //ll_bind
  92. int ll_accept(lua_State *L) {
  93. // accept incoming connections on a server socket
  94. // Lua args: server socket file descriptor (as integer)
  95. // return client socket file descriptor (as integer) and
  96. // the raw client address as a string, or nil, errmsg
  97. int cfd, sfd;
  98. struct sockaddr_storage addr;
  99. socklen_t len = sizeof(addr); //enough for ip4 & 6 addr
  100. sfd = luaL_checkinteger(L, 1); // get server socket fd
  101. cfd = accept(sfd, (struct sockaddr *)&addr, &len);
  102. if (cfd == -1) {
  103. lua_pushnil (L);
  104. lua_pushfstring (L, "accept error: %d", errno);
  105. return 2;
  106. }
  107. //success, return client socket fd and client sockaddr
  108. lua_pushinteger (L, cfd);
  109. lua_pushlstring(L, (const char *)&addr, len);
  110. return 2;
  111. } //ll_accept
  112. int ll_connect(lua_State *L) {
  113. // connect to a host
  114. // Lua args: sockaddr as a binary string
  115. // return connection socket fd (as an integer) or nil, errmsg
  116. const char * addr;
  117. size_t addr_len;
  118. int cfd;
  119. int r;
  120. int family;
  121. addr = luaL_checklstring(L, 1, &addr_len);
  122. family = (int) addr[0];
  123. cfd = socket(family, SOCK_STREAM, 0); //0 = default protocol
  124. if (cfd < 0) {
  125. lua_pushnil (L);
  126. lua_pushfstring (L, "socket() error %d", errno);
  127. return 2;
  128. }
  129. r = connect(cfd, (struct sockaddr *) addr, addr_len);
  130. if (r < 0) {
  131. close(cfd);
  132. lua_pushnil (L);
  133. lua_pushfstring (L, "connect error %d", errno);
  134. return 2;
  135. }
  136. //success, return connection socket fd
  137. lua_pushinteger (L, cfd);
  138. return 1;
  139. } //ll_connect
  140. int ll_write(lua_State *L) {
  141. // Lua args:
  142. // fd: integer - socket descriptor
  143. // s: string - string containing bytes to send
  144. // idx: integer - index of the first byte in s to send
  145. // sbytes: integer - number of bytes to send
  146. // (adjusted to idx and string length if too large)
  147. int fd;
  148. int n;
  149. const char *s;
  150. size_t slen;
  151. int idx, sbytes;
  152. fd = luaL_checkinteger(L, 1); // get socket fd
  153. s = luaL_checklstring(L, 2, &slen); // string to write
  154. idx = luaL_optinteger(L, 3, 1); // starting index in string
  155. sbytes = luaL_optinteger(L, 4, 0); // number of bytes to write
  156. if (idx > slen) {
  157. luaL_error(L, "write: idx (%d) too large", idx);
  158. }
  159. if (sbytes == 0) { sbytes = slen; }
  160. if (idx + sbytes -1 > slen) { sbytes = slen - idx + 1; }
  161. n = write(fd, s+idx-1, sbytes);
  162. if (n < 0) { // write error
  163. lua_pushnil (L);
  164. lua_pushfstring (L, "write error: %d %d", n, errno);
  165. return 2;
  166. }
  167. //success, return number of bytes sent
  168. lua_pushinteger (L, n);
  169. return 1;
  170. } //ll_write
  171. int ll_read(lua_State *L) {
  172. // read bytes from a socket file descriptor
  173. // Lua args:
  174. // socket fd: integer
  175. // timeout: integer (in milliseconds)
  176. // (optional - defaults to DEFAULT_TIMEOUT)
  177. // reads at most BUFSIZE bytes.
  178. // return the bytes read as a string, or (nil, error msg)
  179. // on error or timeout
  180. //
  181. int fd;
  182. int n;
  183. luaL_Buffer b;
  184. char buf[BUFSIZE];
  185. struct pollfd pfd;
  186. int timeout;
  187. int nbytes, rbytes;
  188. fd = luaL_checkinteger(L, 1);
  189. timeout = luaL_optinteger(L, 2, DEFAULT_TIMEOUT);
  190. pfd.fd = fd;
  191. pfd.events = POLLIN;
  192. pfd.revents = 0;
  193. rbytes = 0; // total number of bytes read
  194. n = poll(&pfd, (nfds_t) 1, timeout);
  195. if (n < 0) { // poll error
  196. lua_pushnil (L);
  197. lua_pushfstring (L, "poll error: %d %d", n, errno);
  198. return 2;
  199. }
  200. if (n == 0) { // timeout
  201. lua_pushnil (L);
  202. lua_pushfstring (L, "read timeout");
  203. return 2;
  204. }
  205. n = read(fd, buf, BUFSIZE);
  206. if (n < 0) { // read error
  207. lua_pushnil (L);
  208. lua_pushfstring (L, "read error: %d %d", n, errno);
  209. return 2;
  210. }
  211. lua_pushlstring (L, (const char *)&buf, n);
  212. return 1;
  213. } //ll_read
  214. int ll_close(lua_State *L) {
  215. // close a socket
  216. // Lua args: socket file descriptor (as integer)
  217. // return true on success or nil, errmsg
  218. int fd;
  219. int n;
  220. fd = luaL_checkinteger(L, 1); // get socket fd
  221. n = close(fd);
  222. if (n == -1) {
  223. lua_pushnil (L);
  224. lua_pushfstring (L, "close error: %d", errno);
  225. return 2;
  226. }
  227. //success, return true
  228. lua_pushboolean (L, 1);
  229. return 1;
  230. } //ll_close
  231. //----------------------------------------------------------------------
  232. // UDP
  233. int ll_udpsocket(lua_State *L) {
  234. // create a UDP socket. Optionnally bind it to an address
  235. // if an address is provided.
  236. // Lua arg: addr, the server sockaddr as a binary string.
  237. // addr is optional. if addr is null or empty, an AF_INET socket
  238. // is created and not bound. if addr is "\x0a", an AF_INET6
  239. // socket is created and not bound. if addr length is > 1,
  240. // the socket is created and bound.
  241. //
  242. // return socket file descriptor as integer or nil, errmsg
  243. //
  244. const char * addr;
  245. size_t addr_len;
  246. int sfd;
  247. int r;
  248. int family; // AF_INET=2, AF_INET6=10
  249. addr = luaL_optlstring(L, 1, NULL, &addr_len);
  250. //~ printf("addr_len: %d \n", addr_len);
  251. if (addr_len == 0) {
  252. family = 2;
  253. } else {
  254. family = addr[0]; // first byte of sockaddr
  255. }
  256. sfd = socket(family, SOCK_DGRAM, 0); // 0 for default protocol
  257. if (sfd < 0) {
  258. lua_pushnil (L);
  259. lua_pushfstring (L, "udpsocket() error %d", errno);
  260. return 2;
  261. }
  262. if (addr_len > 1) {
  263. // bind the socket to addr
  264. r = bind(sfd, (struct sockaddr *) addr, addr_len);
  265. if (r < 0) {
  266. close(sfd);
  267. lua_pushnil (L);
  268. lua_pushfstring (L, "bind error %d", errno);
  269. return 2;
  270. }
  271. }
  272. // success, return socket fd
  273. lua_pushinteger (L, sfd);
  274. return 1;
  275. } //ll_udpsocket
  276. int ll_sendto(lua_State *L) {
  277. // Lua args:
  278. // fd: integer - socket descriptor
  279. // addr: raw address (sockaddr) of the recipient
  280. // s: string to send
  281. int fd;
  282. int n;
  283. const char *addr;
  284. size_t addr_len;
  285. const char *s;
  286. size_t slen;
  287. int flags = 0;
  288. fd = luaL_checkinteger(L, 1); // get socket fd
  289. addr = luaL_checklstring(L, 2, &addr_len); // recipient addr
  290. s = luaL_checklstring(L, 3, &slen); // string to write
  291. if (slen > UDPMAXSIZE) {
  292. luaL_error(L, "sendto: string too large %d", slen);
  293. }
  294. n = sendto(fd, s, slen, flags,
  295. (const struct sockaddr *)addr, addr_len);
  296. if (n < 0) { // write error
  297. lua_pushnil (L);
  298. lua_pushfstring (L, "write error: %d %d", n, errno);
  299. return 2;
  300. }
  301. //success, return number of bytes sent
  302. lua_pushinteger (L, n);
  303. return 1;
  304. } //ll_sendto
  305. int ll_recvfrom(lua_State *L) {
  306. // receive message from a socket file descriptor
  307. // Lua args:
  308. // socket fd: integer
  309. // timeout: integer (in milliseconds)
  310. // (optional - defaults to DEFAULT_TIMEOUT)
  311. // reads at most UDPMAXSIZE bytes.
  312. // return the received message as a string, and the sender
  313. // raw address (sockaddr), or (nil, error msg) on error or timeout
  314. //
  315. int fd;
  316. int n;
  317. char addr[ADDRMAXSIZE];
  318. size_t addr_len = ADDRMAXSIZE;
  319. char buf[UDPMAXSIZE];
  320. struct pollfd pfd;
  321. int timeout;
  322. int flags = 0;
  323. fd = luaL_checkinteger(L, 1);
  324. timeout = luaL_optinteger(L, 2, DEFAULT_TIMEOUT);
  325. pfd.fd = fd;
  326. pfd.events = POLLIN;
  327. pfd.revents = 0;
  328. n = poll(&pfd, (nfds_t) 1, timeout);
  329. if (n < 0) { // poll error
  330. lua_pushnil (L);
  331. lua_pushfstring (L, "poll error: %d %d", n, errno);
  332. return 2;
  333. }
  334. if (n == 0) { // timeout
  335. lua_pushnil (L);
  336. lua_pushfstring (L, "recvfrom timeout");
  337. return 2;
  338. }
  339. n = recvfrom(fd, buf, UDPMAXSIZE, flags,
  340. (struct sockaddr *)addr, (socklen_t *) &addr_len);
  341. if (n < 0) { // read error
  342. lua_pushnil (L);
  343. lua_pushfstring (L, "recvfrom error: %d %d", n, errno);
  344. return 2;
  345. }
  346. lua_pushlstring (L, (const char *)&buf, n);
  347. lua_pushlstring (L, (const char *)&addr, addr_len);
  348. return 2;
  349. } //ll_recvfrom
  350. //----------------------------------------------------------------------
  351. // socket raw address, DNS interface
  352. int ll_getpeername(lua_State *L) {
  353. // get the address of the peer connected to socket fd
  354. // Lua args: socket file descriptor (as integer)
  355. // returns the raw client address as a string, or nil, errmsg
  356. int fd;
  357. int n;
  358. struct sockaddr addr;
  359. socklen_t len = sizeof(addr); //enough for ip4&6 addr
  360. fd = luaL_checkinteger(L, 1); // get socket fd
  361. n = getpeername(fd, &addr, &len);
  362. if (n == -1) {
  363. lua_pushnil (L);
  364. lua_pushfstring (L, "close error: %d", errno);
  365. return 2;
  366. }
  367. //success, return peer socket addr
  368. lua_pushlstring (L, (const char *)&addr, len);
  369. return 1;
  370. } //ll_getpeername
  371. int ll_getsockname(lua_State *L) {
  372. // get the address a socket is bound to
  373. // Lua args: socket file descriptor (as integer)
  374. // returns the raw client address as a string, or nil, errmsg
  375. int fd;
  376. int n;
  377. struct sockaddr addr;
  378. socklen_t len = sizeof(addr); //enough for ip4&6 addr
  379. fd = luaL_checkinteger(L, 1); // get socket fd
  380. n = getsockname(fd, &addr, &len);
  381. if (n == -1) {
  382. lua_pushnil (L);
  383. lua_pushfstring (L, "close error: %d", errno);
  384. return 2;
  385. }
  386. //success, return socket addr
  387. lua_pushlstring (L, (const char *)&addr, len);
  388. return 1;
  389. } //ll_getsockname
  390. int ll_getaddrinfo(lua_State *L) {
  391. // get a list of addresses corresponding to a hostname and port
  392. const char *host, *service;
  393. struct addrinfo hints;
  394. struct addrinfo *result, *rp;
  395. int sfd;
  396. int n;
  397. host = luaL_checkstring(L, 1);
  398. service = luaL_optstring(L, 2, "0");
  399. memset(&hints, 0, sizeof(struct addrinfo));
  400. hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
  401. hints.ai_socktype = SOCK_STREAM;
  402. n = getaddrinfo(host, service, &hints, &result);
  403. if (n) {
  404. lua_pushnil (L);
  405. lua_pushfstring(L, "getaddrinfo: %d %s", n, gai_strerror(n));
  406. return 2;
  407. }
  408. // build the table of the returned addresses
  409. lua_newtable(L);
  410. n = 1;
  411. for (rp = result; rp != NULL; rp = rp->ai_next) {
  412. lua_pushinteger (L, n);
  413. lua_pushlstring(L, (const char *)rp->ai_addr, rp->ai_addrlen);
  414. lua_settable(L, -3);
  415. n += 1;
  416. }
  417. // free the address list
  418. freeaddrinfo(result);
  419. // return the address table
  420. return 1;
  421. } //ll_getaddrinfo
  422. #define HOSTLEN 512
  423. #define SERVLEN 128
  424. int ll_getnameinfo(lua_State *L) {
  425. // inverse of getaddrinfo(). converts a raw address into a host and port
  426. // port is always returned as an integer
  427. // Lua args:
  428. // addr - a raw address (sockaddr) as returned by bind,
  429. // connect, getaddrinfo
  430. // numerichost - an optional flag. set it to any true value to return
  431. // host numeric address or leave it empty for a host name
  432. //
  433. char hostname[HOSTLEN];
  434. char servname[SERVLEN];
  435. const char *addr;
  436. size_t addrlen;
  437. int numerichost;
  438. int n;
  439. addr = luaL_checklstring(L, 1, &addrlen); // raw addr (sockaddr)
  440. numerichost = lua_toboolean(L, 2);
  441. numerichost = numerichost ? NI_NUMERICHOST : 0;
  442. n = getnameinfo((const struct sockaddr *)addr, addrlen,
  443. hostname, HOSTLEN, servname, SERVLEN,
  444. (NI_NUMERICSERV | numerichost));
  445. if (n) {
  446. lua_pushnil (L);
  447. lua_pushfstring (L, "getnameinfo: %d %s", n, gai_strerror(n));
  448. return 2;
  449. }
  450. //success, return hostame and servname
  451. lua_pushstring(L, hostname);
  452. lua_pushinteger(L, atoi(servname));
  453. return 2;
  454. } //ll_getnameinfo
  455. int ll_msleep(lua_State *L) {
  456. // suspend the execution of the calling thread for some time
  457. // Lua args: the sleep time in milliseconds as an integer
  458. // return value: true on success, or nil, errmsg
  459. //
  460. int n;
  461. long ms = luaL_checkinteger(L, 1); // sleep time in milliseconds
  462. struct timespec req;
  463. req.tv_sec = ms / 1000;
  464. req.tv_nsec = (ms % 1000) * 1000000;
  465. n = nanosleep(&req, NULL);
  466. if (n == -1) {
  467. lua_pushnil (L);
  468. lua_pushfstring (L, "nanosleep error: %d", errno);
  469. return 2;
  470. }
  471. //success, return true
  472. lua_pushboolean (L, 1);
  473. return 1;
  474. } //ll_msleep
  475. // ---------------------------------------------------------------------
  476. // Lua library function
  477. static const struct luaL_Reg minisocklib[] = {
  478. // tcp/unix
  479. {"bind", ll_bind},
  480. {"accept", ll_accept},
  481. {"connect", ll_connect},
  482. {"write", ll_write},
  483. {"read", ll_read},
  484. {"close", ll_close},
  485. // udp
  486. {"udpsocket", ll_udpsocket},
  487. {"sendto", ll_sendto},
  488. {"recvfrom", ll_recvfrom},
  489. // info
  490. {"getsockname", ll_getsockname},
  491. {"getpeername", ll_getpeername},
  492. {"getaddrinfo", ll_getaddrinfo},
  493. {"getnameinfo", ll_getnameinfo},
  494. // misc
  495. {"msleep", ll_msleep},
  496. {NULL, NULL},
  497. };
  498. int luaopen_minisock (lua_State *L) {
  499. luaL_newlib (L, minisocklib);
  500. //
  501. lua_pushliteral (L, "VERSION");
  502. lua_pushliteral (L, ll_VERSION);
  503. lua_settable (L, -3);
  504. lua_pushliteral (L, "BUFSIZE");
  505. lua_pushinteger (L, BUFSIZE);
  506. lua_settable (L, -3);
  507. lua_pushliteral (L, "UDPMAXSIZE");
  508. lua_pushinteger (L, UDPMAXSIZE);
  509. lua_settable (L, -3);
  510. //
  511. return 1;
  512. }