A clone of btpd with my configuration changes.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

win32.c 10 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. /*
  2. * Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
  3. * Copyright 2003 Michael A. Davis <mike@datanerds.net>
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. The name of the author may not be used to endorse or promote products
  15. * derived from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. #include "config.h"
  29. #include <winsock2.h>
  30. #include <windows.h>
  31. #include <sys/types.h>
  32. #include <sys/queue.h>
  33. #include <sys/tree.h>
  34. #include <signal.h>
  35. #include <stdio.h>
  36. #include <stdlib.h>
  37. #include <string.h>
  38. #include <errno.h>
  39. #include <assert.h>
  40. #include "log.h"
  41. #include "event.h"
  42. #include "event-internal.h"
  43. #define XFREE(ptr) do { if (ptr) free(ptr); } while(0)
  44. extern struct event_list timequeue;
  45. extern struct event_list addqueue;
  46. extern struct event_list signalqueue;
  47. struct win_fd_set {
  48. u_int fd_count;
  49. SOCKET fd_array[1];
  50. };
  51. int evsigcaught[NSIG];
  52. volatile sig_atomic_t signal_caught = 0;
  53. /* MSDN says this is required to handle SIGFPE */
  54. volatile double SIGFPE_REQ = 0.0f;
  55. static void signal_handler(int sig);
  56. void signal_process(void);
  57. int signal_recalc(void);
  58. struct win32op {
  59. int fd_setsz;
  60. struct win_fd_set *readset_in;
  61. struct win_fd_set *writeset_in;
  62. struct win_fd_set *readset_out;
  63. struct win_fd_set *writeset_out;
  64. struct win_fd_set *exset_out;
  65. int n_events;
  66. int n_events_alloc;
  67. struct event **events;
  68. };
  69. void *win32_init (void);
  70. int win32_insert (void *, struct event *);
  71. int win32_del (void *, struct event *);
  72. int win32_recalc (struct event_base *base, void *, int);
  73. int win32_dispatch (struct event_base *base, void *, struct timeval *);
  74. void win32_dealloc (void *);
  75. struct eventop win32ops = {
  76. "win32",
  77. win32_init,
  78. win32_insert,
  79. win32_del,
  80. win32_recalc,
  81. win32_dispatch,
  82. win32_dealloc
  83. };
  84. #define FD_SET_ALLOC_SIZE(n) ((sizeof(struct win_fd_set) + ((n)-1)*sizeof(SOCKET)))
  85. static int
  86. realloc_fd_sets(struct win32op *op, size_t new_size)
  87. {
  88. size_t size;
  89. assert(new_size >= op->readset_in->fd_count &&
  90. new_size >= op->writeset_in->fd_count);
  91. assert(new_size >= 1);
  92. size = FD_SET_ALLOC_SIZE(new_size);
  93. if (!(op->readset_in = realloc(op->readset_in, size)))
  94. return (-1);
  95. if (!(op->writeset_in = realloc(op->writeset_in, size)))
  96. return (-1);
  97. if (!(op->readset_out = realloc(op->readset_out, size)))
  98. return (-1);
  99. if (!(op->exset_out = realloc(op->exset_out, size)))
  100. return (-1);
  101. if (!(op->writeset_out = realloc(op->writeset_out, size)))
  102. return (-1);
  103. op->fd_setsz = new_size;
  104. return (0);
  105. }
  106. static int
  107. timeval_to_ms(struct timeval *tv)
  108. {
  109. return ((tv->tv_sec * 1000) + (tv->tv_usec / 1000));
  110. }
  111. static int
  112. do_fd_set(struct win32op *op, SOCKET s, int read)
  113. {
  114. unsigned int i;
  115. struct win_fd_set *set = read ? op->readset_in : op->writeset_in;
  116. for (i=0;i<set->fd_count;++i) {
  117. if (set->fd_array[i]==s)
  118. return (0);
  119. }
  120. if (set->fd_count == op->fd_setsz) {
  121. if (realloc_fd_sets(op, op->fd_setsz*2))
  122. return (-1);
  123. /* set pointer will have changed and needs reiniting! */
  124. set = read ? op->readset_in : op->writeset_in;
  125. }
  126. set->fd_array[set->fd_count] = s;
  127. return (set->fd_count++);
  128. }
  129. static int
  130. do_fd_clear(struct win32op *op, SOCKET s, int read)
  131. {
  132. unsigned int i;
  133. struct win_fd_set *set = read ? op->readset_in : op->writeset_in;
  134. for (i=0;i<set->fd_count;++i) {
  135. if (set->fd_array[i]==s) {
  136. if (--set->fd_count != i) {
  137. set->fd_array[i] = set->fd_array[set->fd_count];
  138. }
  139. return (0);
  140. }
  141. }
  142. return (0);
  143. }
  144. #define NEVENT 64
  145. void *
  146. win32_init(void)
  147. {
  148. struct win32op *winop;
  149. size_t size;
  150. if (!(winop = calloc(1, sizeof(struct win32op))))
  151. return NULL;
  152. winop->fd_setsz = NEVENT;
  153. size = FD_SET_ALLOC_SIZE(NEVENT);
  154. if (!(winop->readset_in = malloc(size)))
  155. goto err;
  156. if (!(winop->writeset_in = malloc(size)))
  157. goto err;
  158. if (!(winop->readset_out = malloc(size)))
  159. goto err;
  160. if (!(winop->writeset_out = malloc(size)))
  161. goto err;
  162. if (!(winop->exset_out = malloc(size)))
  163. goto err;
  164. winop->n_events = 0;
  165. winop->n_events_alloc = NEVENT;
  166. if (!(winop->events = malloc(NEVENT*sizeof(struct event*))))
  167. goto err;
  168. winop->readset_in->fd_count = winop->writeset_in->fd_count = 0;
  169. winop->readset_out->fd_count = winop->writeset_out->fd_count
  170. = winop->exset_out->fd_count = 0;
  171. return (winop);
  172. err:
  173. XFREE(winop->readset_in);
  174. XFREE(winop->writeset_in);
  175. XFREE(winop->readset_out);
  176. XFREE(winop->writeset_out);
  177. XFREE(winop->exset_out);
  178. XFREE(winop->events);
  179. XFREE(winop);
  180. return (NULL);
  181. }
  182. int
  183. win32_recalc(struct event_base *base, void *arg, int max)
  184. {
  185. return (signal_recalc());
  186. }
  187. int
  188. win32_insert(void *op, struct event *ev)
  189. {
  190. struct win32op *win32op = op;
  191. int i;
  192. if (ev->ev_events & EV_SIGNAL) {
  193. if (ev->ev_events & (EV_READ|EV_WRITE))
  194. event_errx(1, "%s: EV_SIGNAL incompatible use",
  195. __func__);
  196. if((int)signal(EVENT_SIGNAL(ev), signal_handler) == -1)
  197. return (-1);
  198. return (0);
  199. }
  200. if (!(ev->ev_events & (EV_READ|EV_WRITE)))
  201. return (0);
  202. for (i=0;i<win32op->n_events;++i) {
  203. if(win32op->events[i] == ev) {
  204. event_debug(("%s: Event for %d already inserted.",
  205. __func__, (int)ev->ev_fd));
  206. return (0);
  207. }
  208. }
  209. event_debug(("%s: adding event for %d", __func__, (int)ev->ev_fd));
  210. if (ev->ev_events & EV_READ) {
  211. if (do_fd_set(win32op, ev->ev_fd, 1)<0)
  212. return (-1);
  213. }
  214. if (ev->ev_events & EV_WRITE) {
  215. if (do_fd_set(win32op, ev->ev_fd, 0)<0)
  216. return (-1);
  217. }
  218. if (win32op->n_events_alloc == win32op->n_events) {
  219. size_t sz;
  220. win32op->n_events_alloc *= 2;
  221. sz = sizeof(struct event*)*win32op->n_events_alloc;
  222. if (!(win32op->events = realloc(win32op->events, sz)))
  223. return (-1);
  224. }
  225. win32op->events[win32op->n_events++] = ev;
  226. return (0);
  227. }
  228. int
  229. win32_del(void *op, struct event *ev)
  230. {
  231. struct win32op *win32op = op;
  232. int i, found;
  233. if (ev->ev_events & EV_SIGNAL)
  234. return ((int)signal(EVENT_SIGNAL(ev), SIG_IGN));
  235. found = -1;
  236. for (i=0;i<win32op->n_events;++i) {
  237. if(win32op->events[i] == ev) {
  238. found = i;
  239. break;
  240. }
  241. }
  242. if (found < 0) {
  243. event_debug(("%s: Unable to remove non-inserted event for %d",
  244. __func__, ev->ev_fd));
  245. return (-1);
  246. }
  247. event_debug(("%s: Removing event for %d", __func__, ev->ev_fd));
  248. if (ev->ev_events & EV_READ)
  249. do_fd_clear(win32op, ev->ev_fd, 1);
  250. if (ev->ev_events & EV_WRITE)
  251. do_fd_clear(win32op, ev->ev_fd, 0);
  252. if (i != --win32op->n_events) {
  253. win32op->events[i] = win32op->events[win32op->n_events];
  254. }
  255. return 0;
  256. }
  257. static void
  258. fd_set_copy(struct win_fd_set *out, const struct win_fd_set *in)
  259. {
  260. out->fd_count = in->fd_count;
  261. memcpy(out->fd_array, in->fd_array, in->fd_count * (sizeof(SOCKET)));
  262. }
  263. /*
  264. static void dump_fd_set(struct win_fd_set *s)
  265. {
  266. unsigned int i;
  267. printf("[ ");
  268. for(i=0;i<s->fd_count;++i)
  269. printf("%d ",(int)s->fd_array[i]);
  270. printf("]\n");
  271. }
  272. */
  273. int
  274. win32_dispatch(struct event_base *base, void *op,
  275. struct timeval *tv)
  276. {
  277. struct win32op *win32op = op;
  278. int res = 0;
  279. int i;
  280. int fd_count;
  281. fd_set_copy(win32op->readset_out, win32op->readset_in);
  282. fd_set_copy(win32op->exset_out, win32op->readset_in);
  283. fd_set_copy(win32op->writeset_out, win32op->writeset_in);
  284. fd_count =
  285. (win32op->readset_out->fd_count > win32op->writeset_out->fd_count) ?
  286. win32op->readset_out->fd_count : win32op->writeset_out->fd_count;
  287. if (!fd_count) {
  288. /* Windows doesn't like you to call select() with no sockets */
  289. Sleep(timeval_to_ms(tv));
  290. signal_process();
  291. return (0);
  292. }
  293. res = select(fd_count,
  294. (struct fd_set*)win32op->readset_out,
  295. (struct fd_set*)win32op->writeset_out,
  296. (struct fd_set*)win32op->exset_out, tv);
  297. event_debug(("%s: select returned %d", __func__, res));
  298. if(res <= 0) {
  299. signal_process();
  300. return res;
  301. }
  302. for (i=0;i<win32op->n_events;++i) {
  303. struct event *ev;
  304. int got = 0;
  305. ev = win32op->events[i];
  306. if ((ev->ev_events & EV_READ)) {
  307. if (FD_ISSET(ev->ev_fd, win32op->readset_out) ||
  308. FD_ISSET(ev->ev_fd, win32op->exset_out)) {
  309. got |= EV_READ;
  310. }
  311. }
  312. if ((ev->ev_events & EV_WRITE)) {
  313. if (FD_ISSET(ev->ev_fd, win32op->writeset_out)) {
  314. got |= EV_WRITE;
  315. }
  316. }
  317. if (!got)
  318. continue;
  319. if (!(ev->ev_events & EV_PERSIST)) {
  320. event_del(ev);
  321. }
  322. event_active(ev,got,1);
  323. }
  324. if (signal_recalc() == -1)
  325. return (-1);
  326. return (0);
  327. }
  328. void
  329. win32_dealloc(void *arg)
  330. {
  331. struct win32op *win32op = arg;
  332. if (win32op->readset_in)
  333. free(win32op->readset_in);
  334. if (win32op->writeset_in)
  335. free(win32op->writeset_in);
  336. if (win32op->readset_out)
  337. free(win32op->readset_out);
  338. if (win32op->writeset_out)
  339. free(win32op->writeset_out);
  340. if (win32op->exset_out)
  341. free(win32op->exset_out);
  342. if (win32op->events)
  343. free(win32op->events);
  344. memset(win32op, 0, sizeof(win32op));
  345. free(win32op);
  346. }
  347. static void
  348. signal_handler(int sig)
  349. {
  350. evsigcaught[sig]++;
  351. signal_caught = 1;
  352. }
  353. int
  354. signal_recalc(void)
  355. {
  356. struct event *ev;
  357. /* Reinstall our signal handler. */
  358. TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) {
  359. if((int)signal(EVENT_SIGNAL(ev), signal_handler) == -1)
  360. return (-1);
  361. }
  362. return (0);
  363. }
  364. void
  365. signal_process(void)
  366. {
  367. struct event *ev;
  368. short ncalls;
  369. TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) {
  370. ncalls = evsigcaught[EVENT_SIGNAL(ev)];
  371. if (ncalls) {
  372. if (!(ev->ev_events & EV_PERSIST))
  373. event_del(ev);
  374. event_active(ev, EV_SIGNAL, ncalls);
  375. }
  376. }
  377. memset(evsigcaught, 0, sizeof(evsigcaught));
  378. signal_caught = 0;
  379. }