test-ipc.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  1. // SPDX-License-Identifier: LGPL-2.1-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2013-2014 Intel Corporation. All rights reserved.
  7. *
  8. *
  9. */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #include <stdio.h>
  14. #include <errno.h>
  15. #include <unistd.h>
  16. #include <stdlib.h>
  17. #include <stdbool.h>
  18. #include <inttypes.h>
  19. #include <string.h>
  20. #include <fcntl.h>
  21. #include <sys/socket.h>
  22. #include <sys/un.h>
  23. #include <glib.h>
  24. #include "src/shared/util.h"
  25. #include "src/log.h"
  26. #include "android/ipc-common.h"
  27. #include "android/ipc.h"
  28. static const char HAL_SK_PATH[] = "\0test_hal_socket";
  29. #define SERVICE_ID_MAX 10
  30. struct test_data {
  31. bool disconnect;
  32. const void *cmd;
  33. uint16_t cmd_size;
  34. uint8_t service;
  35. const struct ipc_handler *handlers;
  36. uint8_t handlers_size;
  37. };
  38. struct context {
  39. GMainLoop *main_loop;
  40. int sk;
  41. guint source;
  42. guint cmd_source;
  43. guint notif_source;
  44. GIOChannel *cmd_io;
  45. GIOChannel *notif_io;
  46. const struct test_data *data;
  47. };
  48. static struct ipc *ipc = NULL;
  49. static void context_quit(struct context *context)
  50. {
  51. g_main_loop_quit(context->main_loop);
  52. }
  53. static gboolean cmd_watch(GIOChannel *io, GIOCondition cond,
  54. gpointer user_data)
  55. {
  56. struct context *context = user_data;
  57. const struct test_data *test_data = context->data;
  58. const struct ipc_hdr *sent_msg = test_data->cmd;
  59. uint8_t buf[128];
  60. int sk;
  61. struct ipc_hdr success_resp = {
  62. .service_id = sent_msg->service_id,
  63. .opcode = sent_msg->opcode,
  64. .len = 0,
  65. };
  66. if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
  67. g_assert(test_data->disconnect);
  68. return FALSE;
  69. }
  70. g_assert(!test_data->disconnect);
  71. sk = g_io_channel_unix_get_fd(io);
  72. g_assert(read(sk, buf, sizeof(buf)) == sizeof(struct ipc_hdr));
  73. g_assert(!memcmp(&success_resp, buf, sizeof(struct ipc_hdr)));
  74. context_quit(context);
  75. return TRUE;
  76. }
  77. static gboolean notif_watch(GIOChannel *io, GIOCondition cond,
  78. gpointer user_data)
  79. {
  80. struct context *context = user_data;
  81. const struct test_data *test_data = context->data;
  82. if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
  83. g_assert(test_data->disconnect);
  84. return FALSE;
  85. }
  86. g_assert(!test_data->disconnect);
  87. return TRUE;
  88. }
  89. static gboolean connect_handler(GIOChannel *io, GIOCondition cond,
  90. gpointer user_data)
  91. {
  92. struct context *context = user_data;
  93. const struct test_data *test_data = context->data;
  94. GIOChannel *new_io;
  95. GIOCondition watch_cond;
  96. int sk;
  97. if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
  98. g_assert(FALSE);
  99. return FALSE;
  100. }
  101. g_assert(!context->cmd_source || !context->notif_source);
  102. sk = accept(context->sk, NULL, NULL);
  103. g_assert(sk >= 0);
  104. new_io = g_io_channel_unix_new(sk);
  105. watch_cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
  106. if (context->cmd_source && !context->notif_source) {
  107. context->notif_source = g_io_add_watch(new_io, watch_cond,
  108. notif_watch, context);
  109. g_assert(context->notif_source > 0);
  110. context->notif_io = new_io;
  111. }
  112. if (!context->cmd_source) {
  113. context->cmd_source = g_io_add_watch(new_io, watch_cond,
  114. cmd_watch, context);
  115. context->cmd_io = new_io;
  116. }
  117. if (context->cmd_source && context->notif_source && !test_data->cmd)
  118. context_quit(context);
  119. return TRUE;
  120. }
  121. static struct context *create_context(gconstpointer data)
  122. {
  123. struct context *context = g_new0(struct context, 1);
  124. struct sockaddr_un addr;
  125. GIOChannel *io;
  126. int ret, sk;
  127. context->main_loop = g_main_loop_new(NULL, FALSE);
  128. g_assert(context->main_loop);
  129. sk = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
  130. g_assert(sk >= 0);
  131. memset(&addr, 0, sizeof(addr));
  132. addr.sun_family = AF_UNIX;
  133. memcpy(addr.sun_path, HAL_SK_PATH, sizeof(HAL_SK_PATH));
  134. ret = bind(sk, (struct sockaddr *) &addr, sizeof(addr));
  135. g_assert(ret == 0);
  136. ret = listen(sk, 5);
  137. g_assert(ret == 0);
  138. io = g_io_channel_unix_new(sk);
  139. g_io_channel_set_close_on_unref(io, TRUE);
  140. context->source = g_io_add_watch(io,
  141. G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
  142. connect_handler, context);
  143. g_assert(context->source > 0);
  144. g_io_channel_unref(io);
  145. context->sk = sk;
  146. context->data = data;
  147. return context;
  148. }
  149. static void execute_context(struct context *context)
  150. {
  151. g_main_loop_run(context->main_loop);
  152. g_io_channel_shutdown(context->notif_io, TRUE, NULL);
  153. g_io_channel_shutdown(context->cmd_io, TRUE, NULL);
  154. g_io_channel_unref(context->cmd_io);
  155. g_io_channel_unref(context->notif_io);
  156. g_source_remove(context->notif_source);
  157. g_source_remove(context->cmd_source);
  158. g_source_remove(context->source);
  159. g_main_loop_unref(context->main_loop);
  160. g_free(context);
  161. }
  162. static void disconnected(void *data)
  163. {
  164. struct context *context = data;
  165. g_assert(context->data->disconnect);
  166. context_quit(context);
  167. }
  168. static void test_init(gconstpointer data)
  169. {
  170. struct context *context = create_context(data);
  171. ipc = ipc_init(HAL_SK_PATH, sizeof(HAL_SK_PATH), SERVICE_ID_MAX,
  172. true, NULL, NULL);
  173. g_assert(ipc);
  174. execute_context(context);
  175. ipc_cleanup(ipc);
  176. ipc = NULL;
  177. }
  178. static gboolean send_cmd(gpointer user_data)
  179. {
  180. struct context *context = user_data;
  181. const struct test_data *test_data = context->data;
  182. int sk;
  183. sk = g_io_channel_unix_get_fd(context->cmd_io);
  184. g_assert(sk >= 0);
  185. g_assert(write(sk, test_data->cmd, test_data->cmd_size) ==
  186. test_data->cmd_size);
  187. return FALSE;
  188. }
  189. static gboolean register_service(gpointer user_data)
  190. {
  191. struct context *context = user_data;
  192. const struct test_data *test_data = context->data;
  193. ipc_register(ipc, test_data->service, test_data->handlers,
  194. test_data->handlers_size);
  195. return FALSE;
  196. }
  197. static gboolean unregister_service(gpointer user_data)
  198. {
  199. struct context *context = user_data;
  200. const struct test_data *test_data = context->data;
  201. ipc_unregister(ipc, test_data->service);
  202. return FALSE;
  203. }
  204. static void test_cmd(gconstpointer data)
  205. {
  206. struct context *context = create_context(data);
  207. ipc = ipc_init(HAL_SK_PATH, sizeof(HAL_SK_PATH), SERVICE_ID_MAX,
  208. true, disconnected, context);
  209. g_assert(ipc);
  210. g_idle_add(send_cmd, context);
  211. execute_context(context);
  212. ipc_cleanup(ipc);
  213. ipc = NULL;
  214. }
  215. static void test_cmd_reg(gconstpointer data)
  216. {
  217. struct context *context = create_context(data);
  218. const struct test_data *test_data = context->data;
  219. ipc = ipc_init(HAL_SK_PATH, sizeof(HAL_SK_PATH), SERVICE_ID_MAX,
  220. true, disconnected, context);
  221. g_assert(ipc);
  222. g_idle_add(register_service, context);
  223. g_idle_add(send_cmd, context);
  224. execute_context(context);
  225. ipc_unregister(ipc, test_data->service);
  226. ipc_cleanup(ipc);
  227. ipc = NULL;
  228. }
  229. static void test_cmd_reg_1(gconstpointer data)
  230. {
  231. struct context *context = create_context(data);
  232. ipc = ipc_init(HAL_SK_PATH, sizeof(HAL_SK_PATH), SERVICE_ID_MAX,
  233. true, disconnected, context);
  234. g_assert(ipc);
  235. g_idle_add(register_service, context);
  236. g_idle_add(unregister_service, context);
  237. g_idle_add(send_cmd, context);
  238. execute_context(context);
  239. ipc_cleanup(ipc);
  240. ipc = NULL;
  241. }
  242. static void test_cmd_handler_1(const void *buf, uint16_t len)
  243. {
  244. ipc_send_rsp(ipc, 0, 1, 0);
  245. }
  246. static void test_cmd_handler_2(const void *buf, uint16_t len)
  247. {
  248. ipc_send_rsp(ipc, 0, 2, 0);
  249. }
  250. static void test_cmd_handler_invalid(const void *buf, uint16_t len)
  251. {
  252. g_assert(false);
  253. }
  254. static const struct test_data test_init_1 = {};
  255. static const struct ipc_hdr test_cmd_1_hdr = {
  256. .service_id = 0,
  257. .opcode = 1,
  258. .len = 0
  259. };
  260. static const struct ipc_hdr test_cmd_2_hdr = {
  261. .service_id = 0,
  262. .opcode = 2,
  263. .len = 0
  264. };
  265. static const struct test_data test_cmd_service_invalid_1 = {
  266. .cmd = &test_cmd_1_hdr,
  267. .cmd_size = sizeof(test_cmd_1_hdr),
  268. .disconnect = true,
  269. };
  270. static const struct ipc_handler cmd_handlers[] = {
  271. { test_cmd_handler_1, false, 0 }
  272. };
  273. static const struct test_data test_cmd_service_valid_1 = {
  274. .cmd = &test_cmd_1_hdr,
  275. .cmd_size = sizeof(test_cmd_1_hdr),
  276. .service = 0,
  277. .handlers = cmd_handlers,
  278. .handlers_size = 1
  279. };
  280. static const struct test_data test_cmd_service_invalid_2 = {
  281. .cmd = &test_cmd_1_hdr,
  282. .cmd_size = sizeof(test_cmd_1_hdr),
  283. .service = 0,
  284. .handlers = cmd_handlers,
  285. .handlers_size = 1,
  286. .disconnect = true,
  287. };
  288. static const struct ipc_handler cmd_handlers_invalid_2[] = {
  289. { test_cmd_handler_1, false, 0 },
  290. { test_cmd_handler_invalid, false, 0 }
  291. };
  292. static const struct ipc_handler cmd_handlers_invalid_1[] = {
  293. { test_cmd_handler_invalid, false, 0 },
  294. { test_cmd_handler_2, false, 0 },
  295. };
  296. static const struct test_data test_cmd_opcode_valid_1 = {
  297. .cmd = &test_cmd_1_hdr,
  298. .cmd_size = sizeof(test_cmd_1_hdr),
  299. .service = 0,
  300. .handlers = cmd_handlers_invalid_2,
  301. .handlers_size = 2,
  302. };
  303. static const struct test_data test_cmd_opcode_valid_2 = {
  304. .cmd = &test_cmd_2_hdr,
  305. .cmd_size = sizeof(test_cmd_2_hdr),
  306. .service = 0,
  307. .handlers = cmd_handlers_invalid_1,
  308. .handlers_size = 2,
  309. };
  310. static const struct test_data test_cmd_opcode_invalid_1 = {
  311. .cmd = &test_cmd_2_hdr,
  312. .cmd_size = sizeof(test_cmd_2_hdr),
  313. .service = 0,
  314. .handlers = cmd_handlers,
  315. .handlers_size = 1,
  316. .disconnect = true,
  317. };
  318. static const struct test_data test_cmd_hdr_invalid = {
  319. .cmd = &test_cmd_1_hdr,
  320. .cmd_size = sizeof(test_cmd_1_hdr) - 1,
  321. .service = 0,
  322. .handlers = cmd_handlers,
  323. .handlers_size = 1,
  324. .disconnect = true,
  325. };
  326. #define VARDATA_EX1 "some data example"
  327. struct vardata {
  328. struct ipc_hdr hdr;
  329. uint8_t data[IPC_MTU - sizeof(struct ipc_hdr)];
  330. } __attribute__((packed));
  331. static const struct vardata test_cmd_vardata = {
  332. .hdr.service_id = 0,
  333. .hdr.opcode = 1,
  334. .hdr.len = sizeof(VARDATA_EX1),
  335. .data = VARDATA_EX1,
  336. };
  337. static const struct ipc_handler cmd_vardata_handlers[] = {
  338. { test_cmd_handler_1, true, sizeof(VARDATA_EX1) }
  339. };
  340. static const struct test_data test_cmd_vardata_valid = {
  341. .cmd = &test_cmd_vardata,
  342. .cmd_size = sizeof(struct ipc_hdr) + sizeof(VARDATA_EX1),
  343. .service = 0,
  344. .handlers = cmd_vardata_handlers,
  345. .handlers_size = 1,
  346. };
  347. static const struct ipc_handler cmd_vardata_handlers_valid2[] = {
  348. { test_cmd_handler_1, true, sizeof(VARDATA_EX1) - 1 }
  349. };
  350. static const struct test_data test_cmd_vardata_valid_2 = {
  351. .cmd = &test_cmd_vardata,
  352. .cmd_size = sizeof(struct ipc_hdr) + sizeof(VARDATA_EX1),
  353. .service = 0,
  354. .handlers = cmd_vardata_handlers_valid2,
  355. .handlers_size = 1,
  356. };
  357. static const struct test_data test_cmd_vardata_invalid_1 = {
  358. .cmd = &test_cmd_vardata,
  359. .cmd_size = sizeof(struct ipc_hdr) + sizeof(VARDATA_EX1) - 1,
  360. .service = 0,
  361. .handlers = cmd_vardata_handlers,
  362. .handlers_size = 1,
  363. .disconnect = true,
  364. };
  365. static const struct ipc_hdr test_cmd_service_offrange_hdr = {
  366. .service_id = SERVICE_ID_MAX + 1,
  367. .opcode = 1,
  368. .len = 0
  369. };
  370. static const struct test_data test_cmd_service_offrange = {
  371. .cmd = &test_cmd_service_offrange_hdr,
  372. .cmd_size = sizeof(struct ipc_hdr),
  373. .service = 0,
  374. .handlers = cmd_handlers,
  375. .handlers_size = 1,
  376. .disconnect = true,
  377. };
  378. static const struct vardata test_cmd_invalid_data_1 = {
  379. .hdr.service_id = 0,
  380. .hdr.opcode = 1,
  381. .hdr.len = sizeof(VARDATA_EX1),
  382. .data = VARDATA_EX1,
  383. };
  384. static const struct test_data test_cmd_msg_invalid_1 = {
  385. .cmd = &test_cmd_invalid_data_1,
  386. .cmd_size = sizeof(struct ipc_hdr) + sizeof(VARDATA_EX1) - 1,
  387. .service = 0,
  388. .handlers = cmd_handlers,
  389. .handlers_size = 1,
  390. .disconnect = true,
  391. };
  392. static const struct vardata test_cmd_invalid_data_2 = {
  393. .hdr.service_id = 0,
  394. .hdr.opcode = 1,
  395. .hdr.len = sizeof(VARDATA_EX1) - 1,
  396. .data = VARDATA_EX1,
  397. };
  398. static const struct test_data test_cmd_msg_invalid_2 = {
  399. .cmd = &test_cmd_invalid_data_2,
  400. .cmd_size = sizeof(struct ipc_hdr) + sizeof(VARDATA_EX1),
  401. .service = 0,
  402. .handlers = cmd_handlers,
  403. .handlers_size = 1,
  404. .disconnect = true,
  405. };
  406. int main(int argc, char *argv[])
  407. {
  408. g_test_init(&argc, &argv, NULL);
  409. if (g_test_verbose())
  410. __btd_log_init("*", 0);
  411. g_test_add_data_func("/android_ipc/init", &test_init_1, test_init);
  412. g_test_add_data_func("/android_ipc/service_invalid_1",
  413. &test_cmd_service_invalid_1, test_cmd);
  414. g_test_add_data_func("/android_ipc/service_valid_1",
  415. &test_cmd_service_valid_1, test_cmd_reg);
  416. g_test_add_data_func("/android_ipc/service_invalid_2",
  417. &test_cmd_service_invalid_2, test_cmd_reg_1);
  418. g_test_add_data_func("/android_ipc/opcode_valid_1",
  419. &test_cmd_opcode_valid_1, test_cmd_reg);
  420. g_test_add_data_func("/android_ipc/opcode_valid_2",
  421. &test_cmd_opcode_valid_2, test_cmd_reg);
  422. g_test_add_data_func("/android_ipc/opcode_invalid_1",
  423. &test_cmd_opcode_invalid_1, test_cmd_reg);
  424. g_test_add_data_func("/android_ipc/vardata_valid",
  425. &test_cmd_vardata_valid, test_cmd_reg);
  426. g_test_add_data_func("/android_ipc/vardata_valid_2",
  427. &test_cmd_vardata_valid_2, test_cmd_reg);
  428. g_test_add_data_func("/android_ipc/vardata_invalid_1",
  429. &test_cmd_vardata_invalid_1, test_cmd_reg);
  430. g_test_add_data_func("/android_ipc/service_offrange",
  431. &test_cmd_service_offrange, test_cmd_reg);
  432. g_test_add_data_func("/android_ipc/hdr_invalid",
  433. &test_cmd_hdr_invalid, test_cmd_reg);
  434. g_test_add_data_func("/android_ipc/msg_invalid_1",
  435. &test_cmd_msg_invalid_1, test_cmd_reg);
  436. g_test_add_data_func("/android_ipc/msg_invalid_2",
  437. &test_cmd_msg_invalid_2, test_cmd_reg);
  438. return g_test_run();
  439. }