unix: support sockaddr_un in uv_udp_send()

PR-URL: https://github.com/libuv/libuv/pull/2220
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
This commit is contained in:
Yury Selivanov 2019-03-17 15:23:23 -04:00 committed by cjihrig
parent 280f7b2496
commit 89a027d862
No known key found for this signature in database
GPG Key ID: 7434390BDBE9B9C5
4 changed files with 74 additions and 2 deletions

View File

@ -30,6 +30,7 @@
#if defined(__MVS__)
#include <xti.h>
#endif
#include <sys/un.h>
#if defined(IPV6_JOIN_GROUP) && !defined(IPV6_ADD_MEMBERSHIP)
# define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
@ -232,8 +233,16 @@ static void uv__udp_sendmsg(uv_udp_t* handle) {
h.msg_namelen = 0;
} else {
h.msg_name = &req->addr;
h.msg_namelen = req->addr.ss_family == AF_INET6 ?
sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
if (req->addr.ss_family == AF_INET6)
h.msg_namelen = sizeof(struct sockaddr_in6);
else if (req->addr.ss_family == AF_INET)
h.msg_namelen = sizeof(struct sockaddr_in);
else if (req->addr.ss_family == AF_UNIX)
h.msg_namelen = sizeof(struct sockaddr_un);
else {
assert(0 && "unsupported address family");
abort();
}
}
h.msg_iov = (struct iovec*) req->bufs;
h.msg_iovlen = req->nbufs;

View File

@ -34,6 +34,7 @@
# include <malloc.h> /* malloc */
#else
# include <net/if.h> /* if_nametoindex */
# include <sys/un.h> /* AF_UNIX, sockaddr_un */
#endif
@ -376,6 +377,10 @@ int uv__udp_check_before_send(uv_udp_t* handle, const struct sockaddr* addr) {
addrlen = sizeof(struct sockaddr_in);
else if (addr->sa_family == AF_INET6)
addrlen = sizeof(struct sockaddr_in6);
#if defined(AF_UNIX) && !defined(_WIN32)
else if (addr->sa_family == AF_UNIX)
addrlen = sizeof(struct sockaddr_un);
#endif
else
return UV_EINVAL;
} else {

View File

@ -155,6 +155,9 @@ TEST_DECLARE (udp_open)
TEST_DECLARE (udp_open_twice)
TEST_DECLARE (udp_open_bound)
TEST_DECLARE (udp_open_connect)
#ifndef _WIN32
TEST_DECLARE (udp_send_unix)
#endif
TEST_DECLARE (udp_try_send)
TEST_DECLARE (pipe_bind_error_addrinuse)
TEST_DECLARE (pipe_bind_error_addrnotavail)
@ -657,6 +660,9 @@ TASK_LIST_START
TEST_ENTRY (udp_open_bound)
TEST_ENTRY (udp_open_connect)
TEST_HELPER (udp_open_connect, udp4_echo_server)
#ifndef _WIN32
TEST_ENTRY (udp_send_unix)
#endif
TEST_ENTRY (pipe_bind_error_addrinuse)
TEST_ENTRY (pipe_bind_error_addrnotavail)

View File

@ -27,6 +27,8 @@
#ifndef _WIN32
# include <unistd.h>
# include <sys/socket.h>
# include <sys/un.h>
#endif
static int send_cb_called = 0;
@ -296,3 +298,53 @@ TEST_IMPL(udp_open_connect) {
MAKE_VALGRIND_HAPPY();
return 0;
}
#ifndef _WIN32
TEST_IMPL(udp_send_unix) {
/* Test that "uv_udp_send()" supports sending over
a "sockaddr_un" address. */
struct sockaddr_un addr;
uv_udp_t handle;
uv_udp_send_t req;
uv_loop_t* loop;
uv_buf_t buf = uv_buf_init("PING", 4);
int fd;
int r;
loop = uv_default_loop();
memset(&addr, 0, sizeof addr);
addr.sun_family = AF_UNIX;
ASSERT(strlen(TEST_PIPENAME) < sizeof(addr.sun_path));
memcpy(addr.sun_path, TEST_PIPENAME, strlen(TEST_PIPENAME));
fd = socket(AF_UNIX, SOCK_STREAM, 0);
ASSERT(fd >= 0);
unlink(TEST_PIPENAME);
ASSERT(0 == bind(fd, (const struct sockaddr*)&addr, sizeof addr));
ASSERT(0 == listen(fd, 1));
r = uv_udp_init(loop, &handle);
ASSERT(r == 0);
r = uv_udp_open(&handle, fd);
ASSERT(r == 0);
uv_run(loop, UV_RUN_DEFAULT);
r = uv_udp_send(&req,
&handle,
&buf,
1,
(const struct sockaddr*) &addr,
NULL);
ASSERT(r == 0);
uv_close((uv_handle_t*)&handle, NULL);
uv_run(loop, UV_RUN_DEFAULT);
close(fd);
unlink(TEST_PIPENAME);
MAKE_VALGRIND_HAPPY();
return 0;
}
#endif