Last active
August 1, 2017 14:21
-
-
Save mischief/ce429b04b7b7609b571da1df224244b5 to your computer and use it in GitHub Desktop.
luajit imsg demo http://man.openbsd.org/imsg_init
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| local os = require("os") | |
| local ffi = require("ffi") | |
| -- luajit ffi declarations | |
| ffi.cdef[[ | |
| typedef int32_t pid_t; | |
| pid_t fork(void); | |
| int close(int d); | |
| char *strerror(int n); | |
| ]] | |
| local unistd = { | |
| close = ffi.C.close, | |
| fork = ffi.C.fork, | |
| } | |
| ffi.cdef[[ | |
| static const int AF_UNIX = 1; | |
| static const int SOCK_STREAM = 1; | |
| static const int PF_UNSPEC = 0; | |
| int socketpair(int d, int type, int protocol, int sv[2]); | |
| ]] | |
| local socket = { | |
| AF_UNIX = ffi.C.AF_UNIX, | |
| SOCK_STREAM = ffi.C.SOCK_STREAM, | |
| PF_UNSPEC = ffi.C.PF_UNSPEC, | |
| socketpair = ffi.C.socketpair, | |
| } | |
| ffi.cdef[[ | |
| typedef unsigned char u_char; | |
| typedef long ssize_t; | |
| typedef int32_t pid_t; | |
| struct ibuf { | |
| struct { struct ibuf *tqe_next; struct ibuf **tqe_prev; } entry; | |
| u_char *buf; | |
| size_t size; | |
| size_t max; | |
| size_t wpos; | |
| size_t rpos; | |
| int fd; | |
| }; | |
| struct msgbuf { | |
| struct { struct ibuf *tqh_first; struct ibuf **tqh_last; } bufs; | |
| uint32_t queued; | |
| int fd; | |
| }; | |
| struct ibuf_read { | |
| u_char buf[65535]; | |
| u_char *rptr; | |
| size_t wpos; | |
| }; | |
| struct imsg_fd { | |
| struct { struct imsg_fd *tqe_next; struct imsg_fd **tqe_prev; } entry; | |
| int fd; | |
| }; | |
| struct imsgbuf { | |
| struct { struct imsg_fd *tqh_first; struct imsg_fd **tqh_last; } fds; | |
| struct ibuf_read r; | |
| struct msgbuf w; | |
| int fd; | |
| pid_t pid; | |
| }; | |
| struct imsg_hdr { | |
| uint32_t type; | |
| uint16_t len; | |
| uint16_t flags; | |
| uint32_t peerid; | |
| uint32_t pid; | |
| }; | |
| struct imsg { | |
| struct imsg_hdr hdr; | |
| int fd; | |
| void *data; | |
| }; | |
| struct ibuf *ibuf_open(size_t); | |
| struct ibuf *ibuf_dynamic(size_t, size_t); | |
| int ibuf_add(struct ibuf *, const void *, size_t); | |
| void *ibuf_reserve(struct ibuf *, size_t); | |
| void *ibuf_seek(struct ibuf *, size_t, size_t); | |
| size_t ibuf_size(struct ibuf *); | |
| size_t ibuf_left(struct ibuf *); | |
| void ibuf_close(struct msgbuf *, struct ibuf *); | |
| int ibuf_write(struct msgbuf *); | |
| void ibuf_free(struct ibuf *); | |
| void msgbuf_init(struct msgbuf *); | |
| void msgbuf_clear(struct msgbuf *); | |
| int msgbuf_write(struct msgbuf *); | |
| void msgbuf_drain(struct msgbuf *, size_t); | |
| void imsg_init(struct imsgbuf *, int); | |
| ssize_t imsg_read(struct imsgbuf *); | |
| ssize_t imsg_get(struct imsgbuf *, struct imsg *); | |
| int imsg_compose(struct imsgbuf *, uint32_t, uint32_t, pid_t, int, | |
| const void *, uint16_t); | |
| int imsg_composev(struct imsgbuf *, uint32_t, uint32_t, pid_t, int, | |
| const struct iovec *, int); | |
| struct ibuf *imsg_create(struct imsgbuf *, uint32_t, uint32_t, pid_t, uint16_t); | |
| int imsg_add(struct ibuf *, const void *, uint16_t); | |
| void imsg_close(struct imsgbuf *, struct ibuf *); | |
| void imsg_free(struct imsg *); | |
| int imsg_flush(struct imsgbuf *); | |
| void imsg_clear(struct imsgbuf *); | |
| ]] | |
| local imsg = ffi.load("util") | |
| err = function(what) | |
| error(what .. ": " .. ffi.C.strerror(ffi.errno())) | |
| end | |
| -- example imsg program | |
| local fds = ffi.new("int[2]") | |
| local parent_ibuf = ffi.new("struct imsgbuf") | |
| local child_ibuf = ffi.new("struct imsgbuf") | |
| if socket.socketpair(socket.AF_UNIX, socket.SOCK_STREAM, socket.PF_UNSPEC, fds) == -1 then | |
| err("socketpair") | |
| end | |
| child_main = function(b) | |
| local data = ffi.new("int32_t[1]", {42}) | |
| local n = imsg.imsg_compose(b, 1, 0, 0, -1, data, 4) | |
| print("child: imsg_compose="..tostring(n)) | |
| if n == -1 then | |
| err("imsg_compose") | |
| end | |
| n = imsg.imsg_flush(b) | |
| print("child: imsg_flush="..tostring(n)) | |
| if n == -1 then | |
| err("imsg_flush") | |
| end | |
| return 0 | |
| end | |
| parent_main = function(b) | |
| local msg = ffi.new("struct imsg") | |
| local n = imsg.imsg_read(b) | |
| print("parent: imsg_read="..tonumber(n)) | |
| if n <= 0 then | |
| err("imsg_read") | |
| end | |
| while true do | |
| n = imsg.imsg_get(b, msg) | |
| print("parent: imsg_get="..tonumber(n)) | |
| if n == 0 then | |
| break | |
| end | |
| if n == -1 then | |
| err("imsg_get") | |
| end | |
| if msg.hdr.type == 1 then | |
| local d = ffi.cast("int32_t*", msg.data) | |
| print(string.format("%d", d[0])) | |
| end | |
| end | |
| end | |
| local pid = unistd.fork() | |
| if pid == -1 then | |
| err("fork") | |
| end | |
| if pid == 0 then | |
| -- child | |
| unistd.close(fds[0]) | |
| imsg.imsg_init(child_ibuf, fds[1]) | |
| os.exit(child_main(child_ibuf)) | |
| end | |
| -- parent | |
| unistd.close(fds[1]) | |
| imsg.imsg_init(parent_ibuf, fds[0]) | |
| os.exit(parent_main(parent_ibuf)) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment