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

18 лет назад
17 лет назад
18 лет назад
17 лет назад
18 лет назад
17 лет назад
18 лет назад
17 лет назад
18 лет назад
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. /*
  2. * Copyright 2000-2003 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 <stdint.h>
  31. #include <sys/types.h>
  32. #include <sys/resource.h>
  33. #ifdef HAVE_SYS_TIME_H
  34. #include <sys/time.h>
  35. #else
  36. #include <sys/_time.h>
  37. #endif
  38. #include <sys/queue.h>
  39. #include <sys/epoll.h>
  40. #include <signal.h>
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43. #include <string.h>
  44. #include <unistd.h>
  45. #include <errno.h>
  46. #ifdef HAVE_FCNTL_H
  47. #include <fcntl.h>
  48. #endif
  49. #include "event.h"
  50. #include "evsignal.h"
  51. #include "log.h"
  52. extern volatile sig_atomic_t evsignal_caught;
  53. /* due to limitations in the epoll interface, we need to keep track of
  54. * all file descriptors outself.
  55. */
  56. struct evepoll {
  57. struct event *evread;
  58. struct event *evwrite;
  59. };
  60. struct epollop {
  61. struct evepoll *fds;
  62. int nfds;
  63. struct epoll_event *events;
  64. int nevents;
  65. int epfd;
  66. };
  67. void *epoll_init (void);
  68. int epoll_add (void *, struct event *);
  69. int epoll_del (void *, struct event *);
  70. int epoll_recalc (struct event_base *, void *, int);
  71. int epoll_dispatch (struct event_base *, void *, struct timeval *);
  72. void epoll_dealloc (void *);
  73. struct eventop epollops = {
  74. "epoll",
  75. epoll_init,
  76. epoll_add,
  77. epoll_del,
  78. epoll_recalc,
  79. epoll_dispatch,
  80. epoll_dealloc
  81. };
  82. #ifdef HAVE_SETFD
  83. #define FD_CLOSEONEXEC(x) do { \
  84. if (fcntl(x, F_SETFD, 1) == -1) \
  85. event_warn("fcntl(%d, F_SETFD)", x); \
  86. } while (0)
  87. #else
  88. #define FD_CLOSEONEXEC(x)
  89. #endif
  90. #define NEVENT 32000
  91. void *
  92. epoll_init(void)
  93. {
  94. int epfd, nfiles = NEVENT;
  95. struct rlimit rl;
  96. struct epollop *epollop;
  97. /* Disable epollueue when this environment variable is set */
  98. if (getenv("EVENT_NOEPOLL"))
  99. return (NULL);
  100. if (getrlimit(RLIMIT_NOFILE, &rl) == 0 &&
  101. rl.rlim_cur != RLIM_INFINITY) {
  102. /*
  103. * Solaris is somewhat retarded - it's important to drop
  104. * backwards compatibility when making changes. So, don't
  105. * dare to put rl.rlim_cur here.
  106. */
  107. nfiles = rl.rlim_cur - 1;
  108. }
  109. /* Initalize the kernel queue */
  110. if ((epfd = epoll_create(nfiles)) == -1) {
  111. event_warn("epoll_create");
  112. return (NULL);
  113. }
  114. FD_CLOSEONEXEC(epfd);
  115. if (!(epollop = calloc(1, sizeof(struct epollop))))
  116. return (NULL);
  117. epollop->epfd = epfd;
  118. /* Initalize fields */
  119. epollop->events = malloc(nfiles * sizeof(struct epoll_event));
  120. if (epollop->events == NULL) {
  121. free(epollop);
  122. return (NULL);
  123. }
  124. epollop->nevents = nfiles;
  125. epollop->fds = calloc(nfiles, sizeof(struct evepoll));
  126. if (epollop->fds == NULL) {
  127. free(epollop->events);
  128. free(epollop);
  129. return (NULL);
  130. }
  131. epollop->nfds = nfiles;
  132. evsignal_init();
  133. return (epollop);
  134. }
  135. int
  136. epoll_recalc(struct event_base *base, void *arg, int max)
  137. {
  138. struct epollop *epollop = arg;
  139. if (max > epollop->nfds) {
  140. struct evepoll *fds;
  141. int nfds;
  142. nfds = epollop->nfds;
  143. while (nfds < max)
  144. nfds <<= 1;
  145. fds = realloc(epollop->fds, nfds * sizeof(struct evepoll));
  146. if (fds == NULL) {
  147. event_warn("realloc");
  148. return (-1);
  149. }
  150. epollop->fds = fds;
  151. memset(fds + epollop->nfds, 0,
  152. (nfds - epollop->nfds) * sizeof(struct evepoll));
  153. epollop->nfds = nfds;
  154. }
  155. return (0);
  156. }
  157. int
  158. epoll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
  159. {
  160. struct epollop *epollop = arg;
  161. struct epoll_event *events = epollop->events;
  162. struct evepoll *evep;
  163. int i, res, timeout;
  164. timeout = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
  165. res = epoll_wait(epollop->epfd, events, epollop->nevents, timeout);
  166. if (res == -1) {
  167. if (errno != EINTR) {
  168. event_warn("epoll_wait");
  169. return (-1);
  170. }
  171. evsignal_process();
  172. return (0);
  173. } else if (evsignal_caught)
  174. evsignal_process();
  175. event_debug(("%s: epoll_wait reports %d", __func__, res));
  176. for (i = 0; i < res; i++) {
  177. int which = 0;
  178. int what = events[i].events;
  179. struct event *evread = NULL, *evwrite = NULL;
  180. evep = (struct evepoll *)events[i].data.ptr;
  181. if (what & EPOLLHUP)
  182. what |= EPOLLIN | EPOLLOUT;
  183. else if (what & EPOLLERR)
  184. what |= EPOLLIN | EPOLLOUT;
  185. if (what & EPOLLIN) {
  186. evread = evep->evread;
  187. which |= EV_READ;
  188. }
  189. if (what & EPOLLOUT) {
  190. evwrite = evep->evwrite;
  191. which |= EV_WRITE;
  192. }
  193. if (!which)
  194. continue;
  195. if (evread != NULL && !(evread->ev_events & EV_PERSIST))
  196. event_del(evread);
  197. if (evwrite != NULL && evwrite != evread &&
  198. !(evwrite->ev_events & EV_PERSIST))
  199. event_del(evwrite);
  200. if (evread != NULL)
  201. event_active(evread, EV_READ, 1);
  202. if (evwrite != NULL)
  203. event_active(evwrite, EV_WRITE, 1);
  204. }
  205. return (0);
  206. }
  207. int
  208. epoll_add(void *arg, struct event *ev)
  209. {
  210. struct epollop *epollop = arg;
  211. struct epoll_event epev = {0, {0}};
  212. struct evepoll *evep;
  213. int fd, op, events;
  214. if (ev->ev_events & EV_SIGNAL)
  215. return (evsignal_add(ev));
  216. fd = ev->ev_fd;
  217. if (fd >= epollop->nfds) {
  218. /* Extent the file descriptor array as necessary */
  219. if (epoll_recalc(ev->ev_base, epollop, fd) == -1)
  220. return (-1);
  221. }
  222. evep = &epollop->fds[fd];
  223. op = EPOLL_CTL_ADD;
  224. events = 0;
  225. if (evep->evread != NULL) {
  226. events |= EPOLLIN;
  227. op = EPOLL_CTL_MOD;
  228. }
  229. if (evep->evwrite != NULL) {
  230. events |= EPOLLOUT;
  231. op = EPOLL_CTL_MOD;
  232. }
  233. if (ev->ev_events & EV_READ)
  234. events |= EPOLLIN;
  235. if (ev->ev_events & EV_WRITE)
  236. events |= EPOLLOUT;
  237. epev.data.ptr = evep;
  238. epev.events = events;
  239. if (epoll_ctl(epollop->epfd, op, ev->ev_fd, &epev) == -1)
  240. return (-1);
  241. /* Update events responsible */
  242. if (ev->ev_events & EV_READ)
  243. evep->evread = ev;
  244. if (ev->ev_events & EV_WRITE)
  245. evep->evwrite = ev;
  246. return (0);
  247. }
  248. int
  249. epoll_del(void *arg, struct event *ev)
  250. {
  251. struct epollop *epollop = arg;
  252. struct epoll_event epev = {0, {0}};
  253. struct evepoll *evep;
  254. int fd, events, op;
  255. int needwritedelete = 1, needreaddelete = 1;
  256. if (ev->ev_events & EV_SIGNAL)
  257. return (evsignal_del(ev));
  258. fd = ev->ev_fd;
  259. if (fd >= epollop->nfds)
  260. return (0);
  261. evep = &epollop->fds[fd];
  262. op = EPOLL_CTL_DEL;
  263. events = 0;
  264. if (ev->ev_events & EV_READ)
  265. events |= EPOLLIN;
  266. if (ev->ev_events & EV_WRITE)
  267. events |= EPOLLOUT;
  268. if ((events & (EPOLLIN|EPOLLOUT)) != (EPOLLIN|EPOLLOUT)) {
  269. if ((events & EPOLLIN) && evep->evwrite != NULL) {
  270. needwritedelete = 0;
  271. events = EPOLLOUT;
  272. op = EPOLL_CTL_MOD;
  273. } else if ((events & EPOLLOUT) && evep->evread != NULL) {
  274. needreaddelete = 0;
  275. events = EPOLLIN;
  276. op = EPOLL_CTL_MOD;
  277. }
  278. }
  279. epev.events = events;
  280. epev.data.ptr = evep;
  281. if (needreaddelete)
  282. evep->evread = NULL;
  283. if (needwritedelete)
  284. evep->evwrite = NULL;
  285. if (epoll_ctl(epollop->epfd, op, fd, &epev) == -1)
  286. return (-1);
  287. return (0);
  288. }
  289. void
  290. epoll_dealloc(void *arg)
  291. {
  292. struct epollop *epollop = arg;
  293. if (epollop->fds)
  294. free(epollop->fds);
  295. if (epollop->events)
  296. free(epollop->events);
  297. if (epollop->epfd >= 0)
  298. close(epollop->epfd);
  299. memset(epollop, 0, sizeof(struct epollop));
  300. free(epollop);
  301. }