mirror of https://github.com/xqemu/xqemu.git
Merge misc I/O channel fixes
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCAAGBQJWen18AAoJEL6G67QVEE/f6TAP/0urpBEzBoYEfqtO+z/CFAyS Z5LvXVwDROxV7r42uuO6r6WNpXm2azdm4nMmFEShR70K7HB1T85aEGhSBS20xcFn 1zSjtutsNWozXYsmJ/rk5aI11E4Pgn2ElZEsom4VwqKJc6ILHDeiQ+jg/5Ky3TFj guEfB3Xyk11uIsxAcL1eomiXxpOfCaakbTPp5LQ9dUhYLeTig8uZ58BUWbc/1ADc hA+r7b+f9P2D34yocNMvfFfp4Ddy03uKueF2JNkwTVN9/1Ee5dHVu1xzS5uwUm8C IeGCx3Rh9f9ZN51qYeL2bCbhqOP/fdXWzCXfPDNVdTPfc7h4/Cl6bGkOs52oJ81x iHxvDY6Jco8fnL3T905RJ4k78eC97EOz9wOnUQEcFFxcwp6xgXYz0WRjlvCudB4S EiV7fqF0+jgX8AGYHHKIBT22D9Tp9L7x66f8eMNcyK79GHmc0nbSBT5KpVobFilg +h9Ws2TbUhRMAp155muX2bwPTHBucHxU5ktESY71ddWJmL53f01q2WWJFLzwWeVs w+QKmlY3dtvzpAPjFyDAvTX0o2YgbjZOG9iMhyNDZuQCo1x38gY8fRyl1+7uPjm6 hmhtKUp9VbXBkwFV3n56tCNDY9Azr1pdxqiPg7fuukTcaHSnu2CHMF2A844oat4G O1ftlHgL2yR7eqty70Wm =JkVB -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/berrange/tags/pull-io-fixes-2015-12-23-1' into staging Merge misc I/O channel fixes # gpg: Signature made Wed 23 Dec 2015 10:54:52 GMT using RSA key ID 15104FDF # gpg: Good signature from "Daniel P. Berrange <dan@berrange.com>" # gpg: aka "Daniel P. Berrange <berrange@redhat.com>" * remotes/berrange/tags/pull-io-fixes-2015-12-23-1: io: fix stack allocation when sending of file descriptors io: fix setting of QIO_CHANNEL_FEATURE_FD_PASS on server connections io: bind to loopback IP addrs in test suite Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
e833dfddb4
|
@ -352,13 +352,19 @@ qio_channel_socket_accept(QIOChannelSocket *ioc,
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getsockname(cioc->fd, (struct sockaddr *)&ioc->localAddr,
|
if (getsockname(cioc->fd, (struct sockaddr *)&cioc->localAddr,
|
||||||
&ioc->localAddrLen) < 0) {
|
&cioc->localAddrLen) < 0) {
|
||||||
error_setg_errno(errp, socket_error(),
|
error_setg_errno(errp, socket_error(),
|
||||||
"Unable to query local socket address");
|
"Unable to query local socket address");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
if (cioc->localAddr.ss_family == AF_UNIX) {
|
||||||
|
QIO_CHANNEL(cioc)->features |= (1 << QIO_CHANNEL_FEATURE_FD_PASS);
|
||||||
|
}
|
||||||
|
#endif /* WIN32 */
|
||||||
|
|
||||||
trace_qio_channel_socket_accept_complete(ioc, cioc, cioc->fd);
|
trace_qio_channel_socket_accept_complete(ioc, cioc, cioc->fd);
|
||||||
return cioc;
|
return cioc;
|
||||||
|
|
||||||
|
@ -487,15 +493,14 @@ static ssize_t qio_channel_socket_writev(QIOChannel *ioc,
|
||||||
QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
|
QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
struct msghdr msg = { NULL, };
|
struct msghdr msg = { NULL, };
|
||||||
|
char control[CMSG_SPACE(sizeof(int) * SOCKET_MAX_FDS)] = { 0 };
|
||||||
|
size_t fdsize = sizeof(int) * nfds;
|
||||||
|
struct cmsghdr *cmsg;
|
||||||
|
|
||||||
msg.msg_iov = (struct iovec *)iov;
|
msg.msg_iov = (struct iovec *)iov;
|
||||||
msg.msg_iovlen = niov;
|
msg.msg_iovlen = niov;
|
||||||
|
|
||||||
if (nfds) {
|
if (nfds) {
|
||||||
char control[CMSG_SPACE(sizeof(int) * SOCKET_MAX_FDS)];
|
|
||||||
size_t fdsize = sizeof(int) * nfds;
|
|
||||||
struct cmsghdr *cmsg;
|
|
||||||
|
|
||||||
if (nfds > SOCKET_MAX_FDS) {
|
if (nfds > SOCKET_MAX_FDS) {
|
||||||
error_setg_errno(errp, -EINVAL,
|
error_setg_errno(errp, -EINVAL,
|
||||||
"Only %d FDs can be sent, got %zu",
|
"Only %d FDs can be sent, got %zu",
|
||||||
|
|
|
@ -210,13 +210,19 @@ static void test_io_channel_setup_async(SocketAddress *listen_addr,
|
||||||
|
|
||||||
static void test_io_channel(bool async,
|
static void test_io_channel(bool async,
|
||||||
SocketAddress *listen_addr,
|
SocketAddress *listen_addr,
|
||||||
SocketAddress *connect_addr)
|
SocketAddress *connect_addr,
|
||||||
|
bool passFD)
|
||||||
{
|
{
|
||||||
QIOChannel *src, *dst;
|
QIOChannel *src, *dst;
|
||||||
QIOChannelTest *test;
|
QIOChannelTest *test;
|
||||||
if (async) {
|
if (async) {
|
||||||
test_io_channel_setup_async(listen_addr, connect_addr, &src, &dst);
|
test_io_channel_setup_async(listen_addr, connect_addr, &src, &dst);
|
||||||
|
|
||||||
|
g_assert(!passFD ||
|
||||||
|
qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS));
|
||||||
|
g_assert(!passFD ||
|
||||||
|
qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS));
|
||||||
|
|
||||||
test = qio_channel_test_new();
|
test = qio_channel_test_new();
|
||||||
qio_channel_test_run_threads(test, true, src, dst);
|
qio_channel_test_run_threads(test, true, src, dst);
|
||||||
qio_channel_test_validate(test);
|
qio_channel_test_validate(test);
|
||||||
|
@ -226,6 +232,11 @@ static void test_io_channel(bool async,
|
||||||
|
|
||||||
test_io_channel_setup_async(listen_addr, connect_addr, &src, &dst);
|
test_io_channel_setup_async(listen_addr, connect_addr, &src, &dst);
|
||||||
|
|
||||||
|
g_assert(!passFD ||
|
||||||
|
qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS));
|
||||||
|
g_assert(!passFD ||
|
||||||
|
qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS));
|
||||||
|
|
||||||
test = qio_channel_test_new();
|
test = qio_channel_test_new();
|
||||||
qio_channel_test_run_threads(test, false, src, dst);
|
qio_channel_test_run_threads(test, false, src, dst);
|
||||||
qio_channel_test_validate(test);
|
qio_channel_test_validate(test);
|
||||||
|
@ -235,6 +246,11 @@ static void test_io_channel(bool async,
|
||||||
} else {
|
} else {
|
||||||
test_io_channel_setup_sync(listen_addr, connect_addr, &src, &dst);
|
test_io_channel_setup_sync(listen_addr, connect_addr, &src, &dst);
|
||||||
|
|
||||||
|
g_assert(!passFD ||
|
||||||
|
qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS));
|
||||||
|
g_assert(!passFD ||
|
||||||
|
qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS));
|
||||||
|
|
||||||
test = qio_channel_test_new();
|
test = qio_channel_test_new();
|
||||||
qio_channel_test_run_threads(test, true, src, dst);
|
qio_channel_test_run_threads(test, true, src, dst);
|
||||||
qio_channel_test_validate(test);
|
qio_channel_test_validate(test);
|
||||||
|
@ -244,6 +260,11 @@ static void test_io_channel(bool async,
|
||||||
|
|
||||||
test_io_channel_setup_sync(listen_addr, connect_addr, &src, &dst);
|
test_io_channel_setup_sync(listen_addr, connect_addr, &src, &dst);
|
||||||
|
|
||||||
|
g_assert(!passFD ||
|
||||||
|
qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS));
|
||||||
|
g_assert(!passFD ||
|
||||||
|
qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS));
|
||||||
|
|
||||||
test = qio_channel_test_new();
|
test = qio_channel_test_new();
|
||||||
qio_channel_test_run_threads(test, false, src, dst);
|
qio_channel_test_run_threads(test, false, src, dst);
|
||||||
qio_channel_test_validate(test);
|
qio_channel_test_validate(test);
|
||||||
|
@ -261,7 +282,7 @@ static void test_io_channel_ipv4(bool async)
|
||||||
|
|
||||||
listen_addr->type = SOCKET_ADDRESS_KIND_INET;
|
listen_addr->type = SOCKET_ADDRESS_KIND_INET;
|
||||||
listen_addr->u.inet = g_new0(InetSocketAddress, 1);
|
listen_addr->u.inet = g_new0(InetSocketAddress, 1);
|
||||||
listen_addr->u.inet->host = g_strdup("0.0.0.0");
|
listen_addr->u.inet->host = g_strdup("127.0.0.1");
|
||||||
listen_addr->u.inet->port = NULL; /* Auto-select */
|
listen_addr->u.inet->port = NULL; /* Auto-select */
|
||||||
|
|
||||||
connect_addr->type = SOCKET_ADDRESS_KIND_INET;
|
connect_addr->type = SOCKET_ADDRESS_KIND_INET;
|
||||||
|
@ -269,7 +290,7 @@ static void test_io_channel_ipv4(bool async)
|
||||||
connect_addr->u.inet->host = g_strdup("127.0.0.1");
|
connect_addr->u.inet->host = g_strdup("127.0.0.1");
|
||||||
connect_addr->u.inet->port = NULL; /* Filled in later */
|
connect_addr->u.inet->port = NULL; /* Filled in later */
|
||||||
|
|
||||||
test_io_channel(async, listen_addr, connect_addr);
|
test_io_channel(async, listen_addr, connect_addr, false);
|
||||||
|
|
||||||
qapi_free_SocketAddress(listen_addr);
|
qapi_free_SocketAddress(listen_addr);
|
||||||
qapi_free_SocketAddress(connect_addr);
|
qapi_free_SocketAddress(connect_addr);
|
||||||
|
@ -295,7 +316,7 @@ static void test_io_channel_ipv6(bool async)
|
||||||
|
|
||||||
listen_addr->type = SOCKET_ADDRESS_KIND_INET;
|
listen_addr->type = SOCKET_ADDRESS_KIND_INET;
|
||||||
listen_addr->u.inet = g_new0(InetSocketAddress, 1);
|
listen_addr->u.inet = g_new0(InetSocketAddress, 1);
|
||||||
listen_addr->u.inet->host = g_strdup("::");
|
listen_addr->u.inet->host = g_strdup("::1");
|
||||||
listen_addr->u.inet->port = NULL; /* Auto-select */
|
listen_addr->u.inet->port = NULL; /* Auto-select */
|
||||||
|
|
||||||
connect_addr->type = SOCKET_ADDRESS_KIND_INET;
|
connect_addr->type = SOCKET_ADDRESS_KIND_INET;
|
||||||
|
@ -303,7 +324,7 @@ static void test_io_channel_ipv6(bool async)
|
||||||
connect_addr->u.inet->host = g_strdup("::1");
|
connect_addr->u.inet->host = g_strdup("::1");
|
||||||
connect_addr->u.inet->port = NULL; /* Filled in later */
|
connect_addr->u.inet->port = NULL; /* Filled in later */
|
||||||
|
|
||||||
test_io_channel(async, listen_addr, connect_addr);
|
test_io_channel(async, listen_addr, connect_addr, false);
|
||||||
|
|
||||||
qapi_free_SocketAddress(listen_addr);
|
qapi_free_SocketAddress(listen_addr);
|
||||||
qapi_free_SocketAddress(connect_addr);
|
qapi_free_SocketAddress(connect_addr);
|
||||||
|
@ -337,7 +358,7 @@ static void test_io_channel_unix(bool async)
|
||||||
connect_addr->u.q_unix = g_new0(UnixSocketAddress, 1);
|
connect_addr->u.q_unix = g_new0(UnixSocketAddress, 1);
|
||||||
connect_addr->u.q_unix->path = g_strdup(TEST_SOCKET);
|
connect_addr->u.q_unix->path = g_strdup(TEST_SOCKET);
|
||||||
|
|
||||||
test_io_channel(async, listen_addr, connect_addr);
|
test_io_channel(async, listen_addr, connect_addr, true);
|
||||||
|
|
||||||
qapi_free_SocketAddress(listen_addr);
|
qapi_free_SocketAddress(listen_addr);
|
||||||
qapi_free_SocketAddress(connect_addr);
|
qapi_free_SocketAddress(connect_addr);
|
||||||
|
@ -355,6 +376,100 @@ static void test_io_channel_unix_async(void)
|
||||||
{
|
{
|
||||||
return test_io_channel_unix(true);
|
return test_io_channel_unix(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_io_channel_unix_fd_pass(void)
|
||||||
|
{
|
||||||
|
SocketAddress *listen_addr = g_new0(SocketAddress, 1);
|
||||||
|
SocketAddress *connect_addr = g_new0(SocketAddress, 1);
|
||||||
|
QIOChannel *src, *dst;
|
||||||
|
int testfd;
|
||||||
|
int fdsend[3];
|
||||||
|
int *fdrecv = NULL;
|
||||||
|
size_t nfdrecv = 0;
|
||||||
|
size_t i;
|
||||||
|
char bufsend[12], bufrecv[12];
|
||||||
|
struct iovec iosend[1], iorecv[1];
|
||||||
|
|
||||||
|
#define TEST_SOCKET "test-io-channel-socket.sock"
|
||||||
|
#define TEST_FILE "test-io-channel-socket.txt"
|
||||||
|
|
||||||
|
testfd = open(TEST_FILE, O_RDWR|O_TRUNC|O_CREAT, 0700);
|
||||||
|
g_assert(testfd != -1);
|
||||||
|
fdsend[0] = testfd;
|
||||||
|
fdsend[1] = testfd;
|
||||||
|
fdsend[2] = testfd;
|
||||||
|
|
||||||
|
listen_addr->type = SOCKET_ADDRESS_KIND_UNIX;
|
||||||
|
listen_addr->u.q_unix = g_new0(UnixSocketAddress, 1);
|
||||||
|
listen_addr->u.q_unix->path = g_strdup(TEST_SOCKET);
|
||||||
|
|
||||||
|
connect_addr->type = SOCKET_ADDRESS_KIND_UNIX;
|
||||||
|
connect_addr->u.q_unix = g_new0(UnixSocketAddress, 1);
|
||||||
|
connect_addr->u.q_unix->path = g_strdup(TEST_SOCKET);
|
||||||
|
|
||||||
|
test_io_channel_setup_sync(listen_addr, connect_addr, &src, &dst);
|
||||||
|
|
||||||
|
memcpy(bufsend, "Hello World", G_N_ELEMENTS(bufsend));
|
||||||
|
|
||||||
|
iosend[0].iov_base = bufsend;
|
||||||
|
iosend[0].iov_len = G_N_ELEMENTS(bufsend);
|
||||||
|
|
||||||
|
iorecv[0].iov_base = bufrecv;
|
||||||
|
iorecv[0].iov_len = G_N_ELEMENTS(bufrecv);
|
||||||
|
|
||||||
|
g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS));
|
||||||
|
g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS));
|
||||||
|
|
||||||
|
qio_channel_writev_full(src,
|
||||||
|
iosend,
|
||||||
|
G_N_ELEMENTS(iosend),
|
||||||
|
fdsend,
|
||||||
|
G_N_ELEMENTS(fdsend),
|
||||||
|
&error_abort);
|
||||||
|
|
||||||
|
qio_channel_readv_full(dst,
|
||||||
|
iorecv,
|
||||||
|
G_N_ELEMENTS(iorecv),
|
||||||
|
&fdrecv,
|
||||||
|
&nfdrecv,
|
||||||
|
&error_abort);
|
||||||
|
|
||||||
|
g_assert(nfdrecv == G_N_ELEMENTS(fdsend));
|
||||||
|
/* Each recvd FD should be different from sent FD */
|
||||||
|
for (i = 0; i < nfdrecv; i++) {
|
||||||
|
g_assert_cmpint(fdrecv[i], !=, testfd);
|
||||||
|
}
|
||||||
|
/* Each recvd FD should be different from each other */
|
||||||
|
g_assert_cmpint(fdrecv[0], !=, fdrecv[1]);
|
||||||
|
g_assert_cmpint(fdrecv[0], !=, fdrecv[2]);
|
||||||
|
g_assert_cmpint(fdrecv[1], !=, fdrecv[2]);
|
||||||
|
|
||||||
|
/* Check the I/O buf we sent at the same time matches */
|
||||||
|
g_assert(memcmp(bufsend, bufrecv, G_N_ELEMENTS(bufsend)) == 0);
|
||||||
|
|
||||||
|
/* Write some data into the FD we received */
|
||||||
|
g_assert(write(fdrecv[0], bufsend, G_N_ELEMENTS(bufsend)) ==
|
||||||
|
G_N_ELEMENTS(bufsend));
|
||||||
|
|
||||||
|
/* Read data from the original FD and make sure it matches */
|
||||||
|
memset(bufrecv, 0, G_N_ELEMENTS(bufrecv));
|
||||||
|
g_assert(lseek(testfd, 0, SEEK_SET) == 0);
|
||||||
|
g_assert(read(testfd, bufrecv, G_N_ELEMENTS(bufrecv)) ==
|
||||||
|
G_N_ELEMENTS(bufrecv));
|
||||||
|
g_assert(memcmp(bufsend, bufrecv, G_N_ELEMENTS(bufsend)) == 0);
|
||||||
|
|
||||||
|
object_unref(OBJECT(src));
|
||||||
|
object_unref(OBJECT(dst));
|
||||||
|
qapi_free_SocketAddress(listen_addr);
|
||||||
|
qapi_free_SocketAddress(connect_addr);
|
||||||
|
unlink(TEST_SOCKET);
|
||||||
|
unlink(TEST_FILE);
|
||||||
|
close(testfd);
|
||||||
|
for (i = 0; i < nfdrecv; i++) {
|
||||||
|
close(fdrecv[i]);
|
||||||
|
}
|
||||||
|
g_free(fdrecv);
|
||||||
|
}
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
|
||||||
|
@ -393,6 +508,8 @@ int main(int argc, char **argv)
|
||||||
test_io_channel_unix_sync);
|
test_io_channel_unix_sync);
|
||||||
g_test_add_func("/io/channel/socket/unix-async",
|
g_test_add_func("/io/channel/socket/unix-async",
|
||||||
test_io_channel_unix_async);
|
test_io_channel_unix_async);
|
||||||
|
g_test_add_func("/io/channel/socket/unix-fd-pass",
|
||||||
|
test_io_channel_unix_fd_pass);
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
return g_test_run();
|
return g_test_run();
|
||||||
|
|
Loading…
Reference in New Issue