/contrib/wpa/src/utils/eloop_win.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 611 lines · 477 code · 117 blank · 17 comment · 113 complexity · 6a9ac2321e8b7438ab1d3abf18dc4ac8 MD5 · raw file

  1. /*
  2. * Event loop based on Windows events and WaitForMultipleObjects
  3. * Copyright (c) 2002-2006, Jouni Malinen <j@w1.fi>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * Alternatively, this software may be distributed under the terms of BSD
  10. * license.
  11. *
  12. * See README and COPYING for more details.
  13. */
  14. #include "includes.h"
  15. #include <winsock2.h>
  16. #include "common.h"
  17. #include "eloop.h"
  18. struct eloop_sock {
  19. int sock;
  20. void *eloop_data;
  21. void *user_data;
  22. eloop_sock_handler handler;
  23. WSAEVENT event;
  24. };
  25. struct eloop_event {
  26. void *eloop_data;
  27. void *user_data;
  28. eloop_event_handler handler;
  29. HANDLE event;
  30. };
  31. struct eloop_timeout {
  32. struct os_time time;
  33. void *eloop_data;
  34. void *user_data;
  35. eloop_timeout_handler handler;
  36. struct eloop_timeout *next;
  37. };
  38. struct eloop_signal {
  39. int sig;
  40. void *user_data;
  41. eloop_signal_handler handler;
  42. int signaled;
  43. };
  44. struct eloop_data {
  45. int max_sock;
  46. size_t reader_count;
  47. struct eloop_sock *readers;
  48. size_t event_count;
  49. struct eloop_event *events;
  50. struct eloop_timeout *timeout;
  51. int signal_count;
  52. struct eloop_signal *signals;
  53. int signaled;
  54. int pending_terminate;
  55. int terminate;
  56. int reader_table_changed;
  57. struct eloop_signal term_signal;
  58. HANDLE term_event;
  59. HANDLE *handles;
  60. size_t num_handles;
  61. };
  62. static struct eloop_data eloop;
  63. int eloop_init(void)
  64. {
  65. os_memset(&eloop, 0, sizeof(eloop));
  66. eloop.num_handles = 1;
  67. eloop.handles = os_malloc(eloop.num_handles *
  68. sizeof(eloop.handles[0]));
  69. if (eloop.handles == NULL)
  70. return -1;
  71. eloop.term_event = CreateEvent(NULL, FALSE, FALSE, NULL);
  72. if (eloop.term_event == NULL) {
  73. printf("CreateEvent() failed: %d\n",
  74. (int) GetLastError());
  75. os_free(eloop.handles);
  76. return -1;
  77. }
  78. return 0;
  79. }
  80. static int eloop_prepare_handles(void)
  81. {
  82. HANDLE *n;
  83. if (eloop.num_handles > eloop.reader_count + eloop.event_count + 8)
  84. return 0;
  85. n = os_realloc(eloop.handles,
  86. eloop.num_handles * 2 * sizeof(eloop.handles[0]));
  87. if (n == NULL)
  88. return -1;
  89. eloop.handles = n;
  90. eloop.num_handles *= 2;
  91. return 0;
  92. }
  93. int eloop_register_read_sock(int sock, eloop_sock_handler handler,
  94. void *eloop_data, void *user_data)
  95. {
  96. WSAEVENT event;
  97. struct eloop_sock *tmp;
  98. if (eloop_prepare_handles())
  99. return -1;
  100. event = WSACreateEvent();
  101. if (event == WSA_INVALID_EVENT) {
  102. printf("WSACreateEvent() failed: %d\n", WSAGetLastError());
  103. return -1;
  104. }
  105. if (WSAEventSelect(sock, event, FD_READ)) {
  106. printf("WSAEventSelect() failed: %d\n", WSAGetLastError());
  107. WSACloseEvent(event);
  108. return -1;
  109. }
  110. tmp = os_realloc(eloop.readers,
  111. (eloop.reader_count + 1) * sizeof(struct eloop_sock));
  112. if (tmp == NULL) {
  113. WSAEventSelect(sock, event, 0);
  114. WSACloseEvent(event);
  115. return -1;
  116. }
  117. tmp[eloop.reader_count].sock = sock;
  118. tmp[eloop.reader_count].eloop_data = eloop_data;
  119. tmp[eloop.reader_count].user_data = user_data;
  120. tmp[eloop.reader_count].handler = handler;
  121. tmp[eloop.reader_count].event = event;
  122. eloop.reader_count++;
  123. eloop.readers = tmp;
  124. if (sock > eloop.max_sock)
  125. eloop.max_sock = sock;
  126. eloop.reader_table_changed = 1;
  127. return 0;
  128. }
  129. void eloop_unregister_read_sock(int sock)
  130. {
  131. size_t i;
  132. if (eloop.readers == NULL || eloop.reader_count == 0)
  133. return;
  134. for (i = 0; i < eloop.reader_count; i++) {
  135. if (eloop.readers[i].sock == sock)
  136. break;
  137. }
  138. if (i == eloop.reader_count)
  139. return;
  140. WSAEventSelect(eloop.readers[i].sock, eloop.readers[i].event, 0);
  141. WSACloseEvent(eloop.readers[i].event);
  142. if (i != eloop.reader_count - 1) {
  143. os_memmove(&eloop.readers[i], &eloop.readers[i + 1],
  144. (eloop.reader_count - i - 1) *
  145. sizeof(struct eloop_sock));
  146. }
  147. eloop.reader_count--;
  148. eloop.reader_table_changed = 1;
  149. }
  150. int eloop_register_event(void *event, size_t event_size,
  151. eloop_event_handler handler,
  152. void *eloop_data, void *user_data)
  153. {
  154. struct eloop_event *tmp;
  155. HANDLE h = event;
  156. if (event_size != sizeof(HANDLE) || h == INVALID_HANDLE_VALUE)
  157. return -1;
  158. if (eloop_prepare_handles())
  159. return -1;
  160. tmp = os_realloc(eloop.events,
  161. (eloop.event_count + 1) * sizeof(struct eloop_event));
  162. if (tmp == NULL)
  163. return -1;
  164. tmp[eloop.event_count].eloop_data = eloop_data;
  165. tmp[eloop.event_count].user_data = user_data;
  166. tmp[eloop.event_count].handler = handler;
  167. tmp[eloop.event_count].event = h;
  168. eloop.event_count++;
  169. eloop.events = tmp;
  170. return 0;
  171. }
  172. void eloop_unregister_event(void *event, size_t event_size)
  173. {
  174. size_t i;
  175. HANDLE h = event;
  176. if (eloop.events == NULL || eloop.event_count == 0 ||
  177. event_size != sizeof(HANDLE))
  178. return;
  179. for (i = 0; i < eloop.event_count; i++) {
  180. if (eloop.events[i].event == h)
  181. break;
  182. }
  183. if (i == eloop.event_count)
  184. return;
  185. if (i != eloop.event_count - 1) {
  186. os_memmove(&eloop.events[i], &eloop.events[i + 1],
  187. (eloop.event_count - i - 1) *
  188. sizeof(struct eloop_event));
  189. }
  190. eloop.event_count--;
  191. }
  192. int eloop_register_timeout(unsigned int secs, unsigned int usecs,
  193. eloop_timeout_handler handler,
  194. void *eloop_data, void *user_data)
  195. {
  196. struct eloop_timeout *timeout, *tmp, *prev;
  197. timeout = os_malloc(sizeof(*timeout));
  198. if (timeout == NULL)
  199. return -1;
  200. os_get_time(&timeout->time);
  201. timeout->time.sec += secs;
  202. timeout->time.usec += usecs;
  203. while (timeout->time.usec >= 1000000) {
  204. timeout->time.sec++;
  205. timeout->time.usec -= 1000000;
  206. }
  207. timeout->eloop_data = eloop_data;
  208. timeout->user_data = user_data;
  209. timeout->handler = handler;
  210. timeout->next = NULL;
  211. if (eloop.timeout == NULL) {
  212. eloop.timeout = timeout;
  213. return 0;
  214. }
  215. prev = NULL;
  216. tmp = eloop.timeout;
  217. while (tmp != NULL) {
  218. if (os_time_before(&timeout->time, &tmp->time))
  219. break;
  220. prev = tmp;
  221. tmp = tmp->next;
  222. }
  223. if (prev == NULL) {
  224. timeout->next = eloop.timeout;
  225. eloop.timeout = timeout;
  226. } else {
  227. timeout->next = prev->next;
  228. prev->next = timeout;
  229. }
  230. return 0;
  231. }
  232. int eloop_cancel_timeout(eloop_timeout_handler handler,
  233. void *eloop_data, void *user_data)
  234. {
  235. struct eloop_timeout *timeout, *prev, *next;
  236. int removed = 0;
  237. prev = NULL;
  238. timeout = eloop.timeout;
  239. while (timeout != NULL) {
  240. next = timeout->next;
  241. if (timeout->handler == handler &&
  242. (timeout->eloop_data == eloop_data ||
  243. eloop_data == ELOOP_ALL_CTX) &&
  244. (timeout->user_data == user_data ||
  245. user_data == ELOOP_ALL_CTX)) {
  246. if (prev == NULL)
  247. eloop.timeout = next;
  248. else
  249. prev->next = next;
  250. os_free(timeout);
  251. removed++;
  252. } else
  253. prev = timeout;
  254. timeout = next;
  255. }
  256. return removed;
  257. }
  258. int eloop_is_timeout_registered(eloop_timeout_handler handler,
  259. void *eloop_data, void *user_data)
  260. {
  261. struct eloop_timeout *tmp;
  262. tmp = eloop.timeout;
  263. while (tmp != NULL) {
  264. if (tmp->handler == handler &&
  265. tmp->eloop_data == eloop_data &&
  266. tmp->user_data == user_data)
  267. return 1;
  268. tmp = tmp->next;
  269. }
  270. return 0;
  271. }
  272. /* TODO: replace with suitable signal handler */
  273. #if 0
  274. static void eloop_handle_signal(int sig)
  275. {
  276. int i;
  277. eloop.signaled++;
  278. for (i = 0; i < eloop.signal_count; i++) {
  279. if (eloop.signals[i].sig == sig) {
  280. eloop.signals[i].signaled++;
  281. break;
  282. }
  283. }
  284. }
  285. #endif
  286. static void eloop_process_pending_signals(void)
  287. {
  288. int i;
  289. if (eloop.signaled == 0)
  290. return;
  291. eloop.signaled = 0;
  292. if (eloop.pending_terminate) {
  293. eloop.pending_terminate = 0;
  294. }
  295. for (i = 0; i < eloop.signal_count; i++) {
  296. if (eloop.signals[i].signaled) {
  297. eloop.signals[i].signaled = 0;
  298. eloop.signals[i].handler(eloop.signals[i].sig,
  299. eloop.signals[i].user_data);
  300. }
  301. }
  302. if (eloop.term_signal.signaled) {
  303. eloop.term_signal.signaled = 0;
  304. eloop.term_signal.handler(eloop.term_signal.sig,
  305. eloop.term_signal.user_data);
  306. }
  307. }
  308. int eloop_register_signal(int sig, eloop_signal_handler handler,
  309. void *user_data)
  310. {
  311. struct eloop_signal *tmp;
  312. tmp = os_realloc(eloop.signals,
  313. (eloop.signal_count + 1) *
  314. sizeof(struct eloop_signal));
  315. if (tmp == NULL)
  316. return -1;
  317. tmp[eloop.signal_count].sig = sig;
  318. tmp[eloop.signal_count].user_data = user_data;
  319. tmp[eloop.signal_count].handler = handler;
  320. tmp[eloop.signal_count].signaled = 0;
  321. eloop.signal_count++;
  322. eloop.signals = tmp;
  323. /* TODO: register signal handler */
  324. return 0;
  325. }
  326. #ifndef _WIN32_WCE
  327. static BOOL eloop_handle_console_ctrl(DWORD type)
  328. {
  329. switch (type) {
  330. case CTRL_C_EVENT:
  331. case CTRL_BREAK_EVENT:
  332. eloop.signaled++;
  333. eloop.term_signal.signaled++;
  334. SetEvent(eloop.term_event);
  335. return TRUE;
  336. default:
  337. return FALSE;
  338. }
  339. }
  340. #endif /* _WIN32_WCE */
  341. int eloop_register_signal_terminate(eloop_signal_handler handler,
  342. void *user_data)
  343. {
  344. #ifndef _WIN32_WCE
  345. if (SetConsoleCtrlHandler((PHANDLER_ROUTINE) eloop_handle_console_ctrl,
  346. TRUE) == 0) {
  347. printf("SetConsoleCtrlHandler() failed: %d\n",
  348. (int) GetLastError());
  349. return -1;
  350. }
  351. #endif /* _WIN32_WCE */
  352. eloop.term_signal.handler = handler;
  353. eloop.term_signal.user_data = user_data;
  354. return 0;
  355. }
  356. int eloop_register_signal_reconfig(eloop_signal_handler handler,
  357. void *user_data)
  358. {
  359. /* TODO */
  360. return 0;
  361. }
  362. void eloop_run(void)
  363. {
  364. struct os_time tv, now;
  365. DWORD count, ret, timeout, err;
  366. size_t i;
  367. while (!eloop.terminate &&
  368. (eloop.timeout || eloop.reader_count > 0 ||
  369. eloop.event_count > 0)) {
  370. tv.sec = tv.usec = 0;
  371. if (eloop.timeout) {
  372. os_get_time(&now);
  373. if (os_time_before(&now, &eloop.timeout->time))
  374. os_time_sub(&eloop.timeout->time, &now, &tv);
  375. }
  376. count = 0;
  377. for (i = 0; i < eloop.event_count; i++)
  378. eloop.handles[count++] = eloop.events[i].event;
  379. for (i = 0; i < eloop.reader_count; i++)
  380. eloop.handles[count++] = eloop.readers[i].event;
  381. if (eloop.term_event)
  382. eloop.handles[count++] = eloop.term_event;
  383. if (eloop.timeout)
  384. timeout = tv.sec * 1000 + tv.usec / 1000;
  385. else
  386. timeout = INFINITE;
  387. if (count > MAXIMUM_WAIT_OBJECTS) {
  388. printf("WaitForMultipleObjects: Too many events: "
  389. "%d > %d (ignoring extra events)\n",
  390. (int) count, MAXIMUM_WAIT_OBJECTS);
  391. count = MAXIMUM_WAIT_OBJECTS;
  392. }
  393. #ifdef _WIN32_WCE
  394. ret = WaitForMultipleObjects(count, eloop.handles, FALSE,
  395. timeout);
  396. #else /* _WIN32_WCE */
  397. ret = WaitForMultipleObjectsEx(count, eloop.handles, FALSE,
  398. timeout, TRUE);
  399. #endif /* _WIN32_WCE */
  400. err = GetLastError();
  401. eloop_process_pending_signals();
  402. /* check if some registered timeouts have occurred */
  403. if (eloop.timeout) {
  404. struct eloop_timeout *tmp;
  405. os_get_time(&now);
  406. if (!os_time_before(&now, &eloop.timeout->time)) {
  407. tmp = eloop.timeout;
  408. eloop.timeout = eloop.timeout->next;
  409. tmp->handler(tmp->eloop_data,
  410. tmp->user_data);
  411. os_free(tmp);
  412. }
  413. }
  414. if (ret == WAIT_FAILED) {
  415. printf("WaitForMultipleObjects(count=%d) failed: %d\n",
  416. (int) count, (int) err);
  417. os_sleep(1, 0);
  418. continue;
  419. }
  420. #ifndef _WIN32_WCE
  421. if (ret == WAIT_IO_COMPLETION)
  422. continue;
  423. #endif /* _WIN32_WCE */
  424. if (ret == WAIT_TIMEOUT)
  425. continue;
  426. while (ret >= WAIT_OBJECT_0 &&
  427. ret < WAIT_OBJECT_0 + eloop.event_count) {
  428. eloop.events[ret].handler(
  429. eloop.events[ret].eloop_data,
  430. eloop.events[ret].user_data);
  431. ret = WaitForMultipleObjects(eloop.event_count,
  432. eloop.handles, FALSE, 0);
  433. }
  434. eloop.reader_table_changed = 0;
  435. for (i = 0; i < eloop.reader_count; i++) {
  436. WSANETWORKEVENTS events;
  437. if (WSAEnumNetworkEvents(eloop.readers[i].sock,
  438. eloop.readers[i].event,
  439. &events) == 0 &&
  440. (events.lNetworkEvents & FD_READ)) {
  441. eloop.readers[i].handler(
  442. eloop.readers[i].sock,
  443. eloop.readers[i].eloop_data,
  444. eloop.readers[i].user_data);
  445. if (eloop.reader_table_changed)
  446. break;
  447. }
  448. }
  449. }
  450. }
  451. void eloop_terminate(void)
  452. {
  453. eloop.terminate = 1;
  454. SetEvent(eloop.term_event);
  455. }
  456. void eloop_destroy(void)
  457. {
  458. struct eloop_timeout *timeout, *prev;
  459. timeout = eloop.timeout;
  460. while (timeout != NULL) {
  461. prev = timeout;
  462. timeout = timeout->next;
  463. os_free(prev);
  464. }
  465. os_free(eloop.readers);
  466. os_free(eloop.signals);
  467. if (eloop.term_event)
  468. CloseHandle(eloop.term_event);
  469. os_free(eloop.handles);
  470. eloop.handles = NULL;
  471. os_free(eloop.events);
  472. eloop.events = NULL;
  473. }
  474. int eloop_terminated(void)
  475. {
  476. return eloop.terminate;
  477. }
  478. void eloop_wait_for_read_sock(int sock)
  479. {
  480. WSAEVENT event;
  481. event = WSACreateEvent();
  482. if (event == WSA_INVALID_EVENT) {
  483. printf("WSACreateEvent() failed: %d\n", WSAGetLastError());
  484. return;
  485. }
  486. if (WSAEventSelect(sock, event, FD_READ)) {
  487. printf("WSAEventSelect() failed: %d\n", WSAGetLastError());
  488. WSACloseEvent(event);
  489. return ;
  490. }
  491. WaitForSingleObject(event, INFINITE);
  492. WSAEventSelect(sock, event, 0);
  493. WSACloseEvent(event);
  494. }