daemon_poll.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. /*
  2. This file is part of libmicrohttpd
  3. Copyright (C) 2007-2018 Daniel Pittman and Christian Grothoff
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with this library; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  15. */
  16. /**
  17. * @file lib/daemon_poll.c
  18. * @brief functions to run poll-based event loop
  19. * @author Christian Grothoff
  20. */
  21. #include "internal.h"
  22. #include "connection_add.h"
  23. #include "connection_call_handlers.h"
  24. #include "connection_finish_forward.h"
  25. #include "daemon_poll.h"
  26. #include "upgrade_process.h"
  27. #include "request_resume.h"
  28. #ifdef HAVE_POLL
  29. #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
  30. /**
  31. * Set required 'event' members in 'pollfd' elements,
  32. * assuming that @a p[0].fd is MHD side of socketpair
  33. * and @a p[1].fd is TLS connected socket.
  34. *
  35. * @param urh upgrade handle to watch for
  36. * @param p pollfd array to update
  37. */
  38. static void
  39. urh_update_pollfd (struct MHD_UpgradeResponseHandle *urh,
  40. struct pollfd p[2])
  41. {
  42. p[0].events = 0;
  43. p[1].events = 0;
  44. if (urh->in_buffer_used < urh->in_buffer_size)
  45. p[0].events |= POLLIN;
  46. if (0 != urh->out_buffer_used)
  47. p[0].events |= POLLOUT;
  48. /* Do not monitor again for errors if error was detected before as
  49. * error state is remembered. */
  50. if ((0 == (urh->app.celi & MHD_EPOLL_STATE_ERROR)) &&
  51. ((0 != urh->in_buffer_size) ||
  52. (0 != urh->out_buffer_size) ||
  53. (0 != urh->out_buffer_used)))
  54. p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
  55. if (urh->out_buffer_used < urh->out_buffer_size)
  56. p[1].events |= POLLIN;
  57. if (0 != urh->in_buffer_used)
  58. p[1].events |= POLLOUT;
  59. /* Do not monitor again for errors if error was detected before as
  60. * error state is remembered. */
  61. if ((0 == (urh->mhd.celi & MHD_EPOLL_STATE_ERROR)) &&
  62. ((0 != urh->out_buffer_size) ||
  63. (0 != urh->in_buffer_size) ||
  64. (0 != urh->in_buffer_used)))
  65. p[1].events |= MHD_POLL_EVENTS_ERR_DISC;
  66. }
  67. /**
  68. * Set @a p to watch for @a urh.
  69. *
  70. * @param urh upgrade handle to watch for
  71. * @param p pollfd array to set
  72. */
  73. static void
  74. urh_to_pollfd (struct MHD_UpgradeResponseHandle *urh,
  75. struct pollfd p[2])
  76. {
  77. p[0].fd = urh->connection->socket_fd;
  78. p[1].fd = urh->mhd.socket;
  79. urh_update_pollfd (urh,
  80. p);
  81. }
  82. /**
  83. * Update ready state in @a urh based on pollfd.
  84. * @param urh upgrade handle to update
  85. * @param p 'poll()' processed pollfd.
  86. */
  87. static void
  88. urh_from_pollfd (struct MHD_UpgradeResponseHandle *urh,
  89. struct pollfd p[2])
  90. {
  91. /* Reset read/write ready, preserve error state. */
  92. urh->app.celi &= (~MHD_EPOLL_STATE_READ_READY & ~MHD_EPOLL_STATE_WRITE_READY);
  93. urh->mhd.celi &= (~MHD_EPOLL_STATE_READ_READY & ~MHD_EPOLL_STATE_WRITE_READY);
  94. if (0 != (p[0].revents & POLLIN))
  95. urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
  96. if (0 != (p[0].revents & POLLOUT))
  97. urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
  98. if (0 != (p[0].revents & POLLHUP))
  99. urh->app.celi |= MHD_EPOLL_STATE_READ_READY | MHD_EPOLL_STATE_WRITE_READY;
  100. if (0 != (p[0].revents & MHD_POLL_REVENTS_ERRROR))
  101. urh->app.celi |= MHD_EPOLL_STATE_ERROR;
  102. if (0 != (p[1].revents & POLLIN))
  103. urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
  104. if (0 != (p[1].revents & POLLOUT))
  105. urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
  106. if (0 != (p[1].revents & POLLHUP))
  107. urh->mhd.celi |= MHD_EPOLL_STATE_ERROR;
  108. if (0 != (p[1].revents & MHD_POLL_REVENTS_ERRROR))
  109. urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY | MHD_EPOLL_STATE_WRITE_READY;
  110. }
  111. #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
  112. /**
  113. * Process all of our connections and possibly the server
  114. * socket using poll().
  115. *
  116. * @param daemon daemon to run poll loop for
  117. * @param may_block #MHD_YES if blocking, #MHD_NO if non-blocking
  118. * @return #MHD_SC_OK on success
  119. */
  120. enum MHD_StatusCode
  121. MHD_daemon_poll_all_ (struct MHD_Daemon *daemon,
  122. bool may_block)
  123. {
  124. unsigned int num_connections;
  125. struct MHD_Connection *pos;
  126. struct MHD_Connection *prev;
  127. #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
  128. struct MHD_UpgradeResponseHandle *urh;
  129. struct MHD_UpgradeResponseHandle *urhn;
  130. #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
  131. if ( (! daemon->disallow_suspend_resume) &&
  132. (MHD_resume_suspended_connections_ (daemon)) )
  133. may_block = false;
  134. /* count number of connections and thus determine poll set size */
  135. num_connections = 0;
  136. for (pos = daemon->connections_head; NULL != pos; pos = pos->next)
  137. num_connections++;
  138. #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
  139. for (urh = daemon->urh_head; NULL != urh; urh = urh->next)
  140. num_connections += 2;
  141. #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
  142. {
  143. MHD_UNSIGNED_LONG_LONG ltimeout;
  144. unsigned int i;
  145. int timeout;
  146. unsigned int poll_server;
  147. int poll_listen;
  148. int poll_itc_idx;
  149. struct pollfd *p;
  150. MHD_socket ls;
  151. p = MHD_calloc_ ((2 + num_connections),
  152. sizeof (struct pollfd));
  153. if (NULL == p)
  154. {
  155. #ifdef HAVE_MESSAGES
  156. MHD_DLOG (daemon,
  157. MHD_SC_POLL_MALLOC_FAILURE,
  158. _ ("Error allocating memory: %s\n"),
  159. MHD_strerror_ (errno));
  160. #endif
  161. return MHD_SC_POLL_MALLOC_FAILURE;
  162. }
  163. poll_server = 0;
  164. poll_listen = -1;
  165. if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_socket)) &&
  166. (! daemon->was_quiesced) &&
  167. (daemon->connections < daemon->global_connection_limit) &&
  168. (! daemon->at_limit) )
  169. {
  170. /* only listen if we are not at the connection limit */
  171. p[poll_server].fd = ls;
  172. p[poll_server].events = POLLIN;
  173. p[poll_server].revents = 0;
  174. poll_listen = (int) poll_server;
  175. poll_server++;
  176. }
  177. poll_itc_idx = -1;
  178. if (MHD_ITC_IS_VALID_ (daemon->itc))
  179. {
  180. p[poll_server].fd = MHD_itc_r_fd_ (daemon->itc);
  181. p[poll_server].events = POLLIN;
  182. p[poll_server].revents = 0;
  183. poll_itc_idx = (int) poll_server;
  184. poll_server++;
  185. }
  186. if (! may_block)
  187. timeout = 0;
  188. else if ( (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode) ||
  189. (MHD_SC_OK != /* FIXME: distinguish between NO_TIMEOUT and errors! */
  190. MHD_daemon_get_timeout (daemon,
  191. &ltimeout)) )
  192. timeout = -1;
  193. else
  194. timeout = (ltimeout > INT_MAX) ? INT_MAX : (int) ltimeout;
  195. i = 0;
  196. for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev)
  197. {
  198. p[poll_server + i].fd = pos->socket_fd;
  199. switch (pos->request.event_loop_info)
  200. {
  201. case MHD_EVENT_LOOP_INFO_READ:
  202. p[poll_server + i].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
  203. break;
  204. case MHD_EVENT_LOOP_INFO_WRITE:
  205. p[poll_server + i].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
  206. break;
  207. case MHD_EVENT_LOOP_INFO_BLOCK:
  208. p[poll_server + i].events |= MHD_POLL_EVENTS_ERR_DISC;
  209. break;
  210. case MHD_EVENT_LOOP_INFO_CLEANUP:
  211. timeout = 0; /* clean up "pos" immediately */
  212. break;
  213. }
  214. i++;
  215. }
  216. #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
  217. for (urh = daemon->urh_tail; NULL != urh; urh = urh->prev)
  218. {
  219. urh_to_pollfd (urh,
  220. &(p[poll_server + i]));
  221. i += 2;
  222. }
  223. #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
  224. if (0 == poll_server + num_connections)
  225. {
  226. free (p);
  227. return MHD_SC_OK;
  228. }
  229. if (MHD_sys_poll_ (p,
  230. poll_server + num_connections,
  231. timeout) < 0)
  232. {
  233. const int err = MHD_socket_get_error_ ();
  234. if (MHD_SCKT_ERR_IS_EINTR_ (err))
  235. {
  236. free (p);
  237. return MHD_SC_OK;
  238. }
  239. #ifdef HAVE_MESSAGES
  240. MHD_DLOG (daemon,
  241. MHD_SC_UNEXPECTED_POLL_ERROR,
  242. _ ("poll failed: %s\n"),
  243. MHD_socket_strerr_ (err));
  244. #endif
  245. free (p);
  246. return MHD_SC_UNEXPECTED_POLL_ERROR;
  247. }
  248. /* Reset. New value will be set when connections are processed. */
  249. daemon->data_already_pending = false;
  250. /* handle ITC FD */
  251. /* do it before any other processing so
  252. new signals will be processed in next loop */
  253. if ( (-1 != poll_itc_idx) &&
  254. (0 != (p[poll_itc_idx].revents & POLLIN)) )
  255. MHD_itc_clear_ (daemon->itc);
  256. /* handle shutdown */
  257. if (daemon->shutdown)
  258. {
  259. free (p);
  260. return MHD_SC_DAEMON_ALREADY_SHUTDOWN;
  261. }
  262. i = 0;
  263. prev = daemon->connections_tail;
  264. while (NULL != (pos = prev))
  265. {
  266. prev = pos->prev;
  267. /* first, sanity checks */
  268. if (i >= num_connections)
  269. break; /* connection list changed somehow, retry later ... */
  270. if (p[poll_server + i].fd != pos->socket_fd)
  271. continue; /* fd mismatch, something else happened, retry later ... */
  272. MHD_connection_call_handlers_ (pos,
  273. 0 != (p[poll_server + i].revents & POLLIN),
  274. 0 != (p[poll_server + i].revents
  275. & POLLOUT),
  276. 0 != (p[poll_server + i].revents
  277. & MHD_POLL_REVENTS_ERR_DISC));
  278. i++;
  279. }
  280. #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
  281. for (urh = daemon->urh_tail; NULL != urh; urh = urhn)
  282. {
  283. if (i >= num_connections)
  284. break; /* connection list changed somehow, retry later ... */
  285. /* Get next connection here as connection can be removed
  286. * from 'daemon->urh_head' list. */
  287. urhn = urh->prev;
  288. /* Check for fd mismatch. FIXME: required for safety? */
  289. if ((p[poll_server + i].fd != urh->connection->socket_fd) ||
  290. (p[poll_server + i + 1].fd != urh->mhd.socket))
  291. break;
  292. urh_from_pollfd (urh,
  293. &p[poll_server + i]);
  294. i += 2;
  295. MHD_upgrade_response_handle_process_ (urh);
  296. /* Finished forwarding? */
  297. if ( (0 == urh->in_buffer_size) &&
  298. (0 == urh->out_buffer_size) &&
  299. (0 == urh->in_buffer_used) &&
  300. (0 == urh->out_buffer_used) )
  301. {
  302. /* MHD_connection_finish_forward_() will remove connection from
  303. * 'daemon->urh_head' list. */
  304. MHD_connection_finish_forward_ (urh->connection);
  305. urh->clean_ready = true;
  306. /* If 'urh->was_closed' already was set to true, connection will be
  307. * moved immediately to cleanup list. Otherwise connection
  308. * will stay in suspended list until 'urh' will be marked
  309. * with 'was_closed' by application. */
  310. MHD_request_resume (&urh->connection->request);
  311. }
  312. }
  313. #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
  314. /* handle 'listen' FD */
  315. if ( (-1 != poll_listen) &&
  316. (0 != (p[poll_listen].revents & POLLIN)) )
  317. (void) MHD_accept_connection_ (daemon);
  318. free (p);
  319. }
  320. return MHD_SC_OK;
  321. }
  322. /**
  323. * Process only the listen socket using poll().
  324. *
  325. * @param daemon daemon to run poll loop for
  326. * @param may_block true if blocking, false if non-blocking
  327. * @return #MHD_SC_OK on success
  328. */
  329. enum MHD_StatusCode
  330. MHD_daemon_poll_listen_socket_ (struct MHD_Daemon *daemon,
  331. bool may_block)
  332. {
  333. struct pollfd p[2];
  334. int timeout;
  335. unsigned int poll_count;
  336. int poll_listen;
  337. int poll_itc_idx;
  338. MHD_socket ls;
  339. memset (&p,
  340. 0,
  341. sizeof (p));
  342. poll_count = 0;
  343. poll_listen = -1;
  344. poll_itc_idx = -1;
  345. if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_socket)) &&
  346. (! daemon->was_quiesced) )
  347. {
  348. p[poll_count].fd = ls;
  349. p[poll_count].events = POLLIN;
  350. p[poll_count].revents = 0;
  351. poll_listen = poll_count;
  352. poll_count++;
  353. }
  354. if (MHD_ITC_IS_VALID_ (daemon->itc))
  355. {
  356. p[poll_count].fd = MHD_itc_r_fd_ (daemon->itc);
  357. p[poll_count].events = POLLIN;
  358. p[poll_count].revents = 0;
  359. poll_itc_idx = poll_count;
  360. poll_count++;
  361. }
  362. if (! daemon->disallow_suspend_resume)
  363. (void) MHD_resume_suspended_connections_ (daemon);
  364. if (! may_block)
  365. timeout = 0;
  366. else
  367. timeout = -1;
  368. if (0 == poll_count)
  369. return MHD_SC_OK;
  370. if (MHD_sys_poll_ (p,
  371. poll_count,
  372. timeout) < 0)
  373. {
  374. const int err = MHD_socket_get_error_ ();
  375. if (MHD_SCKT_ERR_IS_EINTR_ (err))
  376. return MHD_SC_OK;
  377. #ifdef HAVE_MESSAGES
  378. MHD_DLOG (daemon,
  379. MHD_SC_UNEXPECTED_POLL_ERROR,
  380. _ ("poll failed: %s\n"),
  381. MHD_socket_strerr_ (err));
  382. #endif
  383. return MHD_SC_UNEXPECTED_POLL_ERROR;
  384. }
  385. if ( (-1 != poll_itc_idx) &&
  386. (0 != (p[poll_itc_idx].revents & POLLIN)) )
  387. MHD_itc_clear_ (daemon->itc);
  388. /* handle shutdown */
  389. if (daemon->shutdown)
  390. return MHD_SC_DAEMON_ALREADY_SHUTDOWN;
  391. if ( (-1 != poll_listen) &&
  392. (0 != (p[poll_listen].revents & POLLIN)) )
  393. (void) MHD_accept_connection_ (daemon);
  394. return MHD_SC_OK;
  395. }
  396. #endif
  397. /**
  398. * Do poll()-based processing.
  399. *
  400. * @param daemon daemon to run poll()-loop for
  401. * @param may_block true if blocking, false if non-blocking
  402. * @return #MHD_SC_OK on success
  403. */
  404. enum MHD_StatusCode
  405. MHD_daemon_poll_ (struct MHD_Daemon *daemon,
  406. bool may_block)
  407. {
  408. #ifdef HAVE_POLL
  409. if (daemon->shutdown)
  410. return MHD_SC_DAEMON_ALREADY_SHUTDOWN;
  411. if (MHD_TM_THREAD_PER_CONNECTION != daemon->threading_mode)
  412. return MHD_daemon_poll_all_ (daemon,
  413. may_block);
  414. return MHD_daemon_poll_listen_socket_ (daemon,
  415. may_block);
  416. #else
  417. /* This code should be dead, as we should have checked
  418. this earlier... */
  419. return MHD_SC_POLL_NOT_SUPPORTED;
  420. #endif
  421. }
  422. #ifdef HAVE_POLL
  423. #ifdef HTTPS_SUPPORT
  424. /**
  425. * Process upgraded connection with a poll() loop.
  426. * We are in our own thread, only processing @a con
  427. *
  428. * @param con connection to process
  429. */
  430. void
  431. MHD_daemon_upgrade_connection_with_poll_ (struct MHD_Connection *con)
  432. {
  433. struct MHD_UpgradeResponseHandle *urh = con->request.urh;
  434. struct pollfd p[2];
  435. memset (p,
  436. 0,
  437. sizeof (p));
  438. p[0].fd = urh->connection->socket_fd;
  439. p[1].fd = urh->mhd.socket;
  440. while ( (0 != urh->in_buffer_size) ||
  441. (0 != urh->out_buffer_size) ||
  442. (0 != urh->in_buffer_used) ||
  443. (0 != urh->out_buffer_used) )
  444. {
  445. int timeout;
  446. urh_update_pollfd (urh,
  447. p);
  448. if ( (con->tls_read_ready) &&
  449. (urh->in_buffer_used < urh->in_buffer_size))
  450. timeout = 0; /* No need to wait if incoming data is already pending in TLS buffers. */
  451. else
  452. timeout = -1;
  453. if (MHD_sys_poll_ (p,
  454. 2,
  455. timeout) < 0)
  456. {
  457. const int err = MHD_socket_get_error_ ();
  458. if (MHD_SCKT_ERR_IS_EINTR_ (err))
  459. continue;
  460. #ifdef HAVE_MESSAGES
  461. MHD_DLOG (con->daemon,
  462. MHD_SC_UNEXPECTED_POLL_ERROR,
  463. _ ("Error during poll: `%s'\n"),
  464. MHD_socket_strerr_ (err));
  465. #endif
  466. break;
  467. }
  468. urh_from_pollfd (urh,
  469. p);
  470. MHD_upgrade_response_handle_process_ (urh);
  471. }
  472. }
  473. #endif
  474. #endif
  475. /* end of daemon_poll.c */