diff --git a/examples/abstract-unix-socket.janet b/examples/abstract-unix-socket.janet new file mode 100644 index 00000000..e583e7a7 --- /dev/null +++ b/examples/abstract-unix-socket.janet @@ -0,0 +1,6 @@ +# Linux only - uses abstract unix domain sockets +(ev/spawn (net/server :unix "@abc123" (fn [conn] (print (:read conn 1024)) (:close conn)))) +(ev/sleep 1) +(def s (net/connect :unix "@abc123" :stream)) +(:write s "hello") +(:close s) diff --git a/src/core/net.c b/src/core/net.c index f7e62bad..2634ae9d 100644 --- a/src/core/net.c +++ b/src/core/net.c @@ -341,7 +341,7 @@ static int janet_get_sockettype(Janet *argv, int32_t argc, int32_t n) { /* Needs argc >= offset + 2 */ /* For unix paths, just rertuns a single sockaddr and sets *is_unix to 1, * otherwise 0. Also, ignores is_bind when is a unix socket. */ -static struct addrinfo *janet_get_addrinfo(Janet *argv, int32_t offset, int socktype, int passive, int *is_unix) { +static struct addrinfo *janet_get_addrinfo(Janet *argv, int32_t offset, int socktype, int passive, int *is_unix, socklen_t *sizeout) { /* Unix socket support - not yet supported on windows. */ #ifndef JANET_WINDOWS if (janet_keyeq(argv[offset], "unix")) { @@ -352,15 +352,14 @@ static struct addrinfo *janet_get_addrinfo(Janet *argv, int32_t offset, int sock } saddr->sun_family = AF_UNIX; size_t path_size = sizeof(saddr->sun_path); + snprintf(saddr->sun_path, path_size, "%s", path); + *sizeout = sizeof(struct sockaddr_un); #ifdef JANET_LINUX if (path[0] == '@') { saddr->sun_path[0] = '\0'; - snprintf(saddr->sun_path + 1, path_size - 1, "%s", path + 1); - } else -#endif - { - snprintf(saddr->sun_path, path_size, "%s", path); + *sizeout = offsetof(struct sockaddr_un, sun_path) + janet_string_length(path); } +#endif *is_unix = 1; return (struct addrinfo *) saddr; } @@ -385,6 +384,7 @@ static struct addrinfo *janet_get_addrinfo(Janet *argv, int32_t offset, int sock janet_panicf("could not get address info: %s", gai_strerror(status)); } *is_unix = 0; + *sizeout = sizeof(struct sockaddr_un); return ai; } @@ -405,12 +405,13 @@ JANET_CORE_FN(cfun_net_sockaddr, int socktype = janet_get_sockettype(argv, argc, 2); int is_unix = 0; int make_arr = (argc >= 3 && janet_truthy(argv[3])); - struct addrinfo *ai = janet_get_addrinfo(argv, 0, socktype, 0, &is_unix); + socklen_t addrsize = 0; + struct addrinfo *ai = janet_get_addrinfo(argv, 0, socktype, 0, &is_unix, &addrsize); #ifndef JANET_WINDOWS /* no unix domain socket support on windows yet */ if (is_unix) { - void *abst = janet_abstract(&janet_address_type, sizeof(struct sockaddr_un)); - memcpy(abst, ai, sizeof(struct sockaddr_un)); + void *abst = janet_abstract(&janet_address_type, addrsize); + memcpy(abst, ai, addrsize); Janet ret = janet_wrap_abstract(abst); return make_arr ? janet_wrap_array(janet_array_n(&ret, 1)) : ret; } @@ -461,7 +462,8 @@ JANET_CORE_FN(cfun_net_connect, } /* Where we're connecting to */ - struct addrinfo *ai = janet_get_addrinfo(argv, 0, socktype, 0, &is_unix); + socklen_t addrlen = 0; + struct addrinfo *ai = janet_get_addrinfo(argv, 0, socktype, 0, &is_unix, &addrlen); /* Check if we're binding address */ struct addrinfo *binding = NULL; @@ -486,7 +488,6 @@ JANET_CORE_FN(cfun_net_connect, /* Create socket */ JSock sock = JSOCKDEFAULT; void *addr = NULL; - socklen_t addrlen = 0; #ifndef JANET_WINDOWS if (is_unix) { sock = socket(AF_UNIX, socktype | JSOCKFLAGS, 0); @@ -496,7 +497,6 @@ JANET_CORE_FN(cfun_net_connect, janet_panicf("could not create socket: %V", v); } addr = (void *) ai; - addrlen = sizeof(struct sockaddr_un); } else #endif { @@ -664,7 +664,8 @@ JANET_CORE_FN(cfun_net_listen, /* Get host, port, and handler*/ int socktype = janet_get_sockettype(argv, argc, 2); int is_unix = 0; - struct addrinfo *ai = janet_get_addrinfo(argv, 0, socktype, 1, &is_unix); + socklen_t addrlen = 0; + struct addrinfo *ai = janet_get_addrinfo(argv, 0, socktype, 1, &is_unix, &addrlen); int reuse = !(argc >= 4 && janet_truthy(argv[3])); JSock sfd = JSOCKDEFAULT; @@ -676,7 +677,7 @@ JANET_CORE_FN(cfun_net_listen, janet_panicf("could not create socket: %V", janet_ev_lasterr()); } const char *err = serverify_socket(sfd, reuse, 0); - if (NULL != err || bind(sfd, (struct sockaddr *)ai, sizeof(struct sockaddr_un))) { + if (NULL != err || bind(sfd, (struct sockaddr *)ai, addrlen)) { JSOCKCLOSE(sfd); janet_free(ai); if (err) {