server.cc 23 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010
  1. /* C++ modules. Experimental!
  2. Copyright (C) 2018-2022 Free Software Foundation, Inc.
  3. Written by Nathan Sidwell <nathan@acm.org> while at FaceBook
  4. This file is part of GCC.
  5. GCC is free software; you can redistribute it and/or modify it
  6. under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 3, or (at your option)
  8. any later version.
  9. GCC is distributed in the hope that it will be useful, but
  10. WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with GCC; see the file COPYING3. If not see
  15. <http://www.gnu.org/licenses/>. */
  16. #include "config.h"
  17. #include "resolver.h"
  18. // C++
  19. #include <set>
  20. #include <vector>
  21. #include <map>
  22. // C
  23. #include <csignal>
  24. #include <cstring>
  25. #include <cstdarg>
  26. #include <cstdlib>
  27. // OS
  28. #include <unistd.h>
  29. #include <sys/types.h>
  30. #include <sys/stat.h>
  31. #include <fcntl.h>
  32. // Network
  33. /* Include network stuff first. Excitingly OSX10.14 uses bcmp here, which
  34. we poison later! */
  35. #if defined (HAVE_AF_UNIX) || defined (HAVE_AF_INET6)
  36. /* socket, bind, listen, accept{4} */
  37. # define NETWORKING 1
  38. # include <sys/socket.h>
  39. # ifdef HAVE_AF_UNIX
  40. /* sockaddr_un */
  41. # include <sys/un.h>
  42. # endif
  43. # include <netinet/in.h>
  44. # ifdef HAVE_AF_INET6
  45. /* sockaddr_in6, getaddrinfo, freeaddrinfo, gai_sterror, ntohs, htons. */
  46. # include <netdb.h>
  47. # endif
  48. #ifdef HAVE_INET_NTOP
  49. /* inet_ntop. */
  50. #include <arpa/inet.h>
  51. #endif
  52. #endif
  53. #ifndef HAVE_AF_INET6
  54. # define gai_strerror(X) ""
  55. #endif
  56. #ifndef AI_NUMERICSERV
  57. #define AI_NUMERICSERV 0
  58. #endif
  59. #include <getopt.h>
  60. // Select or epoll
  61. #if NETWORKING
  62. #ifdef HAVE_EPOLL
  63. /* epoll_create, epoll_ctl, epoll_pwait */
  64. #include <sys/epoll.h>
  65. #endif
  66. #if defined (HAVE_PSELECT) || defined (HAVE_SELECT)
  67. /* pselect or select */
  68. #include <sys/select.h>
  69. #endif
  70. #endif
  71. // GCC
  72. #include "version.h"
  73. #include "ansidecl.h"
  74. #define HAVE_DECL_BASENAME 1 /* See comment in gcc/configure.ac. */
  75. #include "libiberty.h"
  76. #if !HOST_HAS_O_CLOEXEC
  77. #define O_CLOEXEC 0
  78. #endif
  79. #ifndef IS_DIR_SEPARATOR
  80. #define IS_DIR_SEPARATOR(C) ((C) == '/')
  81. #endif
  82. #ifndef DIR_SEPARATOR
  83. #define DIR_SEPARATOR '/'
  84. #endif
  85. /* Imported from libcpp/system.h
  86. Use gcc_assert(EXPR) to test invariants. */
  87. #if ENABLE_ASSERT_CHECKING
  88. #define gcc_assert(EXPR) \
  89. ((void)(!(EXPR) ? fancy_abort (__FILE__, __LINE__, __FUNCTION__), 0 : 0))
  90. #elif (GCC_VERSION >= 4005)
  91. #define gcc_assert(EXPR) \
  92. ((void)(__builtin_expect (!(EXPR), 0) ? __builtin_unreachable (), 0 : 0))
  93. #else
  94. /* Include EXPR, so that unused variable warnings do not occur. */
  95. #define gcc_assert(EXPR) ((void)(0 && (EXPR)))
  96. #endif
  97. /* Use gcc_unreachable() to mark unreachable locations (like an
  98. unreachable default case of a switch. Do not use gcc_assert(0). */
  99. #if (GCC_VERSION >= 4005) && !ENABLE_ASSERT_CHECKING
  100. #define gcc_unreachable() __builtin_unreachable ()
  101. #else
  102. #define gcc_unreachable() (fancy_abort (__FILE__, __LINE__, __FUNCTION__))
  103. #endif
  104. #if NETWORKING
  105. struct netmask {
  106. in6_addr addr;
  107. unsigned bits;
  108. netmask (const in6_addr &a, unsigned b)
  109. {
  110. if (b > sizeof (in6_addr) * 8)
  111. b = sizeof (in6_addr) * 8;
  112. bits = b;
  113. unsigned byte = (b + 7) / 8;
  114. unsigned ix = 0;
  115. for (ix = 0; ix < byte; ix++)
  116. addr.s6_addr[ix] = a.s6_addr[ix];
  117. for (; ix != sizeof (in6_addr); ix++)
  118. addr.s6_addr[ix] = 0;
  119. if (b & 3)
  120. addr.s6_addr[b/7] &= (255 << 8) >> (b & 3);
  121. }
  122. bool includes (const in6_addr &a) const
  123. {
  124. unsigned byte = bits / 8;
  125. for (unsigned ix = 0; ix != byte; ix++)
  126. if (addr.s6_addr[ix] != a.s6_addr[ix])
  127. return false;
  128. if (bits & 3)
  129. if ((addr.s6_addr[byte] ^ a.s6_addr[byte]) >> (8 - (bits & 3)))
  130. return false;
  131. return true;
  132. }
  133. };
  134. /* Netmask comparison. */
  135. struct netmask_cmp {
  136. bool operator() (const netmask &a, const netmask &b) const
  137. {
  138. if (a.bits != b.bits)
  139. return a.bits < b.bits;
  140. for (unsigned ix = 0; ix != sizeof (in6_addr); ix++)
  141. if (a.addr.s6_addr[ix] != b.addr.s6_addr[ix])
  142. return a.addr.s6_addr[ix] < b.addr.s6_addr[ix];
  143. return false;
  144. }
  145. };
  146. typedef std::set<netmask, netmask_cmp> netmask_set_t;
  147. typedef std::vector<netmask> netmask_vec_t;
  148. #endif
  149. const char *progname;
  150. /* Speak thoughts out loud. */
  151. static bool flag_noisy = false;
  152. /* One and done. */
  153. static bool flag_one = false;
  154. /* Serialize connections. */
  155. static bool flag_sequential = false;
  156. /* Fallback to default if map file is unrewarding. */
  157. static bool flag_map = false;
  158. /* Fallback to xlate if map file is unrewarding. */
  159. static bool flag_xlate = false;
  160. /* Root binary directory. */
  161. static const char *flag_root = "gcm.cache";
  162. #if NETWORKING
  163. static netmask_set_t netmask_set;
  164. static netmask_vec_t accept_addrs;
  165. #endif
  166. /* Strip out the source directory from FILE. */
  167. static const char *
  168. trim_src_file (const char *file)
  169. {
  170. static const char me[] = __FILE__;
  171. unsigned pos = 0;
  172. while (file[pos] == me[pos] && me[pos])
  173. pos++;
  174. while (pos && !IS_DIR_SEPARATOR (me[pos-1]))
  175. pos--;
  176. return file + pos;
  177. }
  178. /* Die screaming. */
  179. void ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF_1 ATTRIBUTE_COLD
  180. internal_error (const char *fmt, ...)
  181. {
  182. fprintf (stderr, "%s:Internal error ", progname);
  183. va_list args;
  184. va_start (args, fmt);
  185. vfprintf (stderr, fmt, args);
  186. va_end (args);
  187. fprintf (stderr, "\n");
  188. exit (2);
  189. }
  190. /* Hooked to from gcc_assert & gcc_unreachable. */
  191. #if ENABLE_ASSERT_CHECKING
  192. void ATTRIBUTE_NORETURN ATTRIBUTE_COLD
  193. fancy_abort (const char *file, int line, const char *func)
  194. {
  195. internal_error ("in %s, at %s:%d", func, trim_src_file (file), line);
  196. }
  197. #endif
  198. /* Exploded on a signal. */
  199. static void ATTRIBUTE_NORETURN ATTRIBUTE_COLD
  200. crash_signal (int sig)
  201. {
  202. signal (sig, SIG_DFL);
  203. // strsignal is not portable :(
  204. internal_error ("signal %d", sig);
  205. }
  206. /* A fatal error of some kind. */
  207. static void ATTRIBUTE_NORETURN ATTRIBUTE_COLD ATTRIBUTE_PRINTF_1
  208. error (const char *msg, ...)
  209. {
  210. fprintf (stderr, "%s:error: ", progname);
  211. va_list args;
  212. va_start (args, msg);
  213. vfprintf (stderr, msg, args);
  214. va_end (args);
  215. fprintf (stderr, "\n");
  216. exit (1);
  217. }
  218. #if NETWORKING
  219. /* Progress messages to the user. */
  220. static bool ATTRIBUTE_PRINTF_1 ATTRIBUTE_COLD
  221. noisy (const char *fmt, ...)
  222. {
  223. fprintf (stderr, "%s:", progname);
  224. va_list args;
  225. va_start (args, fmt);
  226. vfprintf (stderr, fmt, args);
  227. va_end (args);
  228. fprintf (stderr, "\n");
  229. return false;
  230. }
  231. #endif
  232. /* More messages to the user. */
  233. static void ATTRIBUTE_PRINTF_2
  234. fnotice (FILE *file, const char *fmt, ...)
  235. {
  236. va_list args;
  237. va_start (args, fmt);
  238. vfprintf (file, fmt, args);
  239. va_end (args);
  240. }
  241. static void ATTRIBUTE_NORETURN
  242. print_usage (int error_p)
  243. {
  244. FILE *file = error_p ? stderr : stdout;
  245. int status = error_p ? 1 : 0;
  246. fnotice (file, "Usage: %s [OPTION...] [CONNECTION] [MAPPINGS...] \n\n",
  247. progname);
  248. fnotice (file, "C++ Module Mapper.\n\n");
  249. fnotice (file, " -a, --accept Netmask to accept from\n");
  250. fnotice (file, " -f, --fallback Use fallback for missing mappings\n");
  251. fnotice (file, " -h, --help Print this help, then exit\n");
  252. fnotice (file, " -n, --noisy Print progress messages\n");
  253. fnotice (file, " -1, --one One connection and then exit\n");
  254. fnotice (file, " -r, --root DIR Root compiled module directory\n");
  255. fnotice (file, " -s, --sequential Process connections sequentially\n");
  256. fnotice (file, " -v, --version Print version number, then exit\n");
  257. fnotice (file, "Send SIGTERM(%d) to terminate\n", SIGTERM);
  258. fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
  259. bug_report_url);
  260. exit (status);
  261. }
  262. /* Print version information and exit. */
  263. static void ATTRIBUTE_NORETURN
  264. print_version (void)
  265. {
  266. fnotice (stdout, "%s %s%s\n", progname, pkgversion_string, version_string);
  267. fprintf (stdout, "Copyright %s 2018-2022 Free Software Foundation, Inc.\n",
  268. ("(C)"));
  269. fnotice (stdout,
  270. ("This is free software; see the source for copying conditions.\n"
  271. "There is NO warranty; not even for MERCHANTABILITY or \n"
  272. "FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
  273. exit (0);
  274. }
  275. /* ARG is a netmask to accept from. Add it to the table. Return
  276. false if we fail to resolve it. */
  277. static bool
  278. accept_from (char *arg ATTRIBUTE_UNUSED)
  279. {
  280. bool ok = true;
  281. #if HAVE_AF_INET6
  282. unsigned bits = sizeof (in6_addr) * 8;
  283. char *slash = strrchr (arg, '/');
  284. if (slash)
  285. {
  286. *slash = 0;
  287. if (slash[1])
  288. {
  289. char *endp;
  290. bits = strtoul (slash + 1, &endp, 0);
  291. }
  292. }
  293. addrinfo hints;
  294. hints.ai_flags = AI_NUMERICSERV;
  295. hints.ai_family = AF_INET6;
  296. hints.ai_socktype = SOCK_STREAM;
  297. hints.ai_protocol = 0;
  298. hints.ai_addrlen = 0;
  299. hints.ai_addr = NULL;
  300. hints.ai_canonname = NULL;
  301. hints.ai_next = NULL;
  302. struct addrinfo *addrs = NULL;
  303. /* getaddrinfo requires either hostname or servname to be non-null, so that we must
  304. set a port number (to cover the case that the string passed contains just /NN).
  305. Use an arbitrary in-range port number, but avoiding "0" which triggers a bug on
  306. some BSD variants. */
  307. if (int e = getaddrinfo (slash == arg ? NULL : arg, "1", &hints, &addrs))
  308. {
  309. noisy ("cannot resolve '%s': %s", arg, gai_strerror (e));
  310. ok = false;
  311. }
  312. else
  313. for (addrinfo *next = addrs; next; next = next->ai_next)
  314. if (next->ai_family == AF_INET6)
  315. {
  316. netmask mask (((const sockaddr_in6 *)next->ai_addr)->sin6_addr, bits);
  317. netmask_set.insert (mask);
  318. }
  319. freeaddrinfo (addrs);
  320. #endif
  321. return ok;
  322. }
  323. /* Process args, return index to first non-arg. */
  324. static int
  325. process_args (int argc, char **argv)
  326. {
  327. static const struct option options[] =
  328. {
  329. { "accept", required_argument, NULL, 'a' },
  330. { "help", no_argument, NULL, 'h' },
  331. { "map", no_argument, NULL, 'm' },
  332. { "noisy", no_argument, NULL, 'n' },
  333. { "one", no_argument, NULL, '1' },
  334. { "root", required_argument, NULL, 'r' },
  335. { "sequential", no_argument, NULL, 's' },
  336. { "translate",no_argument, NULL, 't' },
  337. { "version", no_argument, NULL, 'v' },
  338. { 0, 0, 0, 0 }
  339. };
  340. int opt;
  341. bool bad_accept = false;
  342. const char *opts = "a:fhmn1r:stv";
  343. while ((opt = getopt_long (argc, argv, opts, options, NULL)) != -1)
  344. {
  345. switch (opt)
  346. {
  347. case 'a':
  348. if (!accept_from (optarg))
  349. bad_accept = true;
  350. break;
  351. case 'h':
  352. print_usage (false);
  353. /* print_usage will exit. */
  354. case 'f': // deprecated alias
  355. case 'm':
  356. flag_map = true;
  357. break;
  358. case 'n':
  359. flag_noisy = true;
  360. break;
  361. case '1':
  362. flag_one = true;
  363. break;
  364. case 'r':
  365. flag_root = optarg;
  366. break;
  367. case 's':
  368. flag_sequential = true;
  369. break;
  370. case 't':
  371. flag_xlate = true;
  372. break;
  373. case 'v':
  374. print_version ();
  375. /* print_version will exit. */
  376. default:
  377. print_usage (true);
  378. /* print_usage will exit. */
  379. }
  380. }
  381. if (bad_accept)
  382. error ("failed to resolve all accept addresses");
  383. return optind;
  384. }
  385. #if NETWORKING
  386. /* Manipulate the EPOLL state, or do nothing, if there is epoll. */
  387. #ifdef HAVE_EPOLL
  388. static inline void
  389. do_epoll_ctl (int epoll_fd, int code, int event, int fd, unsigned data)
  390. {
  391. epoll_event ev;
  392. ev.events = event;
  393. ev.data.u32 = data;
  394. if (epoll_ctl (epoll_fd, code, fd, &ev))
  395. {
  396. noisy ("epoll_ctl error:%s", xstrerror (errno));
  397. gcc_unreachable ();
  398. }
  399. }
  400. #define my_epoll_ctl(EFD,C,EV,FD,CL) \
  401. ((EFD) >= 0 ? do_epoll_ctl (EFD,C,EV,FD,CL) : (void)0)
  402. #else
  403. #define my_epoll_ctl(EFD,C,EV,FD,CL) ((void)(EFD), (void)(FD), (void)(CL))
  404. #endif
  405. /* We increment this to tell the server to shut down. */
  406. static volatile int term = false;
  407. static volatile int kill_sock_fd = -1;
  408. #if !defined (HAVE_PSELECT) && defined (HAVE_SELECT)
  409. static int term_pipe[2] = {-1, -1};
  410. #else
  411. #define term_pipe ((int *)NULL)
  412. #endif
  413. /* A terminate signal. Shutdown gracefully. */
  414. static void
  415. term_signal (int sig)
  416. {
  417. signal (sig, term_signal);
  418. term = term + 1;
  419. if (term_pipe && term_pipe[1] >= 0)
  420. write (term_pipe[1], &term_pipe[1], 1);
  421. }
  422. /* A kill signal. Shutdown immediately. */
  423. static void
  424. kill_signal (int sig)
  425. {
  426. signal (sig, SIG_DFL);
  427. int sock_fd = kill_sock_fd;
  428. if (sock_fd >= 0)
  429. close (sock_fd);
  430. exit (2);
  431. }
  432. bool process_server (Cody::Server *server, unsigned slot, int epoll_fd)
  433. {
  434. switch (server->GetDirection ())
  435. {
  436. case Cody::Server::READING:
  437. if (int err = server->Read ())
  438. return !(err == EINTR || err == EAGAIN);
  439. server->ProcessRequests ();
  440. server->PrepareToWrite ();
  441. break;
  442. case Cody::Server::WRITING:
  443. if (int err = server->Write ())
  444. return !(err == EINTR || err == EAGAIN);
  445. server->PrepareToRead ();
  446. break;
  447. default:
  448. // We should never get here
  449. return true;
  450. }
  451. // We've changed direction, so update epoll
  452. gcc_assert (server->GetFDRead () == server->GetFDWrite ());
  453. my_epoll_ctl (epoll_fd, EPOLL_CTL_MOD,
  454. server->GetDirection () == Cody::Server::READING
  455. ? EPOLLIN : EPOLLOUT, server->GetFDRead (), slot + 1);
  456. return false;
  457. }
  458. void close_server (Cody::Server *server, int epoll_fd)
  459. {
  460. my_epoll_ctl (epoll_fd, EPOLL_CTL_DEL, EPOLLIN, server->GetFDRead (), 0);
  461. close (server->GetFDRead ());
  462. delete server;
  463. }
  464. int open_server (bool ip6, int sock_fd)
  465. {
  466. sockaddr_in6 addr;
  467. socklen_t addr_len = sizeof (addr);
  468. #ifdef HAVE_ACCEPT4
  469. int client_fd = accept4 (sock_fd, ip6 ? (sockaddr *)&addr : nullptr,
  470. &addr_len, SOCK_NONBLOCK);
  471. #else
  472. int client_fd = accept (sock_fd, ip6 ? (sockaddr *)&addr : nullptr, &addr_len);
  473. #endif
  474. if (client_fd < 0)
  475. {
  476. error ("cannot accept: %s", xstrerror (errno));
  477. flag_one = true;
  478. }
  479. else if (ip6)
  480. {
  481. const char *str = NULL;
  482. #if HAVE_INET_NTOP
  483. char name[INET6_ADDRSTRLEN];
  484. str = inet_ntop (addr.sin6_family, &addr.sin6_addr, name, sizeof (name));
  485. #endif
  486. if (!accept_addrs.empty ())
  487. {
  488. netmask_vec_t::iterator e = accept_addrs.end ();
  489. for (netmask_vec_t::iterator i = accept_addrs.begin ();
  490. i != e; ++i)
  491. if (i->includes (addr.sin6_addr))
  492. goto present;
  493. close (client_fd);
  494. client_fd = -1;
  495. noisy ("Rejecting connection from disallowed source '%s'",
  496. str ? str : "");
  497. present:;
  498. }
  499. if (client_fd >= 0)
  500. flag_noisy && noisy ("Accepting connection from '%s'", str ? str : "");
  501. }
  502. return client_fd;
  503. }
  504. /* A server listening on bound socket SOCK_FD. */
  505. static void
  506. server (bool ipv6, int sock_fd, module_resolver *resolver)
  507. {
  508. int epoll_fd = -1;
  509. signal (SIGTERM, term_signal);
  510. #ifdef HAVE_EPOLL
  511. epoll_fd = epoll_create (1);
  512. #endif
  513. if (epoll_fd >= 0)
  514. my_epoll_ctl (epoll_fd, EPOLL_CTL_ADD, EPOLLIN, sock_fd, 0);
  515. #if defined (HAVE_EPOLL) || defined (HAVE_PSELECT) || defined (HAVE_SELECT)
  516. sigset_t mask;
  517. {
  518. sigset_t block;
  519. sigemptyset (&block);
  520. sigaddset (&block, SIGTERM);
  521. sigprocmask (SIG_BLOCK, &block, &mask);
  522. }
  523. #endif
  524. #ifdef HAVE_EPOLL
  525. const unsigned max_events = 20;
  526. epoll_event events[max_events];
  527. #endif
  528. #if defined (HAVE_PSELECT) || defined (HAVE_SELECT)
  529. fd_set readers, writers;
  530. #endif
  531. if (term_pipe)
  532. pipe (term_pipe);
  533. // We need stable references to servers, so this array can contain nulls
  534. std::vector<Cody::Server *> connections;
  535. unsigned live = 0;
  536. while (sock_fd >= 0 || live)
  537. {
  538. /* Wait for one or more events. */
  539. bool eintr = false;
  540. int event_count;
  541. if (epoll_fd >= 0)
  542. {
  543. #ifdef HAVE_EPOLL
  544. event_count = epoll_pwait (epoll_fd, events, max_events, -1, &mask);
  545. #endif
  546. }
  547. else
  548. {
  549. #if defined (HAVE_PSELECT) || defined (HAVE_SELECT)
  550. FD_ZERO (&readers);
  551. FD_ZERO (&writers);
  552. unsigned limit = 0;
  553. if (sock_fd >= 0
  554. && !(term || (live && (flag_one || flag_sequential))))
  555. {
  556. FD_SET (sock_fd, &readers);
  557. limit = sock_fd + 1;
  558. }
  559. if (term_pipe && term_pipe[0] >= 0)
  560. {
  561. FD_SET (term_pipe[0], &readers);
  562. if (unsigned (term_pipe[0]) >= limit)
  563. limit = term_pipe[0] + 1;
  564. }
  565. for (auto iter = connections.begin ();
  566. iter != connections.end (); ++iter)
  567. if (auto *server = *iter)
  568. {
  569. int fd = -1;
  570. switch (server->GetDirection ())
  571. {
  572. case Cody::Server::READING:
  573. fd = server->GetFDRead ();
  574. FD_SET (fd, &readers);
  575. break;
  576. case Cody::Server::WRITING:
  577. fd = server->GetFDWrite ();
  578. FD_SET (fd, &writers);
  579. break;
  580. default:
  581. break;
  582. }
  583. if (fd >= 0 && limit <= unsigned (fd))
  584. limit = fd + 1;
  585. }
  586. #ifdef HAVE_PSELECT
  587. event_count = pselect (limit, &readers, &writers, NULL, NULL, &mask);
  588. #else
  589. event_count = select (limit, &readers, &writers, NULL, NULL);
  590. #endif
  591. if (term_pipe && FD_ISSET (term_pipe[0], &readers))
  592. {
  593. /* Fake up an interrupted system call. */
  594. event_count = -1;
  595. errno = EINTR;
  596. }
  597. #endif
  598. }
  599. if (event_count < 0)
  600. {
  601. // Error in waiting
  602. if (errno == EINTR)
  603. {
  604. flag_noisy && noisy ("Interrupted wait");
  605. eintr = true;
  606. }
  607. else
  608. error ("cannot %s: %s", epoll_fd >= 0 ? "epoll_wait"
  609. #ifdef HAVE_PSELECT
  610. : "pselect",
  611. #else
  612. : "select",
  613. #endif
  614. xstrerror (errno));
  615. event_count = 0;
  616. }
  617. auto iter = connections.begin ();
  618. while (event_count--)
  619. {
  620. // Process an event
  621. int active = -2;
  622. if (epoll_fd >= 0)
  623. {
  624. #ifdef HAVE_EPOLL
  625. /* See PR c++/88664 for why a temporary is used. */
  626. unsigned data = events[event_count].data.u32;
  627. active = int (data) - 1;
  628. #endif
  629. }
  630. else
  631. {
  632. for (; iter != connections.end (); ++iter)
  633. if (auto *server = *iter)
  634. {
  635. bool found = false;
  636. switch (server->GetDirection ())
  637. {
  638. #if defined (HAVE_PSELECT) || defined (HAVE_SELECT)
  639. case Cody::Server::READING:
  640. found = FD_ISSET (server->GetFDRead (), &readers);
  641. break;
  642. case Cody::Server::WRITING:
  643. found = FD_ISSET (server->GetFDWrite (), &writers);
  644. break;
  645. #endif
  646. default:
  647. break;
  648. }
  649. if (found)
  650. {
  651. active = iter - connections.begin ();
  652. ++iter;
  653. break;
  654. }
  655. }
  656. if (active < 0 && sock_fd >= 0 && FD_ISSET (sock_fd, &readers))
  657. active = -1;
  658. }
  659. if (active >= 0)
  660. {
  661. // Do the action
  662. auto *server = connections[active];
  663. if (process_server (server, active, epoll_fd))
  664. {
  665. connections[active] = nullptr;
  666. close_server (server, epoll_fd);
  667. live--;
  668. if (flag_sequential)
  669. my_epoll_ctl (epoll_fd, EPOLL_CTL_ADD, EPOLLIN, sock_fd, 0);
  670. }
  671. }
  672. else if (active == -1 && !eintr)
  673. {
  674. // New connection
  675. int fd = open_server (ipv6, sock_fd);
  676. if (fd >= 0)
  677. {
  678. #if !defined (HAVE_ACCEPT4) \
  679. && (defined (HAVE_EPOLL) || defined (HAVE_PSELECT) || defined (HAVE_SELECT))
  680. int flags = fcntl (fd, F_GETFL, 0);
  681. fcntl (fd, F_SETFL, flags | O_NONBLOCK);
  682. #endif
  683. auto *server = new Cody::Server (resolver, fd);
  684. unsigned slot = connections.size ();
  685. if (live == slot)
  686. connections.push_back (server);
  687. else
  688. for (auto iter = connections.begin (); ; ++iter)
  689. if (!*iter)
  690. {
  691. *iter = server;
  692. slot = iter - connections.begin ();
  693. break;
  694. }
  695. live++;
  696. my_epoll_ctl (epoll_fd, EPOLL_CTL_ADD, EPOLLIN, fd, slot + 1);
  697. }
  698. }
  699. if (sock_fd >= 0
  700. && (term || (live && (flag_one || flag_sequential))))
  701. {
  702. /* Stop paying attention to sock_fd. */
  703. my_epoll_ctl (epoll_fd, EPOLL_CTL_DEL, EPOLLIN, sock_fd, 0);
  704. if (flag_one || term)
  705. {
  706. close (sock_fd);
  707. sock_fd = -1;
  708. }
  709. }
  710. }
  711. }
  712. #if defined (HAVE_EPOLL) || defined (HAVE_PSELECT) || defined (HAVE_SELECT)
  713. /* Restore the signal mask. */
  714. sigprocmask (SIG_SETMASK, &mask, NULL);
  715. #endif
  716. gcc_assert (sock_fd < 0);
  717. if (epoll_fd >= 0)
  718. close (epoll_fd);
  719. if (term_pipe && term_pipe[0] >= 0)
  720. {
  721. close (term_pipe[0]);
  722. close (term_pipe[1]);
  723. }
  724. }
  725. #endif
  726. static int maybe_parse_socket (std::string &option, module_resolver *r)
  727. {
  728. /* Local or ipv6 address. */
  729. auto last = option.find_last_of ('?');
  730. if (last != option.npos)
  731. {
  732. r->set_ident (option.c_str () + last + 1);
  733. option.erase (last);
  734. }
  735. int fd = -2;
  736. char const *errmsg = nullptr;
  737. /* Does it look like a socket? */
  738. if (option[0] == '=')
  739. {
  740. /* A local socket. */
  741. #if CODY_NETWORKING
  742. fd = Cody::ListenLocal (&errmsg, option.c_str () + 1);
  743. #endif
  744. }
  745. else
  746. {
  747. auto colon = option.find_last_of (':');
  748. if (colon != option.npos)
  749. {
  750. /* Try a hostname:port address. */
  751. char const *cptr = option.c_str () + colon;
  752. char *endp;
  753. unsigned port = strtoul (cptr + 1, &endp, 10);
  754. if (port && endp != cptr + 1 && !*endp)
  755. {
  756. /* Ends in ':number', treat as ipv6 domain socket. */
  757. option.erase (colon);
  758. #if CODY_NETWORKING
  759. fd = Cody::ListenInet6 (&errmsg, option.c_str (), port);
  760. #endif
  761. }
  762. }
  763. }
  764. if (errmsg)
  765. error ("failed to open socket: %s", errmsg);
  766. return fd;
  767. }
  768. int
  769. main (int argc, char *argv[])
  770. {
  771. const char *p = argv[0] + strlen (argv[0]);
  772. while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
  773. --p;
  774. progname = p;
  775. #ifdef SIGSEGV
  776. signal (SIGSEGV, crash_signal);
  777. #endif
  778. #ifdef SIGILL
  779. signal (SIGILL, crash_signal);
  780. #endif
  781. #ifdef SIGBUS
  782. signal (SIGBUS, crash_signal);
  783. #endif
  784. #ifdef SIGABRT
  785. signal (SIGABRT, crash_signal);
  786. #endif
  787. #ifdef SIGFPE
  788. signal (SIGFPE, crash_signal);
  789. #endif
  790. #ifdef SIGPIPE
  791. /* Ignore sigpipe, so read/write get an error. */
  792. signal (SIGPIPE, SIG_IGN);
  793. #endif
  794. #if NETWORKING
  795. #ifdef SIGINT
  796. signal (SIGINT, kill_signal);
  797. #endif
  798. #endif
  799. int argno = process_args (argc, argv);
  800. std::string name;
  801. int sock_fd = -1; /* Socket fd, otherwise stdin/stdout. */
  802. module_resolver r (flag_map, flag_xlate);
  803. if (argno != argc)
  804. {
  805. name = argv[argno];
  806. sock_fd = maybe_parse_socket (name, &r);
  807. if (!name.empty ())
  808. argno++;
  809. }
  810. if (argno != argc)
  811. for (; argno != argc; argno++)
  812. {
  813. std::string option = argv[argno];
  814. char const *prefix = nullptr;
  815. auto ident = option.find_last_of ('?');
  816. if (ident != option.npos)
  817. {
  818. prefix = option.c_str () + ident + 1;
  819. option[ident] = 0;
  820. }
  821. int fd = open (option.c_str (), O_RDONLY | O_CLOEXEC);
  822. int err = 0;
  823. if (fd < 0)
  824. err = errno;
  825. else
  826. {
  827. err = r.read_tuple_file (fd, prefix, false);
  828. close (fd);
  829. }
  830. if (err)
  831. error ("failed reading '%s': %s", option.c_str (), xstrerror (err));
  832. }
  833. else
  834. r.set_default_map (true);
  835. if (flag_root)
  836. r.set_repo (flag_root);
  837. #ifdef HAVE_AF_INET6
  838. netmask_set_t::iterator end = netmask_set.end ();
  839. for (netmask_set_t::iterator iter = netmask_set.begin ();
  840. iter != end; ++iter)
  841. {
  842. netmask_vec_t::iterator e = accept_addrs.end ();
  843. for (netmask_vec_t::iterator i = accept_addrs.begin (); i != e; ++i)
  844. if (i->includes (iter->addr))
  845. goto present;
  846. accept_addrs.push_back (*iter);
  847. present:;
  848. }
  849. #endif
  850. #if NETWORKING
  851. if (sock_fd >= 0)
  852. {
  853. server (name[0] != '=', sock_fd, &r);
  854. if (name[0] == '=')
  855. unlink (name.c_str () + 1);
  856. }
  857. else
  858. #endif
  859. {
  860. auto server = Cody::Server (&r, 0, 1);
  861. int err = 0;
  862. for (;;)
  863. {
  864. server.PrepareToRead ();
  865. while ((err = server.Read ()))
  866. {
  867. if (err == EINTR || err == EAGAIN)
  868. continue;
  869. goto done;
  870. }
  871. server.ProcessRequests ();
  872. server.PrepareToWrite ();
  873. while ((err = server.Write ()))
  874. {
  875. if (err == EINTR || err == EAGAIN)
  876. continue;
  877. goto done;
  878. }
  879. }
  880. done:;
  881. if (err > 0)
  882. error ("communication error:%s", xstrerror (err));
  883. }
  884. return 0;
  885. }