gnunet-service-arm.c 64 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2009-2011, 2015, 2016 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file arm/gnunet-service-arm.c
  18. * @brief the automated restart manager service
  19. * @author Christian Grothoff
  20. */
  21. #include "platform.h"
  22. #include "gnunet_util_lib.h"
  23. #include "gnunet_arm_service.h"
  24. #include "gnunet_protocols.h"
  25. #include "arm.h"
  26. #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
  27. #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
  28. #if HAVE_WAIT4
  29. /**
  30. * Name of the file for writing resource utilization summaries to.
  31. */
  32. static char *wait_filename;
  33. /**
  34. * Handle for the file for writing resource summaries.
  35. */
  36. static FILE *wait_file;
  37. #endif
  38. /**
  39. * How many messages do we queue up at most for optional
  40. * notifications to a client? (this can cause notifications
  41. * about outgoing messages to be dropped).
  42. */
  43. #define MAX_NOTIFY_QUEUE 1024
  44. /**
  45. * List of our services.
  46. */
  47. struct ServiceList;
  48. /**
  49. * Record with information about a listen socket we have open.
  50. */
  51. struct ServiceListeningInfo
  52. {
  53. /**
  54. * This is a linked list.
  55. */
  56. struct ServiceListeningInfo *next;
  57. /**
  58. * This is a linked list.
  59. */
  60. struct ServiceListeningInfo *prev;
  61. /**
  62. * Address this socket is listening on.
  63. */
  64. struct sockaddr *service_addr;
  65. /**
  66. * Service this listen socket is for.
  67. */
  68. struct ServiceList *sl;
  69. /**
  70. * Number of bytes in @e service_addr
  71. */
  72. socklen_t service_addr_len;
  73. /**
  74. * Our listening socket.
  75. */
  76. struct GNUNET_NETWORK_Handle *listen_socket;
  77. /**
  78. * Task doing the accepting.
  79. */
  80. struct GNUNET_SCHEDULER_Task *accept_task;
  81. };
  82. /**
  83. * List of our services.
  84. */
  85. struct ServiceList
  86. {
  87. /**
  88. * This is a doubly-linked list.
  89. */
  90. struct ServiceList *next;
  91. /**
  92. * This is a doubly-linked list.
  93. */
  94. struct ServiceList *prev;
  95. /**
  96. * Linked list of listen sockets associated with this service.
  97. */
  98. struct ServiceListeningInfo *listen_head;
  99. /**
  100. * Linked list of listen sockets associated with this service.
  101. */
  102. struct ServiceListeningInfo *listen_tail;
  103. /**
  104. * Name of the service.
  105. */
  106. char *name;
  107. /**
  108. * Name of the binary used.
  109. */
  110. char *binary;
  111. /**
  112. * Name of the configuration file used.
  113. */
  114. char *config;
  115. /**
  116. * Client to notify upon kill completion (waitpid), NULL
  117. * if we should simply restart the process.
  118. */
  119. struct GNUNET_SERVICE_Client *killing_client;
  120. /**
  121. * ID of the request that killed the service (for reporting back).
  122. */
  123. uint64_t killing_client_request_id;
  124. /**
  125. * Process structure pointer of the child.
  126. */
  127. struct GNUNET_OS_Process *proc;
  128. /**
  129. * Process exponential backoff time
  130. */
  131. struct GNUNET_TIME_Relative backoff;
  132. /**
  133. * Absolute time at which the process is scheduled to restart in case of death
  134. */
  135. struct GNUNET_TIME_Absolute restart_at;
  136. /**
  137. * Time we asked the service to shut down (used to calculate time it took
  138. * the service to terminate).
  139. */
  140. struct GNUNET_TIME_Absolute killed_at;
  141. /**
  142. * Is this service to be started by default (or did a client tell us explicitly
  143. * to start it)? #GNUNET_NO if the service is started only upon 'accept' on a
  144. * listen socket or possibly explicitly by a client changing the value.
  145. */
  146. int force_start;
  147. /**
  148. * Should we use pipes to signal this process? (YES for Java binaries and if we
  149. * are on Windoze).
  150. */
  151. int pipe_control;
  152. };
  153. /**
  154. * List of running services.
  155. */
  156. static struct ServiceList *running_head;
  157. /**
  158. * List of running services.
  159. */
  160. static struct ServiceList *running_tail;
  161. /**
  162. * Our configuration
  163. */
  164. static const struct GNUNET_CONFIGURATION_Handle *cfg;
  165. /**
  166. * Command to prepend to each actual command.
  167. */
  168. static char *prefix_command;
  169. /**
  170. * Option to append to each actual command.
  171. */
  172. static char *final_option;
  173. /**
  174. * ID of task called whenever we get a SIGCHILD.
  175. */
  176. static struct GNUNET_SCHEDULER_Task *child_death_task;
  177. /**
  178. * ID of task called whenever the timeout for restarting a child
  179. * expires.
  180. */
  181. static struct GNUNET_SCHEDULER_Task *child_restart_task;
  182. /**
  183. * Pipe used to communicate shutdown via signal.
  184. */
  185. static struct GNUNET_DISK_PipeHandle *sigpipe;
  186. /**
  187. * Are we in shutdown mode?
  188. */
  189. static int in_shutdown;
  190. /**
  191. * Return value from main
  192. */
  193. static int global_ret;
  194. /**
  195. * Are we starting user services?
  196. */
  197. static int start_user = GNUNET_YES;
  198. /**
  199. * Are we starting system services?
  200. */
  201. static int start_system = GNUNET_YES;
  202. /**
  203. * Handle to our service instance. Our service is a bit special in that
  204. * its service is not immediately stopped once we get a shutdown
  205. * request (since we need to continue service until all of our child
  206. * processes are dead). This handle is used to shut down the service
  207. * (and thus trigger process termination) once all child processes are
  208. * also dead. A special option in the ARM configuration modifies the
  209. * behaviour of the service implementation to not do the shutdown
  210. * immediately.
  211. */
  212. static struct GNUNET_SERVICE_Handle *service;
  213. /**
  214. * Context for notifications we need to send to our clients.
  215. */
  216. static struct GNUNET_NotificationContext *notifier;
  217. /**
  218. * Add the given UNIX domain path as an address to the
  219. * list (as the first entry).
  220. *
  221. * @param saddrs array to update
  222. * @param saddrlens where to store the address length
  223. * @param unixpath path to add
  224. * @param abstract #GNUNET_YES to add an abstract UNIX domain socket. This
  225. * parameter is ignore on systems other than LINUX
  226. */
  227. static void
  228. add_unixpath (struct sockaddr **saddrs,
  229. socklen_t *saddrlens,
  230. const char *unixpath,
  231. int abstract)
  232. {
  233. #ifdef AF_UNIX
  234. struct sockaddr_un *un;
  235. un = GNUNET_new (struct sockaddr_un);
  236. un->sun_family = AF_UNIX;
  237. GNUNET_strlcpy (un->sun_path, unixpath, sizeof (un->sun_path));
  238. #ifdef LINUX
  239. if (GNUNET_YES == abstract)
  240. un->sun_path[0] = '\0';
  241. #endif
  242. #if HAVE_SOCKADDR_UN_SUN_LEN
  243. un->sun_len = (u_char) sizeof (struct sockaddr_un);
  244. #endif
  245. *saddrs = (struct sockaddr *) un;
  246. *saddrlens = sizeof (struct sockaddr_un);
  247. #else
  248. /* this function should never be called
  249. * unless AF_UNIX is defined! */
  250. GNUNET_assert (0);
  251. #endif
  252. }
  253. /**
  254. * Get the list of addresses that a server for the given service
  255. * should bind to.
  256. *
  257. * @param service_name name of the service
  258. * @param cfg configuration (which specifies the addresses)
  259. * @param addrs set (call by reference) to an array of pointers to the
  260. * addresses the server should bind to and listen on; the
  261. * array will be NULL-terminated (on success)
  262. * @param addr_lens set (call by reference) to an array of the lengths
  263. * of the respective `struct sockaddr` struct in the @a addrs
  264. * array (on success)
  265. * @return number of addresses found on success,
  266. * #GNUNET_SYSERR if the configuration
  267. * did not specify reasonable finding information or
  268. * if it specified a hostname that could not be resolved;
  269. * #GNUNET_NO if the number of addresses configured is
  270. * zero (in this case, `*addrs` and `*addr_lens` will be
  271. * set to NULL).
  272. */
  273. static int
  274. get_server_addresses (const char *service_name,
  275. const struct GNUNET_CONFIGURATION_Handle *cfg,
  276. struct sockaddr ***addrs,
  277. socklen_t ** addr_lens)
  278. {
  279. int disablev6;
  280. struct GNUNET_NETWORK_Handle *desc;
  281. unsigned long long port;
  282. char *unixpath;
  283. struct addrinfo hints;
  284. struct addrinfo *res;
  285. struct addrinfo *pos;
  286. struct addrinfo *next;
  287. unsigned int i;
  288. int resi;
  289. int ret;
  290. int abstract;
  291. struct sockaddr **saddrs;
  292. socklen_t *saddrlens;
  293. char *hostname;
  294. *addrs = NULL;
  295. *addr_lens = NULL;
  296. desc = NULL;
  297. if (GNUNET_CONFIGURATION_have_value (cfg,
  298. service_name,
  299. "DISABLEV6"))
  300. {
  301. if (GNUNET_SYSERR ==
  302. (disablev6 =
  303. GNUNET_CONFIGURATION_get_value_yesno (cfg,
  304. service_name,
  305. "DISABLEV6")))
  306. return GNUNET_SYSERR;
  307. }
  308. else
  309. disablev6 = GNUNET_NO;
  310. if (! disablev6)
  311. {
  312. /* probe IPv6 support */
  313. desc = GNUNET_NETWORK_socket_create (PF_INET6,
  314. SOCK_STREAM,
  315. 0);
  316. if (NULL == desc)
  317. {
  318. if ( (ENOBUFS == errno) ||
  319. (ENOMEM == errno) ||
  320. (ENFILE == errno) ||
  321. (EACCES == errno) )
  322. {
  323. LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
  324. "socket");
  325. return GNUNET_SYSERR;
  326. }
  327. LOG (GNUNET_ERROR_TYPE_INFO,
  328. _("Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n"),
  329. service_name,
  330. STRERROR (errno));
  331. disablev6 = GNUNET_YES;
  332. }
  333. else
  334. {
  335. GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc));
  336. desc = NULL;
  337. }
  338. }
  339. port = 0;
  340. if (GNUNET_CONFIGURATION_have_value (cfg,
  341. service_name,
  342. "PORT"))
  343. {
  344. if (GNUNET_OK !=
  345. GNUNET_CONFIGURATION_get_value_number (cfg,
  346. service_name,
  347. "PORT",
  348. &port))
  349. {
  350. LOG (GNUNET_ERROR_TYPE_ERROR,
  351. _("Require valid port number for service `%s' in configuration!\n"),
  352. service_name);
  353. }
  354. if (port > 65535)
  355. {
  356. LOG (GNUNET_ERROR_TYPE_ERROR,
  357. _("Require valid port number for service `%s' in configuration!\n"),
  358. service_name);
  359. return GNUNET_SYSERR;
  360. }
  361. }
  362. if (GNUNET_CONFIGURATION_have_value (cfg,
  363. service_name,
  364. "BINDTO"))
  365. {
  366. GNUNET_break (GNUNET_OK ==
  367. GNUNET_CONFIGURATION_get_value_string (cfg,
  368. service_name,
  369. "BINDTO",
  370. &hostname));
  371. }
  372. else
  373. hostname = NULL;
  374. unixpath = NULL;
  375. abstract = GNUNET_NO;
  376. #ifdef AF_UNIX
  377. if ((GNUNET_YES ==
  378. GNUNET_CONFIGURATION_have_value (cfg,
  379. service_name,
  380. "UNIXPATH")) &&
  381. (GNUNET_OK ==
  382. GNUNET_CONFIGURATION_get_value_filename (cfg,
  383. service_name,
  384. "UNIXPATH",
  385. &unixpath)) &&
  386. (0 < strlen (unixpath)))
  387. {
  388. /* probe UNIX support */
  389. struct sockaddr_un s_un;
  390. if (strlen (unixpath) >= sizeof (s_un.sun_path))
  391. {
  392. LOG (GNUNET_ERROR_TYPE_WARNING,
  393. _("UNIXPATH `%s' too long, maximum length is %llu\n"),
  394. unixpath,
  395. (unsigned long long) sizeof (s_un.sun_path));
  396. unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
  397. LOG (GNUNET_ERROR_TYPE_INFO,
  398. _("Using `%s' instead\n"),
  399. unixpath);
  400. }
  401. #ifdef LINUX
  402. abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg,
  403. "TESTING",
  404. "USE_ABSTRACT_SOCKETS");
  405. if (GNUNET_SYSERR == abstract)
  406. abstract = GNUNET_NO;
  407. #endif
  408. if ( (GNUNET_YES != abstract) &&
  409. (GNUNET_OK !=
  410. GNUNET_DISK_directory_create_for_file (unixpath)) )
  411. GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
  412. "mkdir",
  413. unixpath);
  414. }
  415. if (NULL != unixpath)
  416. {
  417. desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
  418. if (NULL == desc)
  419. {
  420. if ( (ENOBUFS == errno) ||
  421. (ENOMEM == errno) ||
  422. (ENFILE == errno) ||
  423. (EACCES == errno) )
  424. {
  425. LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket");
  426. GNUNET_free_non_null (hostname);
  427. GNUNET_free (unixpath);
  428. return GNUNET_SYSERR;
  429. }
  430. LOG (GNUNET_ERROR_TYPE_INFO,
  431. _("Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
  432. service_name,
  433. STRERROR (errno));
  434. GNUNET_free (unixpath);
  435. unixpath = NULL;
  436. }
  437. else
  438. {
  439. GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc));
  440. desc = NULL;
  441. }
  442. }
  443. #endif
  444. if ( (0 == port) &&
  445. (NULL == unixpath) )
  446. {
  447. if (GNUNET_YES ==
  448. GNUNET_CONFIGURATION_get_value_yesno (cfg,
  449. service_name,
  450. "START_ON_DEMAND"))
  451. LOG (GNUNET_ERROR_TYPE_ERROR,
  452. _("Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
  453. service_name);
  454. GNUNET_free_non_null (hostname);
  455. return GNUNET_SYSERR;
  456. }
  457. if (0 == port)
  458. {
  459. saddrs = GNUNET_new_array (2,
  460. struct sockaddr *);
  461. saddrlens = GNUNET_new_array (2,
  462. socklen_t);
  463. add_unixpath (saddrs,
  464. saddrlens,
  465. unixpath,
  466. abstract);
  467. GNUNET_free_non_null (unixpath);
  468. GNUNET_free_non_null (hostname);
  469. *addrs = saddrs;
  470. *addr_lens = saddrlens;
  471. return 1;
  472. }
  473. if (NULL != hostname)
  474. {
  475. LOG (GNUNET_ERROR_TYPE_DEBUG,
  476. "Resolving `%s' since that is where `%s' will bind to.\n",
  477. hostname,
  478. service_name);
  479. memset (&hints, 0, sizeof (struct addrinfo));
  480. if (disablev6)
  481. hints.ai_family = AF_INET;
  482. hints.ai_protocol = IPPROTO_TCP;
  483. if ((0 != (ret = getaddrinfo (hostname,
  484. NULL,
  485. &hints,
  486. &res))) ||
  487. (NULL == res))
  488. {
  489. LOG (GNUNET_ERROR_TYPE_ERROR,
  490. _("Failed to resolve `%s': %s\n"),
  491. hostname,
  492. gai_strerror (ret));
  493. GNUNET_free (hostname);
  494. GNUNET_free_non_null (unixpath);
  495. return GNUNET_SYSERR;
  496. }
  497. next = res;
  498. i = 0;
  499. while (NULL != (pos = next))
  500. {
  501. next = pos->ai_next;
  502. if ((disablev6) && (pos->ai_family == AF_INET6))
  503. continue;
  504. i++;
  505. }
  506. if (0 == i)
  507. {
  508. LOG (GNUNET_ERROR_TYPE_ERROR,
  509. _("Failed to find %saddress for `%s'.\n"),
  510. disablev6 ? "IPv4 " : "",
  511. hostname);
  512. freeaddrinfo (res);
  513. GNUNET_free (hostname);
  514. GNUNET_free_non_null (unixpath);
  515. return GNUNET_SYSERR;
  516. }
  517. resi = i;
  518. if (NULL != unixpath)
  519. resi++;
  520. saddrs = GNUNET_new_array (resi + 1,
  521. struct sockaddr *);
  522. saddrlens = GNUNET_new_array (resi + 1,
  523. socklen_t);
  524. i = 0;
  525. if (NULL != unixpath)
  526. {
  527. add_unixpath (saddrs, saddrlens, unixpath, abstract);
  528. i++;
  529. }
  530. next = res;
  531. while (NULL != (pos = next))
  532. {
  533. next = pos->ai_next;
  534. if ((disablev6) && (AF_INET6 == pos->ai_family))
  535. continue;
  536. if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
  537. continue; /* not TCP */
  538. if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
  539. continue; /* huh? */
  540. LOG (GNUNET_ERROR_TYPE_DEBUG, "Service `%s' will bind to `%s'\n",
  541. service_name, GNUNET_a2s (pos->ai_addr, pos->ai_addrlen));
  542. if (AF_INET == pos->ai_family)
  543. {
  544. GNUNET_assert (sizeof (struct sockaddr_in) == pos->ai_addrlen);
  545. saddrlens[i] = pos->ai_addrlen;
  546. saddrs[i] = GNUNET_malloc (saddrlens[i]);
  547. GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
  548. ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
  549. }
  550. else
  551. {
  552. GNUNET_assert (AF_INET6 == pos->ai_family);
  553. GNUNET_assert (sizeof (struct sockaddr_in6) == pos->ai_addrlen);
  554. saddrlens[i] = pos->ai_addrlen;
  555. saddrs[i] = GNUNET_malloc (saddrlens[i]);
  556. GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
  557. ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
  558. }
  559. i++;
  560. }
  561. GNUNET_free (hostname);
  562. freeaddrinfo (res);
  563. resi = i;
  564. }
  565. else
  566. {
  567. /* will bind against everything, just set port */
  568. if (disablev6)
  569. {
  570. /* V4-only */
  571. resi = 1;
  572. if (NULL != unixpath)
  573. resi++;
  574. i = 0;
  575. saddrs = GNUNET_new_array (resi + 1,
  576. struct sockaddr *);
  577. saddrlens = GNUNET_new_array (resi + 1,
  578. socklen_t);
  579. if (NULL != unixpath)
  580. {
  581. add_unixpath (saddrs, saddrlens, unixpath, abstract);
  582. i++;
  583. }
  584. saddrlens[i] = sizeof (struct sockaddr_in);
  585. saddrs[i] = GNUNET_malloc (saddrlens[i]);
  586. #if HAVE_SOCKADDR_IN_SIN_LEN
  587. ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i];
  588. #endif
  589. ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
  590. ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
  591. }
  592. else
  593. {
  594. /* dual stack */
  595. resi = 2;
  596. if (NULL != unixpath)
  597. resi++;
  598. saddrs = GNUNET_new_array (resi + 1,
  599. struct sockaddr *);
  600. saddrlens = GNUNET_new_array (resi + 1,
  601. socklen_t);
  602. i = 0;
  603. if (NULL != unixpath)
  604. {
  605. add_unixpath (saddrs,
  606. saddrlens,
  607. unixpath,
  608. abstract);
  609. i++;
  610. }
  611. saddrlens[i] = sizeof (struct sockaddr_in6);
  612. saddrs[i] = GNUNET_malloc (saddrlens[i]);
  613. #if HAVE_SOCKADDR_IN_SIN_LEN
  614. ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0];
  615. #endif
  616. ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6;
  617. ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
  618. i++;
  619. saddrlens[i] = sizeof (struct sockaddr_in);
  620. saddrs[i] = GNUNET_malloc (saddrlens[i]);
  621. #if HAVE_SOCKADDR_IN_SIN_LEN
  622. ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1];
  623. #endif
  624. ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
  625. ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
  626. }
  627. }
  628. GNUNET_free_non_null (unixpath);
  629. *addrs = saddrs;
  630. *addr_lens = saddrlens;
  631. return resi;
  632. }
  633. /**
  634. * Signal our client that we will start or stop the
  635. * service.
  636. *
  637. * @param client who is being signalled
  638. * @param name name of the service
  639. * @param request_id id of the request that is being responded to.
  640. * @param result message type to send
  641. * @return NULL if it was not found
  642. */
  643. static void
  644. signal_result (struct GNUNET_SERVICE_Client *client,
  645. const char *name,
  646. uint64_t request_id,
  647. enum GNUNET_ARM_Result result)
  648. {
  649. struct GNUNET_MQ_Envelope *env;
  650. struct GNUNET_ARM_ResultMessage *msg;
  651. (void) name;
  652. env = GNUNET_MQ_msg (msg,
  653. GNUNET_MESSAGE_TYPE_ARM_RESULT);
  654. msg->result = htonl (result);
  655. msg->arm_msg.request_id = GNUNET_htonll (request_id);
  656. GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
  657. env);
  658. }
  659. /**
  660. * Tell all clients about status change of a service.
  661. *
  662. * @param name name of the service
  663. * @param status message type to send
  664. * @param unicast if not NULL, send to this client only.
  665. * otherwise, send to all clients in the notifier
  666. */
  667. static void
  668. broadcast_status (const char *name,
  669. enum GNUNET_ARM_ServiceStatus status,
  670. struct GNUNET_SERVICE_Client *unicast)
  671. {
  672. struct GNUNET_MQ_Envelope *env;
  673. struct GNUNET_ARM_StatusMessage *msg;
  674. size_t namelen;
  675. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  676. "Sending status %u of service `%s' to client\n",
  677. (unsigned int) status,
  678. name);
  679. namelen = strlen (name) + 1;
  680. env = GNUNET_MQ_msg_extra (msg,
  681. namelen,
  682. GNUNET_MESSAGE_TYPE_ARM_STATUS);
  683. msg->status = htonl ((uint32_t) (status));
  684. GNUNET_memcpy ((char *) &msg[1],
  685. name,
  686. namelen);
  687. if (NULL == unicast)
  688. {
  689. if (NULL != notifier)
  690. GNUNET_notification_context_broadcast (notifier,
  691. &msg->header,
  692. GNUNET_YES);
  693. GNUNET_MQ_discard (env);
  694. }
  695. else
  696. {
  697. GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (unicast),
  698. env);
  699. }
  700. }
  701. /**
  702. * Actually start the process for the given service.
  703. *
  704. * @param sl identifies service to start
  705. * @param client that asked to start the service (may be NULL)
  706. * @param request_id id of the request in response to which the process is
  707. * being started. 0 if starting was not requested.
  708. */
  709. static void
  710. start_process (struct ServiceList *sl,
  711. struct GNUNET_SERVICE_Client *client,
  712. uint64_t request_id)
  713. {
  714. char *loprefix;
  715. char *options;
  716. int use_debug;
  717. int is_simple_service;
  718. struct ServiceListeningInfo *sli;
  719. SOCKTYPE *lsocks;
  720. unsigned int ls;
  721. char *binary;
  722. char *quotedbinary;
  723. /* calculate listen socket list */
  724. lsocks = NULL;
  725. ls = 0;
  726. for (sli = sl->listen_head; NULL != sli; sli = sli->next)
  727. {
  728. GNUNET_array_append (lsocks, ls,
  729. GNUNET_NETWORK_get_fd (sli->listen_socket));
  730. if (NULL != sli->accept_task)
  731. {
  732. GNUNET_SCHEDULER_cancel (sli->accept_task);
  733. sli->accept_task = NULL;
  734. }
  735. }
  736. #if WINDOWS
  737. GNUNET_array_append (lsocks,
  738. ls,
  739. INVALID_SOCKET);
  740. #else
  741. GNUNET_array_append (lsocks,
  742. ls,
  743. -1);
  744. #endif
  745. /* obtain configuration */
  746. if (GNUNET_OK !=
  747. GNUNET_CONFIGURATION_get_value_string (cfg,
  748. sl->name,
  749. "PREFIX",
  750. &loprefix))
  751. loprefix = GNUNET_strdup (prefix_command);
  752. else
  753. loprefix = GNUNET_CONFIGURATION_expand_dollar (cfg,
  754. loprefix);
  755. if (GNUNET_OK !=
  756. GNUNET_CONFIGURATION_get_value_string (cfg,
  757. sl->name,
  758. "OPTIONS",
  759. &options))
  760. options = NULL;
  761. else
  762. options = GNUNET_CONFIGURATION_expand_dollar (cfg,
  763. options);
  764. {
  765. char *new_options;
  766. char *optpos;
  767. char *fin_options;
  768. fin_options = GNUNET_strdup (final_option);
  769. /* replace '{}' with service name */
  770. while (NULL != (optpos = strstr (fin_options,
  771. "{}")))
  772. {
  773. /* terminate string at opening parenthesis */
  774. *optpos = 0;
  775. GNUNET_asprintf (&new_options,
  776. "%s%s%s",
  777. fin_options,
  778. sl->name,
  779. optpos + 2);
  780. GNUNET_free (fin_options);
  781. fin_options = new_options;
  782. }
  783. if (NULL != options)
  784. {
  785. /* combine "fin_options" with "options" */
  786. optpos = options;
  787. GNUNET_asprintf (&options,
  788. "%s %s",
  789. fin_options,
  790. optpos);
  791. GNUNET_free (fin_options);
  792. GNUNET_free (optpos);
  793. }
  794. else
  795. {
  796. /* only have "fin_options", use that */
  797. options = fin_options;
  798. }
  799. }
  800. options = GNUNET_CONFIGURATION_expand_dollar (cfg,
  801. options);
  802. use_debug = GNUNET_CONFIGURATION_get_value_yesno (cfg,
  803. sl->name,
  804. "DEBUG");
  805. {
  806. const char *service_type = NULL;
  807. const char *choices[] = { "GNUNET", "SIMPLE", NULL };
  808. is_simple_service = GNUNET_NO;
  809. if ( (GNUNET_OK ==
  810. GNUNET_CONFIGURATION_get_value_choice (cfg,
  811. sl->name,
  812. "TYPE",
  813. choices,
  814. &service_type)) &&
  815. (0 == strcasecmp (service_type, "SIMPLE")) )
  816. is_simple_service = GNUNET_YES;
  817. }
  818. GNUNET_assert (NULL == sl->proc);
  819. if (GNUNET_YES == is_simple_service)
  820. {
  821. /* A simple service will receive no GNUnet specific
  822. command line options. */
  823. binary = GNUNET_strdup (sl->binary);
  824. binary = GNUNET_CONFIGURATION_expand_dollar (cfg, binary);
  825. GNUNET_asprintf (&quotedbinary,
  826. "\"%s\"",
  827. sl->binary);
  828. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  829. "Starting simple service `%s' using binary `%s'\n",
  830. sl->name, sl->binary);
  831. /* FIXME: dollar expansion should only be done outside
  832. * of ''-quoted strings, escaping should be considered. */
  833. if (NULL != options)
  834. options = GNUNET_CONFIGURATION_expand_dollar (cfg, options);
  835. sl->proc =
  836. GNUNET_OS_start_process_s (sl->pipe_control,
  837. GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
  838. lsocks,
  839. loprefix,
  840. quotedbinary,
  841. options,
  842. NULL);
  843. }
  844. else
  845. {
  846. /* actually start process */
  847. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  848. "Starting service `%s' using binary `%s' and configuration `%s'\n",
  849. sl->name, sl->binary, sl->config);
  850. binary = GNUNET_OS_get_libexec_binary_path (sl->binary);
  851. GNUNET_asprintf (&quotedbinary,
  852. "\"%s\"",
  853. binary);
  854. if (GNUNET_YES == use_debug)
  855. {
  856. if (NULL == sl->config)
  857. sl->proc =
  858. GNUNET_OS_start_process_s (sl->pipe_control,
  859. GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
  860. lsocks,
  861. loprefix,
  862. quotedbinary,
  863. "-L", "DEBUG",
  864. options,
  865. NULL);
  866. else
  867. sl->proc =
  868. GNUNET_OS_start_process_s (sl->pipe_control,
  869. GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
  870. lsocks,
  871. loprefix,
  872. quotedbinary,
  873. "-c", sl->config,
  874. "-L", "DEBUG",
  875. options,
  876. NULL);
  877. }
  878. else
  879. {
  880. if (NULL == sl->config)
  881. sl->proc =
  882. GNUNET_OS_start_process_s (sl->pipe_control,
  883. GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
  884. lsocks,
  885. loprefix,
  886. quotedbinary,
  887. options,
  888. NULL);
  889. else
  890. sl->proc =
  891. GNUNET_OS_start_process_s (sl->pipe_control,
  892. GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
  893. lsocks,
  894. loprefix,
  895. quotedbinary,
  896. "-c", sl->config,
  897. options,
  898. NULL);
  899. }
  900. }
  901. GNUNET_free (binary);
  902. GNUNET_free (quotedbinary);
  903. if (NULL == sl->proc)
  904. {
  905. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  906. _("Failed to start service `%s'\n"),
  907. sl->name);
  908. if (client)
  909. signal_result (client,
  910. sl->name,
  911. request_id,
  912. GNUNET_ARM_RESULT_START_FAILED);
  913. }
  914. else
  915. {
  916. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  917. _("Starting service `%s'\n"),
  918. sl->name);
  919. broadcast_status (sl->name,
  920. GNUNET_ARM_SERVICE_STARTING,
  921. NULL);
  922. if (client)
  923. signal_result (client,
  924. sl->name,
  925. request_id,
  926. GNUNET_ARM_RESULT_STARTING);
  927. }
  928. /* clean up */
  929. GNUNET_free (loprefix);
  930. GNUNET_free (options);
  931. GNUNET_array_grow (lsocks,
  932. ls,
  933. 0);
  934. }
  935. /**
  936. * Find the process with the given service
  937. * name in the given list and return it.
  938. *
  939. * @param name which service entry to look up
  940. * @return NULL if it was not found
  941. */
  942. static struct ServiceList *
  943. find_service (const char *name)
  944. {
  945. struct ServiceList *sl;
  946. sl = running_head;
  947. while (sl != NULL)
  948. {
  949. if (0 == strcasecmp (sl->name, name))
  950. return sl;
  951. sl = sl->next;
  952. }
  953. return NULL;
  954. }
  955. /**
  956. * First connection has come to the listening socket associated with the service,
  957. * create the service in order to relay the incoming connection to it
  958. *
  959. * @param cls callback data, `struct ServiceListeningInfo` describing a listen socket
  960. */
  961. static void
  962. accept_connection (void *cls)
  963. {
  964. struct ServiceListeningInfo *sli = cls;
  965. struct ServiceList *sl = sli->sl;
  966. sli->accept_task = NULL;
  967. GNUNET_assert (GNUNET_NO == in_shutdown);
  968. start_process (sl, NULL, 0);
  969. }
  970. /**
  971. * Creating a listening socket for each of the service's addresses and
  972. * wait for the first incoming connection to it
  973. *
  974. * @param sa address associated with the service
  975. * @param addr_len length of @a sa
  976. * @param sl service entry for the service in question
  977. */
  978. static void
  979. create_listen_socket (struct sockaddr *sa,
  980. socklen_t addr_len,
  981. struct ServiceList *sl)
  982. {
  983. static int on = 1;
  984. struct GNUNET_NETWORK_Handle *sock;
  985. struct ServiceListeningInfo *sli;
  986. #ifndef WINDOWS
  987. int match_uid;
  988. int match_gid;
  989. #endif
  990. switch (sa->sa_family)
  991. {
  992. case AF_INET:
  993. sock = GNUNET_NETWORK_socket_create (PF_INET,
  994. SOCK_STREAM,
  995. 0);
  996. break;
  997. case AF_INET6:
  998. sock = GNUNET_NETWORK_socket_create (PF_INET6,
  999. SOCK_STREAM,
  1000. 0);
  1001. break;
  1002. case AF_UNIX:
  1003. if (0 == strcmp (GNUNET_a2s (sa,
  1004. addr_len),
  1005. "@")) /* Do not bind to blank UNIX path! */
  1006. return;
  1007. sock = GNUNET_NETWORK_socket_create (PF_UNIX,
  1008. SOCK_STREAM,
  1009. 0);
  1010. break;
  1011. default:
  1012. GNUNET_break (0);
  1013. sock = NULL;
  1014. errno = EAFNOSUPPORT;
  1015. break;
  1016. }
  1017. if (NULL == sock)
  1018. {
  1019. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  1020. _("Unable to create socket for service `%s': %s\n"),
  1021. sl->name,
  1022. STRERROR (errno));
  1023. GNUNET_free (sa);
  1024. return;
  1025. }
  1026. if (GNUNET_OK !=
  1027. GNUNET_NETWORK_socket_setsockopt (sock,
  1028. SOL_SOCKET,
  1029. SO_REUSEADDR,
  1030. &on,
  1031. sizeof (on)))
  1032. GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
  1033. "setsockopt");
  1034. #ifdef IPV6_V6ONLY
  1035. if ( (sa->sa_family == AF_INET6) &&
  1036. (GNUNET_OK !=
  1037. GNUNET_NETWORK_socket_setsockopt (sock,
  1038. IPPROTO_IPV6,
  1039. IPV6_V6ONLY,
  1040. &on,
  1041. sizeof (on))) )
  1042. GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
  1043. "setsockopt");
  1044. #endif
  1045. #ifndef WINDOWS
  1046. if (AF_UNIX == sa->sa_family)
  1047. GNUNET_NETWORK_unix_precheck ((struct sockaddr_un *) sa);
  1048. #endif
  1049. if (GNUNET_OK !=
  1050. GNUNET_NETWORK_socket_bind (sock,
  1051. (const struct sockaddr *) sa,
  1052. addr_len))
  1053. {
  1054. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1055. _("Unable to bind listening socket for service `%s' to address `%s': %s\n"),
  1056. sl->name,
  1057. GNUNET_a2s (sa,
  1058. addr_len),
  1059. STRERROR (errno));
  1060. GNUNET_break (GNUNET_OK ==
  1061. GNUNET_NETWORK_socket_close (sock));
  1062. GNUNET_free (sa);
  1063. return;
  1064. }
  1065. #ifndef WINDOWS
  1066. if ((AF_UNIX == sa->sa_family)
  1067. #ifdef LINUX
  1068. /* Permission settings are not required when abstract sockets are used */
  1069. && ('\0' != ((const struct sockaddr_un *)sa)->sun_path[0])
  1070. #endif
  1071. )
  1072. {
  1073. match_uid =
  1074. GNUNET_CONFIGURATION_get_value_yesno (cfg,
  1075. sl->name,
  1076. "UNIX_MATCH_UID");
  1077. match_gid =
  1078. GNUNET_CONFIGURATION_get_value_yesno (cfg,
  1079. sl->name,
  1080. "UNIX_MATCH_GID");
  1081. GNUNET_DISK_fix_permissions (((const struct sockaddr_un *)sa)->sun_path,
  1082. match_uid,
  1083. match_gid);
  1084. }
  1085. #endif
  1086. if (GNUNET_OK !=
  1087. GNUNET_NETWORK_socket_listen (sock, 5))
  1088. {
  1089. GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
  1090. "listen");
  1091. GNUNET_break (GNUNET_OK ==
  1092. GNUNET_NETWORK_socket_close (sock));
  1093. GNUNET_free (sa);
  1094. return;
  1095. }
  1096. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  1097. _("ARM now monitors connections to service `%s' at `%s'\n"),
  1098. sl->name,
  1099. GNUNET_a2s (sa,
  1100. addr_len));
  1101. sli = GNUNET_new (struct ServiceListeningInfo);
  1102. sli->service_addr = sa;
  1103. sli->service_addr_len = addr_len;
  1104. sli->listen_socket = sock;
  1105. sli->sl = sl;
  1106. sli->accept_task
  1107. = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
  1108. sock,
  1109. &accept_connection, sli);
  1110. GNUNET_CONTAINER_DLL_insert (sl->listen_head,
  1111. sl->listen_tail,
  1112. sli);
  1113. }
  1114. /**
  1115. * Remove and free an entry in the service list. Listen sockets
  1116. * must have already been cleaned up. Only to be called during shutdown.
  1117. *
  1118. * @param sl entry to free
  1119. */
  1120. static void
  1121. free_service (struct ServiceList *sl)
  1122. {
  1123. GNUNET_assert (GNUNET_YES == in_shutdown);
  1124. GNUNET_CONTAINER_DLL_remove (running_head,
  1125. running_tail,
  1126. sl);
  1127. GNUNET_assert (NULL == sl->listen_head);
  1128. GNUNET_free_non_null (sl->config);
  1129. GNUNET_free_non_null (sl->binary);
  1130. GNUNET_free (sl->name);
  1131. GNUNET_free (sl);
  1132. }
  1133. /**
  1134. * Check START-message.
  1135. *
  1136. * @param cls identification of the client
  1137. * @param amsg the actual message
  1138. * @return #GNUNET_OK to keep the connection open,
  1139. * #GNUNET_SYSERR to close it (signal serious error)
  1140. */
  1141. static int
  1142. check_start (void *cls,
  1143. const struct GNUNET_ARM_Message *amsg)
  1144. {
  1145. (void) cls;
  1146. GNUNET_MQ_check_zero_termination (amsg);
  1147. return GNUNET_OK;
  1148. }
  1149. /**
  1150. * Handle START-message.
  1151. *
  1152. * @param cls identification of the client
  1153. * @param amsg the actual message
  1154. */
  1155. static void
  1156. handle_start (void *cls,
  1157. const struct GNUNET_ARM_Message *amsg)
  1158. {
  1159. struct GNUNET_SERVICE_Client *client = cls;
  1160. const char *servicename;
  1161. struct ServiceList *sl;
  1162. uint64_t request_id;
  1163. request_id = GNUNET_ntohll (amsg->request_id);
  1164. servicename = (const char *) &amsg[1];
  1165. GNUNET_SERVICE_client_continue (client);
  1166. if (GNUNET_YES == in_shutdown)
  1167. {
  1168. signal_result (client,
  1169. servicename,
  1170. request_id,
  1171. GNUNET_ARM_RESULT_IN_SHUTDOWN);
  1172. return;
  1173. }
  1174. sl = find_service (servicename);
  1175. if (NULL == sl)
  1176. {
  1177. signal_result (client,
  1178. servicename,
  1179. request_id,
  1180. GNUNET_ARM_RESULT_IS_NOT_KNOWN);
  1181. return;
  1182. }
  1183. sl->force_start = GNUNET_YES;
  1184. if (NULL != sl->proc)
  1185. {
  1186. signal_result (client,
  1187. servicename,
  1188. request_id,
  1189. GNUNET_ARM_RESULT_IS_STARTED_ALREADY);
  1190. return;
  1191. }
  1192. start_process (sl,
  1193. client,
  1194. request_id);
  1195. }
  1196. /**
  1197. * Start a shutdown sequence.
  1198. *
  1199. * @param cls closure (refers to service)
  1200. */
  1201. static void
  1202. trigger_shutdown (void *cls)
  1203. {
  1204. (void) cls;
  1205. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1206. "Triggering shutdown\n");
  1207. GNUNET_SCHEDULER_shutdown ();
  1208. }
  1209. /**
  1210. * Check STOP-message.
  1211. *
  1212. * @param cls identification of the client
  1213. * @param amsg the actual message
  1214. * @return #GNUNET_OK to keep the connection open,
  1215. * #GNUNET_SYSERR to close it (signal serious error)
  1216. */
  1217. static int
  1218. check_stop (void *cls,
  1219. const struct GNUNET_ARM_Message *amsg)
  1220. {
  1221. (void) cls;
  1222. GNUNET_MQ_check_zero_termination (amsg);
  1223. return GNUNET_OK;
  1224. }
  1225. /**
  1226. * Handle STOP-message.
  1227. *
  1228. * @param cls identification of the client
  1229. * @param amsg the actual message
  1230. */
  1231. static void
  1232. handle_stop (void *cls,
  1233. const struct GNUNET_ARM_Message *amsg)
  1234. {
  1235. struct GNUNET_SERVICE_Client *client = cls;
  1236. struct ServiceList *sl;
  1237. const char *servicename;
  1238. uint64_t request_id;
  1239. request_id = GNUNET_ntohll (amsg->request_id);
  1240. servicename = (const char *) &amsg[1];
  1241. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  1242. _("Preparing to stop `%s'\n"),
  1243. servicename);
  1244. GNUNET_SERVICE_client_continue (client);
  1245. if (0 == strcasecmp (servicename,
  1246. "arm"))
  1247. {
  1248. broadcast_status (servicename,
  1249. GNUNET_ARM_SERVICE_STOPPING,
  1250. NULL);
  1251. signal_result (client,
  1252. servicename,
  1253. request_id,
  1254. GNUNET_ARM_RESULT_STOPPING);
  1255. GNUNET_SERVICE_client_persist (client);
  1256. GNUNET_SCHEDULER_add_now (&trigger_shutdown,
  1257. NULL);
  1258. return;
  1259. }
  1260. sl = find_service (servicename);
  1261. if (NULL == sl)
  1262. {
  1263. signal_result (client,
  1264. servicename,
  1265. request_id,
  1266. GNUNET_ARM_RESULT_IS_NOT_KNOWN);
  1267. return;
  1268. }
  1269. sl->force_start = GNUNET_NO;
  1270. if (GNUNET_YES == in_shutdown)
  1271. {
  1272. /* shutdown in progress */
  1273. signal_result (client,
  1274. servicename,
  1275. request_id,
  1276. GNUNET_ARM_RESULT_IN_SHUTDOWN);
  1277. return;
  1278. }
  1279. if (NULL != sl->killing_client)
  1280. {
  1281. /* killing already in progress */
  1282. signal_result (client,
  1283. servicename,
  1284. request_id,
  1285. GNUNET_ARM_RESULT_IS_STOPPING_ALREADY);
  1286. return;
  1287. }
  1288. if (NULL == sl->proc)
  1289. {
  1290. /* process is down */
  1291. signal_result (client,
  1292. servicename,
  1293. request_id,
  1294. GNUNET_ARM_RESULT_IS_STOPPED_ALREADY);
  1295. return;
  1296. }
  1297. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1298. "Sending kill signal to service `%s', waiting for process to die.\n",
  1299. servicename);
  1300. broadcast_status (servicename,
  1301. GNUNET_ARM_SERVICE_STOPPING,
  1302. NULL);
  1303. /* no signal_start - only when it's STOPPED */
  1304. sl->killed_at = GNUNET_TIME_absolute_get ();
  1305. if (0 != GNUNET_OS_process_kill (sl->proc,
  1306. GNUNET_TERM_SIG))
  1307. GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
  1308. "kill");
  1309. sl->killing_client = client;
  1310. sl->killing_client_request_id = request_id;
  1311. }
  1312. /**
  1313. * Handle LIST-message.
  1314. *
  1315. * @param cls identification of the client
  1316. * @param message the actual message
  1317. */
  1318. static void
  1319. handle_list (void *cls,
  1320. const struct GNUNET_ARM_Message *request)
  1321. {
  1322. struct GNUNET_SERVICE_Client *client = cls;
  1323. struct GNUNET_MQ_Envelope *env;
  1324. struct GNUNET_ARM_ListResultMessage *msg;
  1325. size_t string_list_size;
  1326. struct ServiceList *sl;
  1327. uint16_t count;
  1328. char *pos;
  1329. GNUNET_break (0 == ntohl (request->reserved));
  1330. count = 0;
  1331. string_list_size = 0;
  1332. /* first count the running processes get their name's size */
  1333. for (sl = running_head; NULL != sl; sl = sl->next)
  1334. {
  1335. if (NULL != sl->proc)
  1336. {
  1337. string_list_size += strlen (sl->name);
  1338. string_list_size += strlen (sl->binary);
  1339. string_list_size += 4;
  1340. count++;
  1341. }
  1342. }
  1343. env = GNUNET_MQ_msg_extra (msg,
  1344. string_list_size,
  1345. GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT);
  1346. msg->arm_msg.request_id = request->request_id;
  1347. msg->count = htons (count);
  1348. pos = (char *) &msg[1];
  1349. for (sl = running_head; NULL != sl; sl = sl->next)
  1350. {
  1351. if (NULL != sl->proc)
  1352. {
  1353. size_t s = strlen (sl->name) + strlen (sl->binary) + 4;
  1354. GNUNET_snprintf (pos,
  1355. s,
  1356. "%s (%s)",
  1357. sl->name,
  1358. sl->binary);
  1359. pos += s;
  1360. }
  1361. }
  1362. GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
  1363. env);
  1364. GNUNET_SERVICE_client_continue (client);
  1365. }
  1366. /**
  1367. * Handle TEST-message by sending back TEST.
  1368. *
  1369. * @param cls identification of the client
  1370. * @param message the actual message
  1371. */
  1372. static void
  1373. handle_test (void *cls,
  1374. const struct GNUNET_MessageHeader *message)
  1375. {
  1376. struct GNUNET_SERVICE_Client *client = cls;
  1377. struct GNUNET_MQ_Envelope *env;
  1378. struct GNUNET_MessageHeader *msg;
  1379. (void) message;
  1380. env = GNUNET_MQ_msg (msg,
  1381. GNUNET_MESSAGE_TYPE_ARM_TEST);
  1382. GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
  1383. env);
  1384. GNUNET_SERVICE_client_continue (client);
  1385. }
  1386. /**
  1387. * We are done with everything. Stop remaining
  1388. * tasks, signal handler and the server.
  1389. */
  1390. static void
  1391. do_shutdown ()
  1392. {
  1393. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1394. "Last shutdown phase\n");
  1395. if (NULL != notifier)
  1396. {
  1397. GNUNET_notification_context_destroy (notifier);
  1398. notifier = NULL;
  1399. }
  1400. if (NULL != service)
  1401. {
  1402. GNUNET_SERVICE_shutdown (service);
  1403. service = NULL;
  1404. }
  1405. if (NULL != child_death_task)
  1406. {
  1407. GNUNET_SCHEDULER_cancel (child_death_task);
  1408. child_death_task = NULL;
  1409. }
  1410. }
  1411. /**
  1412. * Count how many services are still active.
  1413. *
  1414. * @param running_head list of services
  1415. * @return number of active services found
  1416. */
  1417. static unsigned int
  1418. list_count (struct ServiceList *running_head)
  1419. {
  1420. struct ServiceList *i;
  1421. unsigned int res;
  1422. for (res = 0, i = running_head; NULL != i; i = i->next, res++)
  1423. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1424. "%s\n",
  1425. i->name);
  1426. return res;
  1427. }
  1428. /**
  1429. * Task run for shutdown.
  1430. *
  1431. * @param cls closure, NULL if we need to self-restart
  1432. */
  1433. static void
  1434. shutdown_task (void *cls)
  1435. {
  1436. struct ServiceList *pos;
  1437. struct ServiceList *nxt;
  1438. struct ServiceListeningInfo *sli;
  1439. (void) cls;
  1440. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1441. "First shutdown phase\n");
  1442. if (NULL != child_restart_task)
  1443. {
  1444. GNUNET_SCHEDULER_cancel (child_restart_task);
  1445. child_restart_task = NULL;
  1446. }
  1447. in_shutdown = GNUNET_YES;
  1448. /* first, stop listening */
  1449. for (pos = running_head; NULL != pos; pos = pos->next)
  1450. {
  1451. while (NULL != (sli = pos->listen_head))
  1452. {
  1453. GNUNET_CONTAINER_DLL_remove (pos->listen_head,
  1454. pos->listen_tail,
  1455. sli);
  1456. if (NULL != sli->accept_task)
  1457. {
  1458. GNUNET_SCHEDULER_cancel (sli->accept_task);
  1459. sli->accept_task = NULL;
  1460. }
  1461. GNUNET_break (GNUNET_OK ==
  1462. GNUNET_NETWORK_socket_close (sli->listen_socket));
  1463. GNUNET_free (sli->service_addr);
  1464. GNUNET_free (sli);
  1465. }
  1466. }
  1467. /* then, shutdown all existing service processes */
  1468. nxt = running_head;
  1469. while (NULL != (pos = nxt))
  1470. {
  1471. nxt = pos->next;
  1472. if (NULL != pos->proc)
  1473. {
  1474. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  1475. "Stopping service `%s'\n",
  1476. pos->name);
  1477. pos->killed_at = GNUNET_TIME_absolute_get ();
  1478. if (0 != GNUNET_OS_process_kill (pos->proc,
  1479. GNUNET_TERM_SIG))
  1480. GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
  1481. "kill");
  1482. }
  1483. else
  1484. {
  1485. free_service (pos);
  1486. }
  1487. }
  1488. /* finally, should all service processes be already gone, terminate for real */
  1489. if (NULL == running_head)
  1490. do_shutdown ();
  1491. else
  1492. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1493. "Delaying shutdown, have %u childs still running\n",
  1494. list_count (running_head));
  1495. }
  1496. /**
  1497. * Task run whenever it is time to restart a child that died.
  1498. *
  1499. * @param cls closure, always NULL
  1500. */
  1501. static void
  1502. delayed_restart_task (void *cls)
  1503. {
  1504. struct ServiceList *sl;
  1505. struct GNUNET_TIME_Relative lowestRestartDelay;
  1506. struct ServiceListeningInfo *sli;
  1507. (void) cls;
  1508. child_restart_task = NULL;
  1509. GNUNET_assert (GNUNET_NO == in_shutdown);
  1510. lowestRestartDelay = GNUNET_TIME_UNIT_FOREVER_REL;
  1511. /* check for services that need to be restarted due to
  1512. * configuration changes or because the last restart failed */
  1513. for (sl = running_head; NULL != sl; sl = sl->next)
  1514. {
  1515. if (NULL != sl->proc)
  1516. continue;
  1517. /* service is currently not running */
  1518. if (0 == GNUNET_TIME_absolute_get_remaining (sl->restart_at).rel_value_us)
  1519. {
  1520. /* restart is now allowed */
  1521. if (sl->force_start)
  1522. {
  1523. /* process should run by default, start immediately */
  1524. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  1525. _("Restarting service `%s'.\n"),
  1526. sl->name);
  1527. start_process (sl,
  1528. NULL,
  1529. 0);
  1530. }
  1531. else
  1532. {
  1533. /* process is run on-demand, ensure it is re-started if there is demand */
  1534. for (sli = sl->listen_head; NULL != sli; sli = sli->next)
  1535. if (NULL == sli->accept_task)
  1536. {
  1537. /* accept was actually paused, so start it again */
  1538. sli->accept_task
  1539. = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
  1540. sli->listen_socket,
  1541. &accept_connection,
  1542. sli);
  1543. }
  1544. }
  1545. }
  1546. else
  1547. {
  1548. /* update calculation for earliest time to reactivate a service */
  1549. lowestRestartDelay =
  1550. GNUNET_TIME_relative_min (lowestRestartDelay,
  1551. GNUNET_TIME_absolute_get_remaining
  1552. (sl->restart_at));
  1553. }
  1554. }
  1555. if (lowestRestartDelay.rel_value_us != GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
  1556. {
  1557. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1558. "Will restart process in %s\n",
  1559. GNUNET_STRINGS_relative_time_to_string (lowestRestartDelay,
  1560. GNUNET_YES));
  1561. child_restart_task =
  1562. GNUNET_SCHEDULER_add_delayed_with_priority (lowestRestartDelay,
  1563. GNUNET_SCHEDULER_PRIORITY_IDLE,
  1564. &delayed_restart_task,
  1565. NULL);
  1566. }
  1567. }
  1568. /**
  1569. * Task triggered whenever we receive a SIGCHLD (child
  1570. * process died).
  1571. *
  1572. * @param cls closure, NULL
  1573. */
  1574. static void
  1575. maint_child_death (void *cls)
  1576. {
  1577. struct ServiceList *pos;
  1578. struct ServiceList *next;
  1579. struct ServiceListeningInfo *sli;
  1580. const char *statstr;
  1581. int statcode;
  1582. int ret;
  1583. char c[16];
  1584. enum GNUNET_OS_ProcessStatusType statusType;
  1585. unsigned long statusCode;
  1586. const struct GNUNET_DISK_FileHandle *pr;
  1587. (void) cls;
  1588. pr = GNUNET_DISK_pipe_handle (sigpipe,
  1589. GNUNET_DISK_PIPE_END_READ);
  1590. child_death_task = NULL;
  1591. /* consume the signal */
  1592. GNUNET_break (0 < GNUNET_DISK_file_read (pr,
  1593. &c,
  1594. sizeof (c)));
  1595. /* check for services that died (WAITPID) */
  1596. next = running_head;
  1597. while (NULL != (pos = next))
  1598. {
  1599. next = pos->next;
  1600. if (NULL == pos->proc)
  1601. {
  1602. if (GNUNET_YES == in_shutdown)
  1603. free_service (pos);
  1604. continue;
  1605. }
  1606. #if HAVE_WAIT4
  1607. if (NULL != wait_file)
  1608. {
  1609. /* need to use 'wait4()' to obtain and log performance data */
  1610. struct rusage ru;
  1611. int status;
  1612. pid_t pid;
  1613. pid = GNUNET_OS_process_get_pid (pos->proc);
  1614. ret = wait4 (pid,
  1615. &status,
  1616. WNOHANG,
  1617. &ru);
  1618. if (ret <= 0)
  1619. continue; /* no process done */
  1620. if (WIFEXITED (status))
  1621. {
  1622. statusType = GNUNET_OS_PROCESS_EXITED;
  1623. statusCode = WEXITSTATUS (status);
  1624. }
  1625. else if (WIFSIGNALED (status))
  1626. {
  1627. statusType = GNUNET_OS_PROCESS_SIGNALED;
  1628. statusCode = WTERMSIG (status);
  1629. }
  1630. else if (WIFSTOPPED (status))
  1631. {
  1632. statusType = GNUNET_OS_PROCESS_SIGNALED;
  1633. statusCode = WSTOPSIG (status);
  1634. }
  1635. #ifdef WIFCONTINUED
  1636. else if (WIFCONTINUED (status))
  1637. {
  1638. statusType = GNUNET_OS_PROCESS_RUNNING;
  1639. statusCode = 0;
  1640. }
  1641. #endif
  1642. else
  1643. {
  1644. statusType = GNUNET_OS_PROCESS_UNKNOWN;
  1645. statusCode = 0;
  1646. }
  1647. if ( (GNUNET_OS_PROCESS_EXITED == statusType) ||
  1648. (GNUNET_OS_PROCESS_SIGNALED == statusType) )
  1649. {
  1650. double utime = ru.ru_utime.tv_sec + (ru.ru_utime.tv_usec / 10e6);
  1651. double stime = ru.ru_stime.tv_sec + (ru.ru_stime.tv_usec / 10e6);
  1652. fprintf (wait_file,
  1653. "%s(%u) %.3f %.3f %llu %llu %llu %llu %llu\n",
  1654. pos->binary,
  1655. (unsigned int) pid,
  1656. utime,
  1657. stime,
  1658. (unsigned long long) ru.ru_maxrss,
  1659. (unsigned long long) ru.ru_inblock,
  1660. (unsigned long long) ru.ru_oublock,
  1661. (unsigned long long) ru.ru_nvcsw,
  1662. (unsigned long long) ru.ru_nivcsw);
  1663. }
  1664. }
  1665. else /* continue with JUST this "if" as "else" (intentionally no brackets!) */
  1666. #endif
  1667. if ( (GNUNET_SYSERR ==
  1668. (ret =
  1669. GNUNET_OS_process_status (pos->proc,
  1670. &statusType,
  1671. &statusCode))) ||
  1672. (ret == GNUNET_NO) ||
  1673. (statusType == GNUNET_OS_PROCESS_STOPPED) ||
  1674. (statusType == GNUNET_OS_PROCESS_UNKNOWN) ||
  1675. (statusType == GNUNET_OS_PROCESS_RUNNING) )
  1676. continue;
  1677. if (statusType == GNUNET_OS_PROCESS_EXITED)
  1678. {
  1679. statstr = _( /* process termination method */ "exit");
  1680. statcode = statusCode;
  1681. }
  1682. else if (statusType == GNUNET_OS_PROCESS_SIGNALED)
  1683. {
  1684. statstr = _( /* process termination method */ "signal");
  1685. statcode = statusCode;
  1686. }
  1687. else
  1688. {
  1689. statstr = _( /* process termination method */ "unknown");
  1690. statcode = 0;
  1691. }
  1692. if (0 != pos->killed_at.abs_value_us)
  1693. {
  1694. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  1695. _("Service `%s' took %s to terminate\n"),
  1696. pos->name,
  1697. GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (pos->killed_at),
  1698. GNUNET_YES));
  1699. }
  1700. GNUNET_OS_process_destroy (pos->proc);
  1701. pos->proc = NULL;
  1702. broadcast_status (pos->name,
  1703. GNUNET_ARM_SERVICE_STOPPED,
  1704. NULL);
  1705. if (NULL != pos->killing_client)
  1706. {
  1707. signal_result (pos->killing_client, pos->name,
  1708. pos->killing_client_request_id,
  1709. GNUNET_ARM_RESULT_STOPPED);
  1710. pos->killing_client = NULL;
  1711. pos->killing_client_request_id = 0;
  1712. }
  1713. if (GNUNET_YES != in_shutdown)
  1714. {
  1715. if ( (statusType == GNUNET_OS_PROCESS_EXITED) &&
  1716. (statcode == 0) )
  1717. {
  1718. /* process terminated normally, allow restart at any time */
  1719. pos->restart_at.abs_value_us = 0;
  1720. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  1721. _("Service `%s' terminated normally, will restart at any time\n"),
  1722. pos->name);
  1723. /* process can still be re-started on-demand, ensure it is re-started if there is demand */
  1724. for (sli = pos->listen_head; NULL != sli; sli = sli->next)
  1725. {
  1726. GNUNET_break (NULL == sli->accept_task);
  1727. sli->accept_task =
  1728. GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
  1729. sli->listen_socket,
  1730. &accept_connection,
  1731. sli);
  1732. }
  1733. }
  1734. else
  1735. {
  1736. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  1737. _("Service `%s' terminated with status %s/%d, will restart in %s\n"),
  1738. pos->name,
  1739. statstr,
  1740. statcode,
  1741. GNUNET_STRINGS_relative_time_to_string (pos->backoff,
  1742. GNUNET_YES));
  1743. {
  1744. /* Reduce backoff based on runtime of the process,
  1745. so that there is a cool-down if a process actually
  1746. runs for a while. */
  1747. struct GNUNET_TIME_Relative runtime;
  1748. unsigned int minutes;
  1749. runtime = GNUNET_TIME_absolute_get_duration (pos->restart_at);
  1750. minutes = runtime.rel_value_us / GNUNET_TIME_UNIT_MINUTES.rel_value_us;
  1751. if (minutes > 31)
  1752. pos->backoff = GNUNET_TIME_UNIT_ZERO;
  1753. else
  1754. pos->backoff.rel_value_us <<= minutes;
  1755. }
  1756. /* schedule restart */
  1757. pos->restart_at = GNUNET_TIME_relative_to_absolute (pos->backoff);
  1758. pos->backoff = GNUNET_TIME_STD_BACKOFF (pos->backoff);
  1759. if (NULL != child_restart_task)
  1760. GNUNET_SCHEDULER_cancel (child_restart_task);
  1761. child_restart_task
  1762. = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE,
  1763. &delayed_restart_task,
  1764. NULL);
  1765. }
  1766. }
  1767. else
  1768. {
  1769. free_service (pos);
  1770. }
  1771. }
  1772. child_death_task = GNUNET_SCHEDULER_add_read_file (
  1773. GNUNET_TIME_UNIT_FOREVER_REL,
  1774. pr,
  1775. &maint_child_death, NULL);
  1776. if ((NULL == running_head) && (GNUNET_YES == in_shutdown))
  1777. do_shutdown ();
  1778. else if (GNUNET_YES == in_shutdown)
  1779. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1780. "Delaying shutdown after child's death, still have %u children\n",
  1781. list_count (running_head));
  1782. }
  1783. /**
  1784. * Signal handler called for SIGCHLD. Triggers the
  1785. * respective handler by writing to the trigger pipe.
  1786. */
  1787. static void
  1788. sighandler_child_death ()
  1789. {
  1790. static char c;
  1791. int old_errno = errno; /* back-up errno */
  1792. GNUNET_break (1 ==
  1793. GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle (sigpipe,
  1794. GNUNET_DISK_PIPE_END_WRITE),
  1795. &c,
  1796. sizeof (c)));
  1797. errno = old_errno; /* restore errno */
  1798. }
  1799. /**
  1800. * Setup our service record for the given section in the configuration file
  1801. * (assuming the section is for a service).
  1802. *
  1803. * @param cls unused
  1804. * @param section a section in the configuration file
  1805. * @return #GNUNET_OK (continue)
  1806. */
  1807. static void
  1808. setup_service (void *cls,
  1809. const char *section)
  1810. {
  1811. struct ServiceList *sl;
  1812. char *binary;
  1813. char *config;
  1814. struct stat sbuf;
  1815. struct sockaddr **addrs;
  1816. socklen_t *addr_lens;
  1817. int ret;
  1818. (void) cls;
  1819. if (0 == strcasecmp (section,
  1820. "arm"))
  1821. return;
  1822. if (GNUNET_OK !=
  1823. GNUNET_CONFIGURATION_get_value_string (cfg,
  1824. section,
  1825. "BINARY",
  1826. &binary))
  1827. {
  1828. /* not a service section */
  1829. return;
  1830. }
  1831. if ((GNUNET_YES ==
  1832. GNUNET_CONFIGURATION_have_value (cfg,
  1833. section,
  1834. "RUN_PER_USER")) &&
  1835. (GNUNET_YES ==
  1836. GNUNET_CONFIGURATION_get_value_yesno (cfg,
  1837. section,
  1838. "RUN_PER_USER")))
  1839. {
  1840. if (GNUNET_NO == start_user)
  1841. {
  1842. GNUNET_free (binary);
  1843. return; /* user service, and we don't deal with those */
  1844. }
  1845. }
  1846. else
  1847. {
  1848. if (GNUNET_NO == start_system)
  1849. {
  1850. GNUNET_free (binary);
  1851. return; /* system service, and we don't deal with those */
  1852. }
  1853. }
  1854. sl = find_service (section);
  1855. if (NULL != sl)
  1856. {
  1857. /* got the same section twice!? */
  1858. GNUNET_break (0);
  1859. GNUNET_free (binary);
  1860. return;
  1861. }
  1862. config = NULL;
  1863. if (( (GNUNET_OK !=
  1864. GNUNET_CONFIGURATION_get_value_filename (cfg,
  1865. section,
  1866. "CONFIG",
  1867. &config)) &&
  1868. (GNUNET_OK !=
  1869. GNUNET_CONFIGURATION_get_value_filename (cfg,
  1870. "PATHS",
  1871. "DEFAULTCONFIG",
  1872. &config)) ) ||
  1873. (0 != STAT (config, &sbuf)))
  1874. {
  1875. if (NULL != config)
  1876. {
  1877. GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
  1878. section, "CONFIG",
  1879. STRERROR (errno));
  1880. GNUNET_free (config);
  1881. config = NULL;
  1882. }
  1883. }
  1884. sl = GNUNET_new (struct ServiceList);
  1885. sl->name = GNUNET_strdup (section);
  1886. sl->binary = binary;
  1887. sl->config = config;
  1888. sl->backoff = GNUNET_TIME_UNIT_MILLISECONDS;
  1889. sl->restart_at = GNUNET_TIME_UNIT_FOREVER_ABS;
  1890. #if WINDOWS
  1891. sl->pipe_control = GNUNET_YES;
  1892. #else
  1893. if (GNUNET_CONFIGURATION_have_value (cfg,
  1894. section,
  1895. "PIPECONTROL"))
  1896. sl->pipe_control = GNUNET_CONFIGURATION_get_value_yesno (cfg,
  1897. section,
  1898. "PIPECONTROL");
  1899. #endif
  1900. GNUNET_CONTAINER_DLL_insert (running_head,
  1901. running_tail,
  1902. sl);
  1903. if (GNUNET_YES ==
  1904. GNUNET_CONFIGURATION_get_value_yesno (cfg,
  1905. section,
  1906. "IMMEDIATE_START"))
  1907. {
  1908. sl->force_start = GNUNET_YES;
  1909. if (GNUNET_YES ==
  1910. GNUNET_CONFIGURATION_get_value_yesno (cfg,
  1911. section,
  1912. "NOARMBIND"))
  1913. return;
  1914. }
  1915. else
  1916. {
  1917. if (GNUNET_YES !=
  1918. GNUNET_CONFIGURATION_get_value_yesno (cfg,
  1919. section,
  1920. "START_ON_DEMAND"))
  1921. return;
  1922. }
  1923. if (0 >= (ret = get_server_addresses (section,
  1924. cfg,
  1925. &addrs,
  1926. &addr_lens)))
  1927. return;
  1928. /* this will free (or capture) addrs[i] */
  1929. for (unsigned int i = 0; i < (unsigned int) ret; i++)
  1930. create_listen_socket (addrs[i],
  1931. addr_lens[i],
  1932. sl);
  1933. GNUNET_free (addrs);
  1934. GNUNET_free (addr_lens);
  1935. }
  1936. /**
  1937. * A client connected, mark as a monitoring client.
  1938. *
  1939. * @param cls closure
  1940. * @param client identification of the client
  1941. * @param mq queue to talk to @a client
  1942. * @return @a client
  1943. */
  1944. static void *
  1945. client_connect_cb (void *cls,
  1946. struct GNUNET_SERVICE_Client *client,
  1947. struct GNUNET_MQ_Handle *mq)
  1948. {
  1949. /* All clients are considered to be of the "monitor" kind
  1950. * (that is, they don't affect ARM shutdown).
  1951. */
  1952. (void) cls;
  1953. (void) mq;
  1954. GNUNET_SERVICE_client_mark_monitor (client);
  1955. return client;
  1956. }
  1957. /**
  1958. * A client disconnected, clean up associated state.
  1959. *
  1960. * @param cls closure
  1961. * @param client identification of the client
  1962. * @param app_ctx must match @a client
  1963. */
  1964. static void
  1965. client_disconnect_cb (void *cls,
  1966. struct GNUNET_SERVICE_Client *client,
  1967. void *app_ctx)
  1968. {
  1969. (void) cls;
  1970. GNUNET_assert (client == app_ctx);
  1971. for (struct ServiceList *sl = running_head; NULL != sl; sl = sl->next)
  1972. if (sl->killing_client == client)
  1973. sl->killing_client = NULL;
  1974. }
  1975. /**
  1976. * Handle MONITOR-message.
  1977. *
  1978. * @param cls identification of the client
  1979. * @param message the actual message
  1980. * @return #GNUNET_OK to keep the connection open,
  1981. * #GNUNET_SYSERR to close it (signal serious error)
  1982. */
  1983. static void
  1984. handle_monitor (void *cls,
  1985. const struct GNUNET_MessageHeader *message)
  1986. {
  1987. struct GNUNET_SERVICE_Client *client = cls;
  1988. (void) message;
  1989. /* FIXME: might want to start by letting monitor know about
  1990. services that are already running */
  1991. /* Removal is handled by the server implementation, internally. */
  1992. GNUNET_notification_context_add (notifier,
  1993. GNUNET_SERVICE_client_get_mq (client));
  1994. broadcast_status ("arm",
  1995. GNUNET_ARM_SERVICE_MONITORING_STARTED,
  1996. client);
  1997. GNUNET_SERVICE_client_continue (client);
  1998. }
  1999. /**
  2000. * Process arm requests.
  2001. *
  2002. * @param cls closure, NULL
  2003. * @param serv the initialized service
  2004. * @param c configuration to use
  2005. */
  2006. static void
  2007. run (void *cls,
  2008. const struct GNUNET_CONFIGURATION_Handle *c,
  2009. struct GNUNET_SERVICE_Handle *serv)
  2010. {
  2011. struct ServiceList *sl;
  2012. (void) cls;
  2013. cfg = c;
  2014. service = serv;
  2015. GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
  2016. NULL);
  2017. child_death_task =
  2018. GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
  2019. GNUNET_DISK_pipe_handle (sigpipe,
  2020. GNUNET_DISK_PIPE_END_READ),
  2021. &maint_child_death,
  2022. NULL);
  2023. #if HAVE_WAIT4
  2024. if (GNUNET_OK ==
  2025. GNUNET_CONFIGURATION_get_value_filename (cfg,
  2026. "ARM",
  2027. "RESOURCE_DIAGNOSTICS",
  2028. &wait_filename))
  2029. {
  2030. wait_file = fopen (wait_filename,
  2031. "w");
  2032. if (NULL == wait_file)
  2033. {
  2034. GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
  2035. "fopen",
  2036. wait_filename);
  2037. }
  2038. }
  2039. #endif
  2040. if (GNUNET_OK !=
  2041. GNUNET_CONFIGURATION_get_value_string (cfg,
  2042. "ARM",
  2043. "GLOBAL_PREFIX",
  2044. &prefix_command))
  2045. prefix_command = GNUNET_strdup ("");
  2046. else
  2047. prefix_command = GNUNET_CONFIGURATION_expand_dollar (cfg,
  2048. prefix_command);
  2049. if (GNUNET_OK !=
  2050. GNUNET_CONFIGURATION_get_value_string (cfg,
  2051. "ARM",
  2052. "GLOBAL_POSTFIX",
  2053. &final_option))
  2054. final_option = GNUNET_strdup ("");
  2055. else
  2056. final_option = GNUNET_CONFIGURATION_expand_dollar (cfg,
  2057. final_option);
  2058. start_user = GNUNET_CONFIGURATION_get_value_yesno (cfg,
  2059. "ARM",
  2060. "START_USER_SERVICES");
  2061. start_system = GNUNET_CONFIGURATION_get_value_yesno (cfg,
  2062. "ARM",
  2063. "START_SYSTEM_SERVICES");
  2064. if ( (GNUNET_NO == start_user) &&
  2065. (GNUNET_NO == start_system) )
  2066. {
  2067. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  2068. "Please configure either START_USER_SERVICES or START_SYSTEM_SERVICES or both.\n");
  2069. GNUNET_SCHEDULER_shutdown ();
  2070. global_ret = 1;
  2071. return;
  2072. }
  2073. GNUNET_CONFIGURATION_iterate_sections (cfg,
  2074. &setup_service,
  2075. NULL);
  2076. /* start default services... */
  2077. for (sl = running_head; NULL != sl; sl = sl->next)
  2078. if (GNUNET_YES == sl->force_start)
  2079. start_process (sl,
  2080. NULL,
  2081. 0);
  2082. notifier = GNUNET_notification_context_create (MAX_NOTIFY_QUEUE);
  2083. }
  2084. /**
  2085. * The main function for the arm service.
  2086. *
  2087. * @param argc number of arguments from the command line
  2088. * @param argv command line arguments
  2089. * @return 0 ok, 1 on error
  2090. */
  2091. int
  2092. main (int argc,
  2093. char *const *argv)
  2094. {
  2095. struct GNUNET_SIGNAL_Context *shc_chld;
  2096. struct GNUNET_MQ_MessageHandler handlers[] = {
  2097. GNUNET_MQ_hd_var_size (start,
  2098. GNUNET_MESSAGE_TYPE_ARM_START,
  2099. struct GNUNET_ARM_Message,
  2100. NULL),
  2101. GNUNET_MQ_hd_var_size (stop,
  2102. GNUNET_MESSAGE_TYPE_ARM_STOP,
  2103. struct GNUNET_ARM_Message,
  2104. NULL),
  2105. GNUNET_MQ_hd_fixed_size (monitor,
  2106. GNUNET_MESSAGE_TYPE_ARM_MONITOR,
  2107. struct GNUNET_MessageHeader,
  2108. NULL),
  2109. GNUNET_MQ_hd_fixed_size (list,
  2110. GNUNET_MESSAGE_TYPE_ARM_LIST,
  2111. struct GNUNET_ARM_Message,
  2112. NULL),
  2113. GNUNET_MQ_hd_fixed_size (test,
  2114. GNUNET_MESSAGE_TYPE_ARM_TEST,
  2115. struct GNUNET_MessageHeader,
  2116. NULL),
  2117. GNUNET_MQ_handler_end ()
  2118. };
  2119. sigpipe = GNUNET_DISK_pipe (GNUNET_NO,
  2120. GNUNET_NO,
  2121. GNUNET_NO,
  2122. GNUNET_NO);
  2123. GNUNET_assert (NULL != sigpipe);
  2124. shc_chld =
  2125. GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD,
  2126. &sighandler_child_death);
  2127. if (0 !=
  2128. GNUNET_SERVICE_run_ (argc,
  2129. argv,
  2130. "arm",
  2131. GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN,
  2132. &run,
  2133. &client_connect_cb,
  2134. &client_disconnect_cb,
  2135. NULL,
  2136. handlers))
  2137. global_ret = 2;
  2138. #if HAVE_WAIT4
  2139. if (NULL != wait_file)
  2140. {
  2141. fclose (wait_file);
  2142. wait_file = NULL;
  2143. }
  2144. if (NULL != wait_filename)
  2145. {
  2146. GNUNET_free (wait_filename);
  2147. wait_filename = NULL;
  2148. }
  2149. #endif
  2150. GNUNET_SIGNAL_handler_uninstall (shc_chld);
  2151. shc_chld = NULL;
  2152. GNUNET_DISK_pipe_close (sigpipe);
  2153. sigpipe = NULL;
  2154. return global_ret;
  2155. }
  2156. #if defined(LINUX) && defined(__GLIBC__)
  2157. #include <malloc.h>
  2158. /**
  2159. * MINIMIZE heap size (way below 128k) since this process doesn't need much.
  2160. */
  2161. void __attribute__ ((constructor)) GNUNET_ARM_memory_init ()
  2162. {
  2163. mallopt (M_TRIM_THRESHOLD, 4 * 1024);
  2164. mallopt (M_TOP_PAD, 1 * 1024);
  2165. malloc_trim (0);
  2166. }
  2167. #endif
  2168. /* end of gnunet-service-arm.c */