A clone of btpd with my configuration changes.
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

18 лет назад
17 лет назад
18 лет назад
17 лет назад
18 лет назад
17 лет назад
18 лет назад
17 лет назад
18 лет назад
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. /*
  2. * Copyright 2000-2004 Niels Provos <provos@citi.umich.edu>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. The name of the author may not be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  17. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  18. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  19. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  20. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  21. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  22. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  23. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  25. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. #ifdef HAVE_CONFIG_H
  28. #include "config.h"
  29. #endif
  30. #include <sys/types.h>
  31. #include <sys/resource.h>
  32. #ifdef HAVE_SYS_TIME_H
  33. #include <sys/time.h>
  34. #else
  35. #include <sys/_time.h>
  36. #endif
  37. #include <sys/queue.h>
  38. #include <sys/devpoll.h>
  39. #include <signal.h>
  40. #include <stdio.h>
  41. #include <stdlib.h>
  42. #include <string.h>
  43. #include <unistd.h>
  44. #include <fcntl.h>
  45. #include <errno.h>
  46. #include <assert.h>
  47. #include "event.h"
  48. #include "evsignal.h"
  49. #include "log.h"
  50. extern volatile sig_atomic_t evsignal_caught;
  51. /* due to limitations in the devpoll interface, we need to keep track of
  52. * all file descriptors outself.
  53. */
  54. struct evdevpoll {
  55. struct event *evread;
  56. struct event *evwrite;
  57. };
  58. struct devpollop {
  59. struct evdevpoll *fds;
  60. int nfds;
  61. struct pollfd *events;
  62. int nevents;
  63. int dpfd;
  64. struct pollfd *changes;
  65. int nchanges;
  66. };
  67. void *devpoll_init (void);
  68. int devpoll_add (void *, struct event *);
  69. int devpoll_del (void *, struct event *);
  70. int devpoll_recalc (struct event_base *, void *, int);
  71. int devpoll_dispatch (struct event_base *, void *, struct timeval *);
  72. void devpoll_dealloc (void *);
  73. struct eventop devpollops = {
  74. "devpoll",
  75. devpoll_init,
  76. devpoll_add,
  77. devpoll_del,
  78. devpoll_recalc,
  79. devpoll_dispatch,
  80. devpoll_dealloc
  81. };
  82. #define NEVENT 32000
  83. static int
  84. devpoll_commit(struct devpollop *devpollop)
  85. {
  86. /*
  87. * Due to a bug in Solaris, we have to use pwrite with an offset of 0.
  88. * Write is limited to 2GB of data, until it will fail.
  89. */
  90. if (pwrite(devpollop->dpfd, devpollop->changes,
  91. sizeof(struct pollfd) * devpollop->nchanges, 0) == -1)
  92. return(-1);
  93. devpollop->nchanges = 0;
  94. return(0);
  95. }
  96. static int
  97. devpoll_queue(struct devpollop *devpollop, int fd, int events) {
  98. struct pollfd *pfd;
  99. if (devpollop->nchanges >= devpollop->nevents) {
  100. /*
  101. * Change buffer is full, must commit it to /dev/poll before
  102. * adding more
  103. */
  104. if (devpoll_commit(devpollop) != 0)
  105. return(-1);
  106. }
  107. pfd = &devpollop->changes[devpollop->nchanges++];
  108. pfd->fd = fd;
  109. pfd->events = events;
  110. pfd->revents = 0;
  111. return(0);
  112. }
  113. void *
  114. devpoll_init(void)
  115. {
  116. int dpfd, nfiles = NEVENT;
  117. struct rlimit rl;
  118. struct devpollop *devpollop;
  119. /* Disable devpoll when this environment variable is set */
  120. if (getenv("EVENT_NODEVPOLL"))
  121. return (NULL);
  122. if (!(devpollop = calloc(1, sizeof(struct devpollop))))
  123. return (NULL);
  124. if (getrlimit(RLIMIT_NOFILE, &rl) == 0 &&
  125. rl.rlim_cur != RLIM_INFINITY)
  126. nfiles = rl.rlim_cur - 1;
  127. /* Initialize the kernel queue */
  128. if ((dpfd = open("/dev/poll", O_RDWR)) == -1) {
  129. event_warn("open: /dev/poll");
  130. free(devpollop);
  131. return (NULL);
  132. }
  133. devpollop->dpfd = dpfd;
  134. /* Initialize fields */
  135. devpollop->events = calloc(nfiles, sizeof(struct pollfd));
  136. if (devpollop->events == NULL) {
  137. free(devpollop);
  138. close(dpfd);
  139. return (NULL);
  140. }
  141. devpollop->nevents = nfiles;
  142. devpollop->fds = calloc(nfiles, sizeof(struct evdevpoll));
  143. if (devpollop->fds == NULL) {
  144. free(devpollop->events);
  145. free(devpollop);
  146. close(dpfd);
  147. return (NULL);
  148. }
  149. devpollop->nfds = nfiles;
  150. devpollop->changes = calloc(nfiles, sizeof(struct pollfd));
  151. if (devpollop->changes == NULL) {
  152. free(devpollop->fds);
  153. free(devpollop->events);
  154. free(devpollop);
  155. close(dpfd);
  156. return (NULL);
  157. }
  158. evsignal_init();
  159. return (devpollop);
  160. }
  161. int
  162. devpoll_recalc(struct event_base *base, void *arg, int max)
  163. {
  164. struct devpollop *devpollop = arg;
  165. if (max > devpollop->nfds) {
  166. struct evdevpoll *fds;
  167. int nfds;
  168. nfds = devpollop->nfds;
  169. while (nfds < max)
  170. nfds <<= 1;
  171. fds = realloc(devpollop->fds, nfds * sizeof(struct evdevpoll));
  172. if (fds == NULL) {
  173. event_warn("realloc");
  174. return (-1);
  175. }
  176. devpollop->fds = fds;
  177. memset(fds + devpollop->nfds, 0,
  178. (nfds - devpollop->nfds) * sizeof(struct evdevpoll));
  179. devpollop->nfds = nfds;
  180. }
  181. return (0);
  182. }
  183. int
  184. devpoll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
  185. {
  186. struct devpollop *devpollop = arg;
  187. struct pollfd *events = devpollop->events;
  188. struct dvpoll dvp;
  189. struct evdevpoll *evdp;
  190. int i, res, timeout;
  191. if (devpollop->nchanges)
  192. devpoll_commit(devpollop);
  193. timeout = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
  194. dvp.dp_fds = devpollop->events;
  195. dvp.dp_nfds = devpollop->nevents;
  196. dvp.dp_timeout = timeout;
  197. res = ioctl(devpollop->dpfd, DP_POLL, &dvp);
  198. if (res == -1) {
  199. if (errno != EINTR) {
  200. event_warn("ioctl: DP_POLL");
  201. return (-1);
  202. }
  203. evsignal_process();
  204. return (0);
  205. } else if (evsignal_caught)
  206. evsignal_process();
  207. event_debug(("%s: devpoll_wait reports %d", __func__, res));
  208. for (i = 0; i < res; i++) {
  209. int which = 0;
  210. int what = events[i].revents;
  211. struct event *evread = NULL, *evwrite = NULL;
  212. assert(events[i].fd < devpollop->nfds);
  213. evdp = &devpollop->fds[events[i].fd];
  214. if (what & POLLHUP)
  215. what |= POLLIN | POLLOUT;
  216. else if (what & POLLERR)
  217. what |= POLLIN | POLLOUT;
  218. if (what & POLLIN) {
  219. evread = evdp->evread;
  220. which |= EV_READ;
  221. }
  222. if (what & POLLOUT) {
  223. evwrite = evdp->evwrite;
  224. which |= EV_WRITE;
  225. }
  226. if (!which)
  227. continue;
  228. if (evread != NULL && !(evread->ev_events & EV_PERSIST))
  229. event_del(evread);
  230. if (evwrite != NULL && evwrite != evread &&
  231. !(evwrite->ev_events & EV_PERSIST))
  232. event_del(evwrite);
  233. if (evread != NULL)
  234. event_active(evread, EV_READ, 1);
  235. if (evwrite != NULL)
  236. event_active(evwrite, EV_WRITE, 1);
  237. }
  238. return (0);
  239. }
  240. int
  241. devpoll_add(void *arg, struct event *ev)
  242. {
  243. struct devpollop *devpollop = arg;
  244. struct evdevpoll *evdp;
  245. int fd, events;
  246. if (ev->ev_events & EV_SIGNAL)
  247. return (evsignal_add(ev));
  248. fd = ev->ev_fd;
  249. if (fd >= devpollop->nfds) {
  250. /* Extend the file descriptor array as necessary */
  251. if (devpoll_recalc(ev->ev_base, devpollop, fd) == -1)
  252. return (-1);
  253. }
  254. evdp = &devpollop->fds[fd];
  255. /*
  256. * It's not necessary to OR the existing read/write events that we
  257. * are currently interested in with the new event we are adding.
  258. * The /dev/poll driver ORs any new events with the existing events
  259. * that it has cached for the fd.
  260. */
  261. events = 0;
  262. if (ev->ev_events & EV_READ) {
  263. if (evdp->evread && evdp->evread != ev) {
  264. /* There is already a different read event registered */
  265. return(-1);
  266. }
  267. events |= POLLIN;
  268. }
  269. if (ev->ev_events & EV_WRITE) {
  270. if (evdp->evwrite && evdp->evwrite != ev) {
  271. /* There is already a different write event registered */
  272. return(-1);
  273. }
  274. events |= POLLOUT;
  275. }
  276. if (devpoll_queue(devpollop, fd, events) != 0)
  277. return(-1);
  278. /* Update events responsible */
  279. if (ev->ev_events & EV_READ)
  280. evdp->evread = ev;
  281. if (ev->ev_events & EV_WRITE)
  282. evdp->evwrite = ev;
  283. return (0);
  284. }
  285. int
  286. devpoll_del(void *arg, struct event *ev)
  287. {
  288. struct devpollop *devpollop = arg;
  289. struct evdevpoll *evdp;
  290. int fd, events;
  291. int needwritedelete = 1, needreaddelete = 1;
  292. if (ev->ev_events & EV_SIGNAL)
  293. return (evsignal_del(ev));
  294. fd = ev->ev_fd;
  295. if (fd >= devpollop->nfds)
  296. return (0);
  297. evdp = &devpollop->fds[fd];
  298. events = 0;
  299. if (ev->ev_events & EV_READ)
  300. events |= POLLIN;
  301. if (ev->ev_events & EV_WRITE)
  302. events |= POLLOUT;
  303. /*
  304. * The only way to remove an fd from the /dev/poll monitored set is
  305. * to use POLLREMOVE by itself. This removes ALL events for the fd
  306. * provided so if we care about two events and are only removing one
  307. * we must re-add the other event after POLLREMOVE.
  308. */
  309. if (devpoll_queue(devpollop, fd, POLLREMOVE) != 0)
  310. return(-1);
  311. if ((events & (POLLIN|POLLOUT)) != (POLLIN|POLLOUT)) {
  312. /*
  313. * We're not deleting all events, so we must resubmit the
  314. * event that we are still interested in if one exists.
  315. */
  316. if ((events & POLLIN) && evdp->evwrite != NULL) {
  317. /* Deleting read, still care about write */
  318. devpoll_queue(devpollop, fd, POLLOUT);
  319. needwritedelete = 0;
  320. } else if ((events & POLLOUT) && evdp->evread != NULL) {
  321. /* Deleting write, still care about read */
  322. devpoll_queue(devpollop, fd, POLLIN);
  323. needreaddelete = 0;
  324. }
  325. }
  326. if (needreaddelete)
  327. evdp->evread = NULL;
  328. if (needwritedelete)
  329. evdp->evwrite = NULL;
  330. return (0);
  331. }
  332. void
  333. devpoll_dealloc(void *arg)
  334. {
  335. struct devpollop *devpollop = arg;
  336. if (devpollop->fds)
  337. free(devpollop->fds);
  338. if (devpollop->events)
  339. free(devpollop->events);
  340. if (devpollop->changes)
  341. free(devpollop->changes);
  342. if (devpollop->dpfd >= 0)
  343. close(devpollop->dpfd);
  344. memset(devpollop, 0, sizeof(struct devpollop));
  345. free(devpollop);
  346. }