2
0

test-io-channel-socket.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  1. /*
  2. * QEMU I/O channel sockets test
  3. *
  4. * Copyright (c) 2015-2016 Red Hat, Inc.
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  18. *
  19. */
  20. #include "qemu/osdep.h"
  21. #include "io/channel-socket.h"
  22. #include "io/channel-util.h"
  23. #include "io-channel-helpers.h"
  24. #include "socket-helpers.h"
  25. #include "qapi/error.h"
  26. #include "qemu/module.h"
  27. static void test_io_channel_set_socket_bufs(QIOChannel *src,
  28. QIOChannel *dst)
  29. {
  30. int buflen = 64 * 1024;
  31. /*
  32. * Make the socket buffers small so that we see
  33. * the effects of partial reads/writes
  34. */
  35. setsockopt(((QIOChannelSocket *)src)->fd,
  36. SOL_SOCKET, SO_SNDBUF,
  37. (char *)&buflen,
  38. sizeof(buflen));
  39. setsockopt(((QIOChannelSocket *)dst)->fd,
  40. SOL_SOCKET, SO_SNDBUF,
  41. (char *)&buflen,
  42. sizeof(buflen));
  43. }
  44. static void test_io_channel_setup_sync(SocketAddress *listen_addr,
  45. SocketAddress *connect_addr,
  46. QIOChannel **srv,
  47. QIOChannel **src,
  48. QIOChannel **dst)
  49. {
  50. QIOChannelSocket *lioc;
  51. lioc = qio_channel_socket_new();
  52. qio_channel_socket_listen_sync(lioc, listen_addr, 1, &error_abort);
  53. if (listen_addr->type == SOCKET_ADDRESS_TYPE_INET) {
  54. SocketAddress *laddr = qio_channel_socket_get_local_address(
  55. lioc, &error_abort);
  56. g_free(connect_addr->u.inet.port);
  57. connect_addr->u.inet.port = g_strdup(laddr->u.inet.port);
  58. qapi_free_SocketAddress(laddr);
  59. }
  60. *src = QIO_CHANNEL(qio_channel_socket_new());
  61. qio_channel_socket_connect_sync(
  62. QIO_CHANNEL_SOCKET(*src), connect_addr, &error_abort);
  63. qio_channel_set_delay(*src, false);
  64. qio_channel_wait(QIO_CHANNEL(lioc), G_IO_IN);
  65. *dst = QIO_CHANNEL(qio_channel_socket_accept(lioc, &error_abort));
  66. g_assert(*dst);
  67. test_io_channel_set_socket_bufs(*src, *dst);
  68. *srv = QIO_CHANNEL(lioc);
  69. }
  70. struct TestIOChannelData {
  71. bool err;
  72. GMainLoop *loop;
  73. };
  74. static void test_io_channel_complete(QIOTask *task,
  75. gpointer opaque)
  76. {
  77. struct TestIOChannelData *data = opaque;
  78. data->err = qio_task_propagate_error(task, NULL);
  79. g_main_loop_quit(data->loop);
  80. }
  81. static void test_io_channel_setup_async(SocketAddress *listen_addr,
  82. SocketAddress *connect_addr,
  83. QIOChannel **srv,
  84. QIOChannel **src,
  85. QIOChannel **dst)
  86. {
  87. QIOChannelSocket *lioc;
  88. struct TestIOChannelData data;
  89. data.loop = g_main_loop_new(g_main_context_default(),
  90. TRUE);
  91. lioc = qio_channel_socket_new();
  92. qio_channel_socket_listen_async(
  93. lioc, listen_addr, 1,
  94. test_io_channel_complete, &data, NULL, NULL);
  95. g_main_loop_run(data.loop);
  96. g_main_context_iteration(g_main_context_default(), FALSE);
  97. g_assert(!data.err);
  98. if (listen_addr->type == SOCKET_ADDRESS_TYPE_INET) {
  99. SocketAddress *laddr = qio_channel_socket_get_local_address(
  100. lioc, &error_abort);
  101. g_free(connect_addr->u.inet.port);
  102. connect_addr->u.inet.port = g_strdup(laddr->u.inet.port);
  103. qapi_free_SocketAddress(laddr);
  104. }
  105. *src = QIO_CHANNEL(qio_channel_socket_new());
  106. qio_channel_socket_connect_async(
  107. QIO_CHANNEL_SOCKET(*src), connect_addr,
  108. test_io_channel_complete, &data, NULL, NULL);
  109. g_main_loop_run(data.loop);
  110. g_main_context_iteration(g_main_context_default(), FALSE);
  111. g_assert(!data.err);
  112. qio_channel_wait(QIO_CHANNEL(lioc), G_IO_IN);
  113. *dst = QIO_CHANNEL(qio_channel_socket_accept(lioc, &error_abort));
  114. g_assert(*dst);
  115. qio_channel_set_delay(*src, false);
  116. test_io_channel_set_socket_bufs(*src, *dst);
  117. *srv = QIO_CHANNEL(lioc);
  118. g_main_loop_unref(data.loop);
  119. }
  120. static void test_io_channel_socket_path_exists(SocketAddress *addr,
  121. bool expectExists)
  122. {
  123. if (addr->type != SOCKET_ADDRESS_TYPE_UNIX) {
  124. return;
  125. }
  126. g_assert(g_file_test(addr->u.q_unix.path,
  127. G_FILE_TEST_EXISTS) == expectExists);
  128. }
  129. static void test_io_channel(bool async,
  130. SocketAddress *listen_addr,
  131. SocketAddress *connect_addr,
  132. bool passFD)
  133. {
  134. QIOChannel *src, *dst, *srv;
  135. QIOChannelTest *test;
  136. if (async) {
  137. test_io_channel_setup_async(listen_addr, connect_addr,
  138. &srv, &src, &dst);
  139. g_assert(!passFD ||
  140. qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS));
  141. g_assert(!passFD ||
  142. qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS));
  143. g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_SHUTDOWN));
  144. g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_SHUTDOWN));
  145. test_io_channel_socket_path_exists(listen_addr, true);
  146. test = qio_channel_test_new();
  147. qio_channel_test_run_threads(test, true, src, dst);
  148. qio_channel_test_validate(test);
  149. test_io_channel_socket_path_exists(listen_addr, true);
  150. /* unref without close, to ensure finalize() cleans up */
  151. object_unref(OBJECT(src));
  152. object_unref(OBJECT(dst));
  153. test_io_channel_socket_path_exists(listen_addr, true);
  154. object_unref(OBJECT(srv));
  155. test_io_channel_socket_path_exists(listen_addr, false);
  156. test_io_channel_setup_async(listen_addr, connect_addr,
  157. &srv, &src, &dst);
  158. g_assert(!passFD ||
  159. qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS));
  160. g_assert(!passFD ||
  161. qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS));
  162. g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_SHUTDOWN));
  163. g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_SHUTDOWN));
  164. test = qio_channel_test_new();
  165. qio_channel_test_run_threads(test, false, src, dst);
  166. qio_channel_test_validate(test);
  167. /* close before unref, to ensure finalize copes with already closed */
  168. qio_channel_close(src, &error_abort);
  169. qio_channel_close(dst, &error_abort);
  170. test_io_channel_socket_path_exists(listen_addr, true);
  171. object_unref(OBJECT(src));
  172. object_unref(OBJECT(dst));
  173. test_io_channel_socket_path_exists(listen_addr, true);
  174. qio_channel_close(srv, &error_abort);
  175. test_io_channel_socket_path_exists(listen_addr, false);
  176. object_unref(OBJECT(srv));
  177. test_io_channel_socket_path_exists(listen_addr, false);
  178. } else {
  179. test_io_channel_setup_sync(listen_addr, connect_addr,
  180. &srv, &src, &dst);
  181. g_assert(!passFD ||
  182. qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS));
  183. g_assert(!passFD ||
  184. qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS));
  185. g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_SHUTDOWN));
  186. g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_SHUTDOWN));
  187. test_io_channel_socket_path_exists(listen_addr, true);
  188. test = qio_channel_test_new();
  189. qio_channel_test_run_threads(test, true, src, dst);
  190. qio_channel_test_validate(test);
  191. test_io_channel_socket_path_exists(listen_addr, true);
  192. /* unref without close, to ensure finalize() cleans up */
  193. object_unref(OBJECT(src));
  194. object_unref(OBJECT(dst));
  195. test_io_channel_socket_path_exists(listen_addr, true);
  196. object_unref(OBJECT(srv));
  197. test_io_channel_socket_path_exists(listen_addr, false);
  198. test_io_channel_setup_sync(listen_addr, connect_addr,
  199. &srv, &src, &dst);
  200. g_assert(!passFD ||
  201. qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS));
  202. g_assert(!passFD ||
  203. qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS));
  204. g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_SHUTDOWN));
  205. g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_SHUTDOWN));
  206. test = qio_channel_test_new();
  207. qio_channel_test_run_threads(test, false, src, dst);
  208. qio_channel_test_validate(test);
  209. test_io_channel_socket_path_exists(listen_addr, true);
  210. /* close before unref, to ensure finalize copes with already closed */
  211. qio_channel_close(src, &error_abort);
  212. qio_channel_close(dst, &error_abort);
  213. test_io_channel_socket_path_exists(listen_addr, true);
  214. object_unref(OBJECT(src));
  215. object_unref(OBJECT(dst));
  216. test_io_channel_socket_path_exists(listen_addr, true);
  217. qio_channel_close(srv, &error_abort);
  218. test_io_channel_socket_path_exists(listen_addr, false);
  219. object_unref(OBJECT(srv));
  220. test_io_channel_socket_path_exists(listen_addr, false);
  221. }
  222. }
  223. static void test_io_channel_ipv4(bool async)
  224. {
  225. SocketAddress *listen_addr = g_new0(SocketAddress, 1);
  226. SocketAddress *connect_addr = g_new0(SocketAddress, 1);
  227. listen_addr->type = SOCKET_ADDRESS_TYPE_INET;
  228. listen_addr->u.inet = (InetSocketAddress) {
  229. .host = g_strdup("127.0.0.1"),
  230. .port = NULL, /* Auto-select */
  231. };
  232. connect_addr->type = SOCKET_ADDRESS_TYPE_INET;
  233. connect_addr->u.inet = (InetSocketAddress) {
  234. .host = g_strdup("127.0.0.1"),
  235. .port = NULL, /* Filled in later */
  236. };
  237. test_io_channel(async, listen_addr, connect_addr, false);
  238. qapi_free_SocketAddress(listen_addr);
  239. qapi_free_SocketAddress(connect_addr);
  240. }
  241. static void test_io_channel_ipv4_sync(void)
  242. {
  243. return test_io_channel_ipv4(false);
  244. }
  245. static void test_io_channel_ipv4_async(void)
  246. {
  247. return test_io_channel_ipv4(true);
  248. }
  249. static void test_io_channel_ipv6(bool async)
  250. {
  251. SocketAddress *listen_addr = g_new0(SocketAddress, 1);
  252. SocketAddress *connect_addr = g_new0(SocketAddress, 1);
  253. listen_addr->type = SOCKET_ADDRESS_TYPE_INET;
  254. listen_addr->u.inet = (InetSocketAddress) {
  255. .host = g_strdup("::1"),
  256. .port = NULL, /* Auto-select */
  257. };
  258. connect_addr->type = SOCKET_ADDRESS_TYPE_INET;
  259. connect_addr->u.inet = (InetSocketAddress) {
  260. .host = g_strdup("::1"),
  261. .port = NULL, /* Filled in later */
  262. };
  263. test_io_channel(async, listen_addr, connect_addr, false);
  264. qapi_free_SocketAddress(listen_addr);
  265. qapi_free_SocketAddress(connect_addr);
  266. }
  267. static void test_io_channel_ipv6_sync(void)
  268. {
  269. return test_io_channel_ipv6(false);
  270. }
  271. static void test_io_channel_ipv6_async(void)
  272. {
  273. return test_io_channel_ipv6(true);
  274. }
  275. #ifndef _WIN32
  276. static void test_io_channel_unix(bool async)
  277. {
  278. SocketAddress *listen_addr = g_new0(SocketAddress, 1);
  279. SocketAddress *connect_addr = g_new0(SocketAddress, 1);
  280. #define TEST_SOCKET "test-io-channel-socket.sock"
  281. listen_addr->type = SOCKET_ADDRESS_TYPE_UNIX;
  282. listen_addr->u.q_unix.path = g_strdup(TEST_SOCKET);
  283. connect_addr->type = SOCKET_ADDRESS_TYPE_UNIX;
  284. connect_addr->u.q_unix.path = g_strdup(TEST_SOCKET);
  285. test_io_channel(async, listen_addr, connect_addr, true);
  286. qapi_free_SocketAddress(listen_addr);
  287. qapi_free_SocketAddress(connect_addr);
  288. }
  289. static void test_io_channel_unix_sync(void)
  290. {
  291. return test_io_channel_unix(false);
  292. }
  293. static void test_io_channel_unix_async(void)
  294. {
  295. return test_io_channel_unix(true);
  296. }
  297. static void test_io_channel_unix_fd_pass(void)
  298. {
  299. SocketAddress *listen_addr = g_new0(SocketAddress, 1);
  300. SocketAddress *connect_addr = g_new0(SocketAddress, 1);
  301. QIOChannel *src, *dst, *srv;
  302. int testfd;
  303. int fdsend[3];
  304. int *fdrecv = NULL;
  305. size_t nfdrecv = 0;
  306. size_t i;
  307. char bufsend[12], bufrecv[12];
  308. struct iovec iosend[1], iorecv[1];
  309. #define TEST_SOCKET "test-io-channel-socket.sock"
  310. #define TEST_FILE "test-io-channel-socket.txt"
  311. testfd = open(TEST_FILE, O_RDWR|O_TRUNC|O_CREAT, 0700);
  312. g_assert(testfd != -1);
  313. fdsend[0] = testfd;
  314. fdsend[1] = testfd;
  315. fdsend[2] = testfd;
  316. listen_addr->type = SOCKET_ADDRESS_TYPE_UNIX;
  317. listen_addr->u.q_unix.path = g_strdup(TEST_SOCKET);
  318. connect_addr->type = SOCKET_ADDRESS_TYPE_UNIX;
  319. connect_addr->u.q_unix.path = g_strdup(TEST_SOCKET);
  320. test_io_channel_setup_sync(listen_addr, connect_addr, &srv, &src, &dst);
  321. memcpy(bufsend, "Hello World", G_N_ELEMENTS(bufsend));
  322. iosend[0].iov_base = bufsend;
  323. iosend[0].iov_len = G_N_ELEMENTS(bufsend);
  324. iorecv[0].iov_base = bufrecv;
  325. iorecv[0].iov_len = G_N_ELEMENTS(bufrecv);
  326. g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS));
  327. g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS));
  328. qio_channel_writev_full(src,
  329. iosend,
  330. G_N_ELEMENTS(iosend),
  331. fdsend,
  332. G_N_ELEMENTS(fdsend),
  333. &error_abort);
  334. qio_channel_readv_full(dst,
  335. iorecv,
  336. G_N_ELEMENTS(iorecv),
  337. &fdrecv,
  338. &nfdrecv,
  339. &error_abort);
  340. g_assert(nfdrecv == G_N_ELEMENTS(fdsend));
  341. /* Each recvd FD should be different from sent FD */
  342. for (i = 0; i < nfdrecv; i++) {
  343. g_assert_cmpint(fdrecv[i], !=, testfd);
  344. }
  345. /* Each recvd FD should be different from each other */
  346. g_assert_cmpint(fdrecv[0], !=, fdrecv[1]);
  347. g_assert_cmpint(fdrecv[0], !=, fdrecv[2]);
  348. g_assert_cmpint(fdrecv[1], !=, fdrecv[2]);
  349. /* Check the I/O buf we sent at the same time matches */
  350. g_assert(memcmp(bufsend, bufrecv, G_N_ELEMENTS(bufsend)) == 0);
  351. /* Write some data into the FD we received */
  352. g_assert(write(fdrecv[0], bufsend, G_N_ELEMENTS(bufsend)) ==
  353. G_N_ELEMENTS(bufsend));
  354. /* Read data from the original FD and make sure it matches */
  355. memset(bufrecv, 0, G_N_ELEMENTS(bufrecv));
  356. g_assert(lseek(testfd, 0, SEEK_SET) == 0);
  357. g_assert(read(testfd, bufrecv, G_N_ELEMENTS(bufrecv)) ==
  358. G_N_ELEMENTS(bufrecv));
  359. g_assert(memcmp(bufsend, bufrecv, G_N_ELEMENTS(bufsend)) == 0);
  360. object_unref(OBJECT(src));
  361. object_unref(OBJECT(dst));
  362. object_unref(OBJECT(srv));
  363. qapi_free_SocketAddress(listen_addr);
  364. qapi_free_SocketAddress(connect_addr);
  365. unlink(TEST_SOCKET);
  366. unlink(TEST_FILE);
  367. close(testfd);
  368. for (i = 0; i < nfdrecv; i++) {
  369. close(fdrecv[i]);
  370. }
  371. g_free(fdrecv);
  372. }
  373. static void test_io_channel_unix_listen_cleanup(void)
  374. {
  375. QIOChannelSocket *ioc;
  376. struct sockaddr_un un;
  377. int sock;
  378. #define TEST_SOCKET "test-io-channel-socket.sock"
  379. ioc = qio_channel_socket_new();
  380. /* Manually bind ioc without calling the qio api to avoid setting
  381. * the LISTEN feature */
  382. sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
  383. memset(&un, 0, sizeof(un));
  384. un.sun_family = AF_UNIX;
  385. snprintf(un.sun_path, sizeof(un.sun_path), "%s", TEST_SOCKET);
  386. unlink(TEST_SOCKET);
  387. bind(sock, (struct sockaddr *)&un, sizeof(un));
  388. ioc->fd = sock;
  389. ioc->localAddrLen = sizeof(ioc->localAddr);
  390. getsockname(sock, (struct sockaddr *)&ioc->localAddr,
  391. &ioc->localAddrLen);
  392. g_assert(g_file_test(TEST_SOCKET, G_FILE_TEST_EXISTS));
  393. object_unref(OBJECT(ioc));
  394. g_assert(g_file_test(TEST_SOCKET, G_FILE_TEST_EXISTS));
  395. unlink(TEST_SOCKET);
  396. }
  397. #endif /* _WIN32 */
  398. static void test_io_channel_ipv4_fd(void)
  399. {
  400. QIOChannel *ioc;
  401. int fd = -1;
  402. struct sockaddr_in sa = {
  403. .sin_family = AF_INET,
  404. .sin_addr = {
  405. .s_addr = htonl(INADDR_LOOPBACK),
  406. }
  407. /* Leave port unset for auto-assign */
  408. };
  409. socklen_t salen = sizeof(sa);
  410. fd = socket(AF_INET, SOCK_STREAM, 0);
  411. g_assert_cmpint(fd, >, -1);
  412. g_assert_cmpint(bind(fd, (struct sockaddr *)&sa, salen), ==, 0);
  413. ioc = qio_channel_new_fd(fd, &error_abort);
  414. g_assert_cmpstr(object_get_typename(OBJECT(ioc)),
  415. ==,
  416. TYPE_QIO_CHANNEL_SOCKET);
  417. object_unref(OBJECT(ioc));
  418. }
  419. int main(int argc, char **argv)
  420. {
  421. bool has_ipv4, has_ipv6;
  422. module_call_init(MODULE_INIT_QOM);
  423. socket_init();
  424. g_test_init(&argc, &argv, NULL);
  425. /* We're creating actual IPv4/6 sockets, so we should
  426. * check if the host running tests actually supports
  427. * each protocol to avoid breaking tests on machines
  428. * with either IPv4 or IPv6 disabled.
  429. */
  430. if (socket_check_protocol_support(&has_ipv4, &has_ipv6) < 0) {
  431. g_printerr("socket_check_protocol_support() failed\n");
  432. goto end;
  433. }
  434. if (has_ipv4) {
  435. g_test_add_func("/io/channel/socket/ipv4-sync",
  436. test_io_channel_ipv4_sync);
  437. g_test_add_func("/io/channel/socket/ipv4-async",
  438. test_io_channel_ipv4_async);
  439. g_test_add_func("/io/channel/socket/ipv4-fd",
  440. test_io_channel_ipv4_fd);
  441. }
  442. if (has_ipv6) {
  443. g_test_add_func("/io/channel/socket/ipv6-sync",
  444. test_io_channel_ipv6_sync);
  445. g_test_add_func("/io/channel/socket/ipv6-async",
  446. test_io_channel_ipv6_async);
  447. }
  448. #ifndef _WIN32
  449. g_test_add_func("/io/channel/socket/unix-sync",
  450. test_io_channel_unix_sync);
  451. g_test_add_func("/io/channel/socket/unix-async",
  452. test_io_channel_unix_async);
  453. g_test_add_func("/io/channel/socket/unix-fd-pass",
  454. test_io_channel_unix_fd_pass);
  455. g_test_add_func("/io/channel/socket/unix-listen-cleanup",
  456. test_io_channel_unix_listen_cleanup);
  457. #endif /* _WIN32 */
  458. end:
  459. return g_test_run();
  460. }