gnunet-service-arm_interceptor.c 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191
  1. /*
  2. This file is part of GNUnet.
  3. (C) 2009, 2010 Christian Grothoff (and other contributing authors)
  4. GNUnet is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published
  6. by the Free Software Foundation; either version 3, or (at your
  7. 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. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNUnet; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  15. Boston, MA 02111-1307, USA.
  16. */
  17. /**
  18. * @file arm/gnunet-service-arm_interceptor.c
  19. * @brief listen to incoming connections from clients to services,
  20. * start services for which incoming an incoming connection occur,
  21. * and relay communication between the client and the service for
  22. * that first incoming connection.
  23. *
  24. * @author Safey Abdel Halim
  25. * @author Christian Grothoff
  26. */
  27. #include "platform.h"
  28. #include "gnunet_service_lib.h"
  29. #include "gnunet_configuration_lib.h"
  30. #include "gnunet_constants.h"
  31. #include "gnunet_client_lib.h"
  32. #include "gnunet_container_lib.h"
  33. #include "gnunet-service-arm.h"
  34. #define DEBUG_SERVICE_MANAGER GNUNET_NO
  35. #define BUFFER_SIZE (64 * 1024)
  36. /**
  37. * Problem forwarding from client to service.
  38. */
  39. #define REASON_CLIENT_TO_SERVICE 1
  40. /**
  41. * Problem forwarding from service to client.
  42. */
  43. #define REASON_SERVICE_TO_CLIENT 2
  44. /**
  45. * Problem in both directions.
  46. */
  47. #define REASON_ERROR 3
  48. struct ForwardedConnection;
  49. /**
  50. *
  51. */
  52. struct ServiceListeningInfo
  53. {
  54. /**
  55. * This is a linked list.
  56. */
  57. struct ServiceListeningInfo *next;
  58. /**
  59. * This is a linked list.
  60. */
  61. struct ServiceListeningInfo *prev;
  62. /**
  63. * Name of the service being forwarded.
  64. */
  65. char *serviceName;
  66. /**
  67. *
  68. */
  69. struct sockaddr *service_addr;
  70. /**
  71. *
  72. */
  73. socklen_t service_addr_len;
  74. /**
  75. * Our listening socket.
  76. */
  77. struct GNUNET_NETWORK_Handle *listeningSocket;
  78. /**
  79. *
  80. */
  81. struct ForwardedConnection *fc;
  82. /**
  83. * Task doing the accepting.
  84. */
  85. GNUNET_SCHEDULER_TaskIdentifier acceptTask;
  86. };
  87. /**
  88. * Information of the connection: client-arm-service
  89. */
  90. struct ForwardedConnection
  91. {
  92. /**
  93. *
  94. */
  95. struct GNUNET_NETWORK_Handle *armClientSocket;
  96. /**
  97. *
  98. */
  99. struct GNUNET_NETWORK_Handle *armServiceSocket;
  100. /**
  101. *
  102. */
  103. struct ServiceListeningInfo *listen_info;
  104. /**
  105. *
  106. */
  107. char service_to_client_buffer[BUFFER_SIZE];
  108. /**
  109. *
  110. */
  111. char client_to_service_buffer[BUFFER_SIZE];
  112. /**
  113. *
  114. */
  115. char client_addr[32];
  116. /**
  117. *
  118. */
  119. const char *client_to_service_bufferPos;
  120. /**
  121. *
  122. */
  123. const char *service_to_client_bufferPos;
  124. /**
  125. * Timeout for forwarding.
  126. */
  127. struct GNUNET_TIME_Absolute timeout;
  128. /**
  129. * Current back-off value.
  130. */
  131. struct GNUNET_TIME_Relative back_off;
  132. /**
  133. * Task that tries to initiate forwarding.
  134. */
  135. GNUNET_SCHEDULER_TaskIdentifier start_task;
  136. /**
  137. *
  138. */
  139. GNUNET_SCHEDULER_TaskIdentifier client_to_service_task;
  140. /**
  141. *
  142. */
  143. GNUNET_SCHEDULER_TaskIdentifier service_to_client_task;
  144. /**
  145. *
  146. */
  147. ssize_t client_to_service_bufferDataLength;
  148. /**
  149. *
  150. */
  151. ssize_t service_to_client_bufferDataLength;
  152. /**
  153. *
  154. */
  155. socklen_t client_addr_len;
  156. /**
  157. * Have we ever successfully written data to the service?
  158. */
  159. int first_write_done;
  160. /**
  161. * Reference count (the structure is freed when it reaches zero)
  162. */
  163. int reference_count;
  164. };
  165. /**
  166. * Array with the names of the services started by default.
  167. */
  168. static char **defaultServicesList;
  169. /**
  170. * Size of the defaultServicesList array.
  171. */
  172. static unsigned int numDefaultServices;
  173. /**
  174. *
  175. */
  176. static const struct GNUNET_CONFIGURATION_Handle *cfg;
  177. /**
  178. *
  179. */
  180. static struct ServiceListeningInfo *serviceListeningInfoList_head;
  181. /**
  182. *
  183. */
  184. static struct ServiceListeningInfo *serviceListeningInfoList_tail;
  185. /**
  186. * Put the default services represented by a space separated string into an array of strings
  187. *
  188. * @param services space separated string of default services
  189. */
  190. static void
  191. addDefaultServicesToList (const char *services)
  192. {
  193. unsigned int i;
  194. const char *token;
  195. char *s;
  196. if (strlen (services) == 0)
  197. return;
  198. s = GNUNET_strdup (services);
  199. token = strtok (s, " ");
  200. while (NULL != token)
  201. {
  202. numDefaultServices++;
  203. token = strtok (NULL, " ");
  204. }
  205. GNUNET_free (s);
  206. defaultServicesList = GNUNET_malloc (numDefaultServices * sizeof (char *));
  207. i = 0;
  208. s = GNUNET_strdup (services);
  209. token = strtok (s, " ");
  210. while (NULL != token)
  211. {
  212. defaultServicesList[i++] = GNUNET_strdup (token);
  213. token = strtok (NULL, " ");
  214. }
  215. GNUNET_free (s);
  216. GNUNET_assert (i == numDefaultServices);
  217. }
  218. /**
  219. * Checks whether the serviceName is in the list of default services
  220. *
  221. * @param serviceName string to check its existance in the list
  222. * @return GNUNET_YES if the service is started by default
  223. */
  224. static int
  225. isInDefaultList (const char *serviceName)
  226. {
  227. unsigned int i;
  228. for (i = 0; i < numDefaultServices; i++)
  229. if (strcmp (serviceName, defaultServicesList[i]) == 0)
  230. return GNUNET_YES;
  231. return GNUNET_NO;
  232. }
  233. /**
  234. * Close forwarded connection (partial or full).
  235. *
  236. * @param fc connection to close
  237. * @param reason which direction to close
  238. */
  239. static void
  240. closeClientAndServiceSockets (struct ForwardedConnection *fc, int reason)
  241. {
  242. if (0 != (REASON_SERVICE_TO_CLIENT & reason))
  243. {
  244. #if DEBUG_SERVICE_MANAGER
  245. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  246. "Stopping forwarding from service to client\n");
  247. #endif
  248. if (fc->armClientSocket != NULL)
  249. GNUNET_NETWORK_socket_shutdown (fc->armClientSocket, SHUT_WR);
  250. if (fc->armServiceSocket != NULL)
  251. GNUNET_NETWORK_socket_shutdown (fc->armServiceSocket, SHUT_RD);
  252. }
  253. if (0 != (REASON_CLIENT_TO_SERVICE & reason))
  254. {
  255. #if DEBUG_SERVICE_MANAGER
  256. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  257. "Stopping forwarding from client to service\n");
  258. #endif
  259. if (fc->armClientSocket != NULL)
  260. GNUNET_NETWORK_socket_shutdown (fc->armClientSocket, SHUT_RD);
  261. if (fc->armServiceSocket != NULL)
  262. GNUNET_NETWORK_socket_shutdown (fc->armServiceSocket, SHUT_WR);
  263. }
  264. #if DEBUG_SERVICE_MANAGER
  265. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  266. "Closing forwarding connection (done with both directions)\n");
  267. #endif
  268. fc->reference_count -= 1;
  269. if (fc->reference_count <= 0)
  270. {
  271. if ((NULL != fc->armClientSocket) &&
  272. (GNUNET_SYSERR == GNUNET_NETWORK_socket_close (fc->armClientSocket)))
  273. {
  274. GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "close");
  275. fc->armClientSocket = NULL;
  276. }
  277. if ((NULL != fc->armServiceSocket) &&
  278. (GNUNET_SYSERR == GNUNET_NETWORK_socket_close (fc->armServiceSocket)))
  279. {
  280. GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "close");
  281. fc->armServiceSocket = NULL;
  282. }
  283. if (fc->listen_info != NULL)
  284. {
  285. if (fc->listen_info->serviceName != NULL)
  286. {
  287. GNUNET_free (fc->listen_info->serviceName);
  288. fc->listen_info->serviceName = NULL;
  289. }
  290. if (fc->listen_info->service_addr != NULL)
  291. {
  292. GNUNET_free (fc->listen_info->service_addr);
  293. fc->listen_info->service_addr = NULL;
  294. }
  295. GNUNET_free (fc->listen_info);
  296. fc->listen_info = NULL;
  297. }
  298. GNUNET_free (fc);
  299. }
  300. }
  301. /**
  302. * Read data from the client and then forward it to the service.
  303. *
  304. * @param cls callback data, struct ForwardedConnection for the communication between client and service
  305. * @param tc context
  306. */
  307. static void
  308. receiveFromClient (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
  309. /**
  310. * Receive service messages sent by the service and forward it to client
  311. *
  312. * @param cls callback data, struct ForwardedConnection for the communication between client and service
  313. * @param tc scheduler context
  314. */
  315. static void
  316. receiveFromService (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
  317. /**
  318. *
  319. */
  320. static void
  321. start_forwarding (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
  322. /**
  323. * Forward messages sent from service to client
  324. *
  325. * @param cls callback data, struct ForwardedConnection for the communication between client and service
  326. * @param tc context
  327. */
  328. static void
  329. forwardToClient (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  330. {
  331. struct ForwardedConnection *fc = cls;
  332. ssize_t numberOfBytesSent;
  333. fc->service_to_client_task = GNUNET_SCHEDULER_NO_TASK;
  334. if (GNUNET_YES !=
  335. GNUNET_NETWORK_fdset_isset (tc->write_ready, fc->armClientSocket))
  336. {
  337. fc->service_to_client_task =
  338. GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
  339. fc->armClientSocket, &forwardToClient,
  340. fc);
  341. return;
  342. }
  343. /* Forwarding service response to client */
  344. numberOfBytesSent =
  345. GNUNET_NETWORK_socket_send (fc->armClientSocket,
  346. fc->service_to_client_bufferPos,
  347. fc->service_to_client_bufferDataLength);
  348. if (numberOfBytesSent <= 0)
  349. {
  350. if ((errno != EPIPE) && (errno != ECONNRESET))
  351. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  352. "Failed to forward %u bytes of data to client: %s\n",
  353. fc->service_to_client_bufferDataLength, STRERROR (errno));
  354. closeClientAndServiceSockets (fc, REASON_SERVICE_TO_CLIENT);
  355. return;
  356. }
  357. #if DEBUG_SERVICE_MANAGER
  358. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Forwarded %d bytes to client\n",
  359. numberOfBytesSent);
  360. #endif
  361. if (numberOfBytesSent < fc->service_to_client_bufferDataLength)
  362. {
  363. fc->service_to_client_bufferPos += numberOfBytesSent;
  364. fc->service_to_client_bufferDataLength -= numberOfBytesSent;
  365. fc->service_to_client_task =
  366. GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
  367. fc->armClientSocket, &forwardToClient,
  368. fc);
  369. return;
  370. }
  371. fc->service_to_client_task =
  372. GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
  373. fc->armServiceSocket, &receiveFromService,
  374. fc);
  375. }
  376. /**
  377. * Receive service messages sent by the service and forward it to client
  378. *
  379. * @param cls callback data, struct ForwardedConnection for the communication between client and service
  380. * @param tc scheduler context
  381. */
  382. static void
  383. receiveFromService (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  384. {
  385. struct ForwardedConnection *fc = cls;
  386. struct GNUNET_TIME_Relative rem;
  387. fc->service_to_client_task = GNUNET_SCHEDULER_NO_TASK;
  388. if ((0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) &&
  389. (fc->first_write_done != GNUNET_YES))
  390. {
  391. closeClientAndServiceSockets (fc, REASON_ERROR);
  392. return;
  393. }
  394. if (GNUNET_YES !=
  395. GNUNET_NETWORK_fdset_isset (tc->read_ready, fc->armServiceSocket))
  396. {
  397. fc->service_to_client_task =
  398. GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
  399. fc->armServiceSocket,
  400. &receiveFromService, fc);
  401. return;
  402. }
  403. fc->service_to_client_bufferPos = fc->service_to_client_buffer;
  404. fc->service_to_client_bufferDataLength =
  405. GNUNET_NETWORK_socket_recv (fc->armServiceSocket,
  406. fc->service_to_client_buffer, BUFFER_SIZE);
  407. if (fc->service_to_client_bufferDataLength <= 0)
  408. {
  409. #if DEBUG_SERVICE_MANAGER
  410. if (fc->service_to_client_bufferDataLength == 0)
  411. {
  412. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  413. "Service `%s' stopped sending data.\n",
  414. fc->listen_info->serviceName);
  415. }
  416. #endif
  417. if (fc->first_write_done != GNUNET_YES)
  418. {
  419. fc->service_to_client_bufferDataLength = 0;
  420. GNUNET_break (GNUNET_OK ==
  421. GNUNET_NETWORK_socket_close (fc->armServiceSocket));
  422. fc->armServiceSocket = NULL;
  423. if ((fc->client_to_service_bufferDataLength > 0) &&
  424. (fc->client_to_service_task != GNUNET_SCHEDULER_NO_TASK))
  425. {
  426. GNUNET_SCHEDULER_cancel (fc->client_to_service_task);
  427. fc->client_to_service_task = GNUNET_SCHEDULER_NO_TASK;
  428. }
  429. fc->back_off = GNUNET_TIME_relative_multiply (fc->back_off, 2);
  430. #if DEBUG_SERVICE_MANAGER
  431. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  432. "Failed to connected to service `%s' at `%s', will try again in %llu ms\n",
  433. fc->listen_info->serviceName,
  434. GNUNET_a2s (fc->listen_info->service_addr,
  435. fc->listen_info->service_addr_len),
  436. (unsigned long long) GNUNET_TIME_relative_min (fc->back_off,
  437. rem).rel_value);
  438. #endif
  439. rem = GNUNET_TIME_absolute_get_remaining (fc->timeout);
  440. GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == fc->start_task);
  441. fc->start_task =
  442. GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_min
  443. (fc->back_off, rem), &start_forwarding,
  444. fc);
  445. }
  446. else
  447. {
  448. #if DEBUG_SERVICE_MANAGER
  449. if (fc->service_to_client_bufferDataLength != 0)
  450. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  451. "Error receiving from service: %s\n", STRERROR (errno));
  452. #endif
  453. closeClientAndServiceSockets (fc, REASON_SERVICE_TO_CLIENT);
  454. }
  455. return;
  456. }
  457. fc->first_write_done = GNUNET_YES;
  458. #if DEBUG_SERVICE_MANAGER
  459. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %d bytes for client\n",
  460. fc->service_to_client_bufferDataLength);
  461. #endif
  462. fc->service_to_client_task =
  463. GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
  464. fc->armClientSocket, &forwardToClient,
  465. fc);
  466. }
  467. /**
  468. * Forward client message to service
  469. *
  470. * @param cls callback data, struct ForwardedConnection for the communication between client and service
  471. * @param tc scheduler context
  472. */
  473. static void
  474. forwardToService (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  475. {
  476. struct ForwardedConnection *fc = cls;
  477. ssize_t numberOfBytesSent;
  478. struct GNUNET_TIME_Relative rem;
  479. fc->client_to_service_task = GNUNET_SCHEDULER_NO_TASK;
  480. if ((0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) &&
  481. (fc->first_write_done != GNUNET_YES))
  482. {
  483. closeClientAndServiceSockets (fc, REASON_ERROR);
  484. return;
  485. }
  486. if (GNUNET_YES !=
  487. GNUNET_NETWORK_fdset_isset (tc->write_ready, fc->armServiceSocket))
  488. {
  489. fc->client_to_service_task =
  490. GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
  491. fc->armServiceSocket, &forwardToService,
  492. fc);
  493. return;
  494. }
  495. numberOfBytesSent =
  496. GNUNET_NETWORK_socket_send (fc->armServiceSocket,
  497. fc->client_to_service_bufferPos,
  498. fc->client_to_service_bufferDataLength);
  499. if (numberOfBytesSent <= 0)
  500. {
  501. if (GNUNET_YES != fc->first_write_done)
  502. {
  503. GNUNET_break (GNUNET_OK ==
  504. GNUNET_NETWORK_socket_close (fc->armServiceSocket));
  505. fc->armServiceSocket = NULL;
  506. if ((fc->service_to_client_bufferDataLength == 0) &&
  507. (fc->service_to_client_task != GNUNET_SCHEDULER_NO_TASK))
  508. {
  509. GNUNET_SCHEDULER_cancel (fc->service_to_client_task);
  510. fc->service_to_client_task = GNUNET_SCHEDULER_NO_TASK;
  511. }
  512. fc->back_off = GNUNET_TIME_relative_multiply (fc->back_off, 2);
  513. #if DEBUG_SERVICE_MANAGER
  514. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  515. "Failed to connect to service `%s' at `%s', will try again in %llu ms\n",
  516. fc->listen_info->serviceName,
  517. GNUNET_a2s (fc->listen_info->service_addr,
  518. fc->listen_info->service_addr_len),
  519. (unsigned long long) GNUNET_TIME_relative_min (fc->back_off,
  520. rem).rel_value);
  521. #endif
  522. rem = GNUNET_TIME_absolute_get_remaining (fc->timeout);
  523. GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == fc->start_task);
  524. fc->start_task =
  525. GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_min
  526. (fc->back_off, rem), &start_forwarding,
  527. fc);
  528. }
  529. else
  530. {
  531. if ((errno != EPIPE) && (errno != ECONNRESET))
  532. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  533. "Failed to forward data to service: %s\n",
  534. STRERROR (errno));
  535. closeClientAndServiceSockets (fc, REASON_CLIENT_TO_SERVICE);
  536. }
  537. return;
  538. }
  539. #if DEBUG_SERVICE_MANAGER
  540. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Forwarded %d bytes to service\n",
  541. numberOfBytesSent);
  542. #endif
  543. fc->first_write_done = GNUNET_YES;
  544. if (numberOfBytesSent < fc->client_to_service_bufferDataLength)
  545. {
  546. fc->client_to_service_bufferPos += numberOfBytesSent;
  547. fc->client_to_service_bufferDataLength -= numberOfBytesSent;
  548. fc->client_to_service_task =
  549. GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
  550. fc->armServiceSocket, &forwardToService,
  551. fc);
  552. return;
  553. }
  554. fc->client_to_service_task =
  555. GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
  556. fc->armClientSocket, &receiveFromClient,
  557. fc);
  558. }
  559. /**
  560. * Read data from the client and then forward it to the service.
  561. *
  562. * @param cls callback data, struct ForwardedConnection for the communication between client and service
  563. * @param tc context
  564. */
  565. static void
  566. receiveFromClient (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  567. {
  568. struct ForwardedConnection *fc = cls;
  569. fc->client_to_service_task = GNUNET_SCHEDULER_NO_TASK;
  570. if (GNUNET_YES !=
  571. GNUNET_NETWORK_fdset_isset (tc->read_ready, fc->armClientSocket))
  572. {
  573. fc->client_to_service_task =
  574. GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
  575. fc->armClientSocket, &receiveFromClient,
  576. fc);
  577. return;
  578. }
  579. fc->client_to_service_bufferPos = fc->client_to_service_buffer;
  580. fc->client_to_service_bufferDataLength =
  581. GNUNET_NETWORK_socket_recv (fc->armClientSocket,
  582. fc->client_to_service_buffer, BUFFER_SIZE);
  583. if (fc->client_to_service_bufferDataLength <= 0)
  584. {
  585. if (fc->client_to_service_bufferDataLength == 0)
  586. {
  587. #if DEBUG_SERVICE_MANAGER
  588. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  589. "Client closed connection with service `%s'\n",
  590. fc->listen_info->serviceName);
  591. #endif
  592. }
  593. else
  594. {
  595. #if DEBUG_SERVICE_MANAGER
  596. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error receiving from client: %s\n",
  597. STRERROR (errno));
  598. #endif
  599. }
  600. closeClientAndServiceSockets (fc, REASON_CLIENT_TO_SERVICE);
  601. return;
  602. }
  603. #if DEBUG_SERVICE_MANAGER
  604. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %d bytes for service\n",
  605. fc->client_to_service_bufferDataLength);
  606. #endif
  607. if (fc->armServiceSocket != NULL)
  608. fc->client_to_service_task =
  609. GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
  610. fc->armServiceSocket, &forwardToService,
  611. fc);
  612. else
  613. /* We have not added any task with fc as a closure, so we're
  614. * dropping our reference to fc
  615. */
  616. fc->reference_count -= 1;
  617. }
  618. static void
  619. fc_acceptConnection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  620. {
  621. struct ServiceListeningInfo *sli = cls;
  622. struct ForwardedConnection *fc = sli->fc;
  623. if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY))
  624. {
  625. GNUNET_assert (GNUNET_OK ==
  626. GNUNET_NETWORK_socket_close (sli->listeningSocket));
  627. closeClientAndServiceSockets (fc, REASON_ERROR);
  628. GNUNET_free (sli);
  629. return;
  630. }
  631. #if DEBUG_SERVICE_MANAGER
  632. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  633. "Connected to service, now starting forwarding\n");
  634. #endif
  635. fc->armServiceSocket = sli->listeningSocket;
  636. GNUNET_free (fc->listen_info->service_addr);
  637. fc->listen_info->service_addr = sli->service_addr;
  638. fc->listen_info->service_addr_len = sli->service_addr_len;
  639. /* Drop fc reference count prematurely, it'll be incremented
  640. * once or twice in the following conditional branches.
  641. * This is, apparently, the place where reference count increases
  642. * past 1.
  643. */
  644. fc->reference_count -= 1;
  645. if (fc->client_to_service_task == GNUNET_SCHEDULER_NO_TASK)
  646. {
  647. if (fc->client_to_service_bufferDataLength == 0)
  648. fc->client_to_service_task =
  649. GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
  650. fc->armClientSocket,
  651. &receiveFromClient, fc);
  652. else
  653. fc->client_to_service_task =
  654. GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
  655. fc->armServiceSocket,
  656. &forwardToService, fc);
  657. fc->reference_count += 1;
  658. }
  659. if (fc->service_to_client_task == GNUNET_SCHEDULER_NO_TASK)
  660. {
  661. if (fc->service_to_client_bufferDataLength == 0)
  662. fc->service_to_client_task =
  663. GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
  664. fc->armServiceSocket,
  665. &receiveFromService, fc);
  666. else
  667. fc->service_to_client_task =
  668. GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
  669. fc->armClientSocket, &forwardToClient,
  670. fc);
  671. fc->reference_count += 1;
  672. }
  673. GNUNET_free (sli);
  674. }
  675. static struct ServiceListeningInfo *
  676. service_try_to_connect (const struct sockaddr *addr, int pf, socklen_t addrlen,
  677. struct ForwardedConnection *fc)
  678. {
  679. struct GNUNET_NETWORK_Handle *sock;
  680. struct ServiceListeningInfo *serviceListeningInfo;
  681. sock = GNUNET_NETWORK_socket_create (pf, SOCK_STREAM, 0);
  682. if (sock == NULL)
  683. {
  684. GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "socket");
  685. return NULL;
  686. }
  687. if ((GNUNET_SYSERR == GNUNET_NETWORK_socket_connect (sock, addr, addrlen)) &&
  688. (errno != EINPROGRESS))
  689. {
  690. GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "connect");
  691. GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
  692. return NULL;
  693. }
  694. serviceListeningInfo = GNUNET_malloc (sizeof (struct ServiceListeningInfo));
  695. serviceListeningInfo->serviceName = NULL;
  696. serviceListeningInfo->service_addr = GNUNET_malloc (addrlen);
  697. memcpy (serviceListeningInfo->service_addr, addr, addrlen);
  698. serviceListeningInfo->service_addr_len = addrlen;
  699. serviceListeningInfo->listeningSocket = sock;
  700. serviceListeningInfo->fc = fc;
  701. serviceListeningInfo->acceptTask =
  702. GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
  703. serviceListeningInfo->listeningSocket,
  704. &fc_acceptConnection,
  705. serviceListeningInfo);
  706. return serviceListeningInfo;
  707. }
  708. /**
  709. *
  710. */
  711. static void
  712. start_forwarding (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  713. {
  714. struct ForwardedConnection *fc = cls;
  715. struct ServiceListeningInfo *sc;
  716. struct sockaddr_in target_ipv4;
  717. struct sockaddr_in6 target_ipv6;
  718. const struct sockaddr_in *v4;
  719. const struct sockaddr_in6 *v6;
  720. char listen_address[INET6_ADDRSTRLEN];
  721. fc->start_task = GNUNET_SCHEDULER_NO_TASK;
  722. if ((NULL != tc) && (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)))
  723. {
  724. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  725. _("Unable to forward to service `%s': shutdown\n"),
  726. fc->listen_info->serviceName);
  727. closeClientAndServiceSockets (fc, REASON_ERROR);
  728. return;
  729. }
  730. if (0 == GNUNET_TIME_absolute_get_remaining (fc->timeout).rel_value)
  731. {
  732. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  733. _
  734. ("Unable to forward to service `%s': timeout before connect\n"),
  735. fc->listen_info->serviceName);
  736. closeClientAndServiceSockets (fc, REASON_ERROR);
  737. return;
  738. }
  739. switch (fc->listen_info->service_addr->sa_family)
  740. {
  741. case AF_UNSPEC:
  742. GNUNET_break (0);
  743. closeClientAndServiceSockets (fc, REASON_ERROR);
  744. return;
  745. case AF_INET:
  746. v4 = (const struct sockaddr_in *) fc->listen_info->service_addr;
  747. inet_ntop (fc->listen_info->service_addr->sa_family,
  748. (const void *) &v4->sin_addr, listen_address, INET_ADDRSTRLEN);
  749. if (0 == strncmp (listen_address, "0.0.0.0", 7))
  750. {
  751. /* connect to [::1] and 127.0.0.1 instead of [::] and 0.0.0.0 */
  752. memset (&target_ipv4, 0, sizeof (target_ipv4));
  753. GNUNET_assert (1 ==
  754. inet_pton (AF_INET, "127.0.0.1", &target_ipv4.sin_addr));
  755. target_ipv4.sin_family = AF_INET;
  756. target_ipv4.sin_port = v4->sin_port;
  757. v4 = &target_ipv4;
  758. }
  759. sc = service_try_to_connect ((const struct sockaddr *) v4, PF_INET,
  760. sizeof (struct sockaddr_in), fc);
  761. break;
  762. case AF_INET6:
  763. v6 = (struct sockaddr_in6 *) fc->listen_info->service_addr;
  764. inet_ntop (fc->listen_info->service_addr->sa_family,
  765. (const void *) &v6->sin6_addr, listen_address, INET6_ADDRSTRLEN);
  766. if ((strncmp (listen_address, "[::]:", 5) == 0) ||
  767. (strncmp (listen_address, "::", 2) == 0))
  768. {
  769. memset (&target_ipv6, 0, sizeof (target_ipv6));
  770. target_ipv6.sin6_addr = in6addr_loopback;
  771. target_ipv6.sin6_family = AF_INET6;
  772. target_ipv6.sin6_port = v6->sin6_port;
  773. v6 = &target_ipv6;
  774. }
  775. sc = service_try_to_connect ((const struct sockaddr *) v6, PF_INET6,
  776. sizeof (struct sockaddr_in6), fc);
  777. break;
  778. case AF_UNIX:
  779. sc = service_try_to_connect (fc->listen_info->service_addr, PF_UNIX,
  780. fc->listen_info->service_addr_len, fc);
  781. break;
  782. default:
  783. GNUNET_break (0);
  784. closeClientAndServiceSockets (fc, REASON_ERROR);
  785. return;
  786. }
  787. if (NULL == sc)
  788. {
  789. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  790. _("Unable to start service `%s': %s\n"),
  791. fc->listen_info->serviceName, STRERROR (errno));
  792. closeClientAndServiceSockets (fc, REASON_ERROR);
  793. return;
  794. }
  795. }
  796. /**
  797. *
  798. */
  799. int
  800. stop_listening (const char *serviceName)
  801. {
  802. struct ServiceListeningInfo *pos;
  803. struct ServiceListeningInfo *next;
  804. int ret;
  805. ret = GNUNET_NO;
  806. next = serviceListeningInfoList_head;
  807. while (NULL != (pos = next))
  808. {
  809. next = pos->next;
  810. if ((serviceName != NULL) && (strcmp (pos->serviceName, serviceName) != 0))
  811. continue;
  812. if (pos->acceptTask != GNUNET_SCHEDULER_NO_TASK)
  813. GNUNET_SCHEDULER_cancel (pos->acceptTask);
  814. GNUNET_break (GNUNET_OK ==
  815. GNUNET_NETWORK_socket_close (pos->listeningSocket));
  816. GNUNET_CONTAINER_DLL_remove (serviceListeningInfoList_head,
  817. serviceListeningInfoList_tail, pos);
  818. GNUNET_free (pos->serviceName);
  819. GNUNET_free (pos->service_addr);
  820. GNUNET_free (pos);
  821. ret = GNUNET_OK;
  822. }
  823. return ret;
  824. }
  825. /**
  826. * First connection has come to the listening socket associated with the service,
  827. * create the service in order to relay the incoming connection to it
  828. *
  829. * @param cls callback data, struct ServiceListeningInfo describing a listen socket
  830. * @param tc context
  831. */
  832. static void
  833. acceptConnection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
  834. static void
  835. accept_and_forward (struct ServiceListeningInfo *serviceListeningInfo)
  836. {
  837. struct ForwardedConnection *fc;
  838. fc = GNUNET_malloc (sizeof (struct ForwardedConnection));
  839. fc->reference_count = 1;
  840. fc->listen_info = serviceListeningInfo;
  841. fc->service_to_client_bufferPos = fc->service_to_client_buffer;
  842. fc->client_to_service_bufferPos = fc->client_to_service_buffer;
  843. fc->client_addr_len = sizeof (fc->client_addr);
  844. fc->armClientSocket =
  845. GNUNET_NETWORK_socket_accept (serviceListeningInfo->listeningSocket,
  846. (struct sockaddr *) fc->client_addr,
  847. &fc->client_addr_len);
  848. if (NULL == fc->armClientSocket)
  849. {
  850. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  851. _("Unable to accept connection for service `%s': %s\n"),
  852. serviceListeningInfo->serviceName, STRERROR (errno));
  853. GNUNET_free (fc);
  854. GNUNET_CONTAINER_DLL_insert (serviceListeningInfoList_head,
  855. serviceListeningInfoList_tail,
  856. serviceListeningInfo);
  857. serviceListeningInfo->acceptTask =
  858. GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
  859. serviceListeningInfo->listeningSocket,
  860. &acceptConnection, serviceListeningInfo);
  861. return;
  862. }
  863. GNUNET_break (GNUNET_OK ==
  864. GNUNET_NETWORK_socket_close
  865. (serviceListeningInfo->listeningSocket));
  866. start_service (NULL, serviceListeningInfo->serviceName, NULL);
  867. GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Service `%s' started\n"),
  868. fc->listen_info->serviceName);
  869. fc->timeout =
  870. GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_SERVICE_TIMEOUT);
  871. fc->back_off = GNUNET_TIME_UNIT_MILLISECONDS;
  872. fc->client_to_service_task =
  873. GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
  874. fc->armClientSocket, &receiveFromClient,
  875. fc);
  876. GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == fc->start_task);
  877. /* We're creating another chain of tasks for this fc that
  878. * will have its own reference to it.
  879. */
  880. fc->reference_count += 1;
  881. fc->start_task = GNUNET_SCHEDULER_add_now (&start_forwarding, fc);
  882. }
  883. /**
  884. * First connection has come to the listening socket associated with the service,
  885. * create the service in order to relay the incoming connection to it
  886. *
  887. * @param cls callback data, struct ServiceListeningInfo describing a listen socket
  888. * @param tc context
  889. */
  890. static void
  891. acceptConnection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  892. {
  893. struct ServiceListeningInfo *sli = cls;
  894. struct ServiceListeningInfo *pos;
  895. struct ServiceListeningInfo *next;
  896. int *lsocks;
  897. unsigned int ls;
  898. int use_lsocks;
  899. sli->acceptTask = GNUNET_SCHEDULER_NO_TASK;
  900. if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
  901. return;
  902. GNUNET_CONTAINER_DLL_remove (serviceListeningInfoList_head,
  903. serviceListeningInfoList_tail, sli);
  904. #ifndef MINGW
  905. use_lsocks = GNUNET_NO;
  906. if (GNUNET_YES ==
  907. GNUNET_CONFIGURATION_have_value (cfg, sli->serviceName,
  908. "DISABLE_SOCKET_FORWARDING"))
  909. use_lsocks =
  910. GNUNET_CONFIGURATION_get_value_yesno (cfg, sli->serviceName,
  911. "DISABLE_SOCKET_FORWARDING");
  912. #else
  913. use_lsocks = GNUNET_YES;
  914. #endif
  915. if (GNUNET_NO != use_lsocks)
  916. {
  917. accept_and_forward (sli);
  918. return;
  919. }
  920. lsocks = NULL;
  921. ls = 0;
  922. next = serviceListeningInfoList_head;
  923. while (NULL != (pos = next))
  924. {
  925. next = pos->next;
  926. if (0 == strcmp (pos->serviceName, sli->serviceName))
  927. {
  928. GNUNET_array_append (lsocks, ls,
  929. GNUNET_NETWORK_get_fd (pos->listeningSocket));
  930. GNUNET_free (pos->listeningSocket); /* deliberately no closing! */
  931. GNUNET_free (pos->service_addr);
  932. GNUNET_free (pos->serviceName);
  933. GNUNET_SCHEDULER_cancel (pos->acceptTask);
  934. GNUNET_CONTAINER_DLL_remove (serviceListeningInfoList_head,
  935. serviceListeningInfoList_tail, pos);
  936. GNUNET_free (pos);
  937. }
  938. }
  939. GNUNET_array_append (lsocks, ls,
  940. GNUNET_NETWORK_get_fd (sli->listeningSocket));
  941. GNUNET_free (sli->listeningSocket); /* deliberately no closing! */
  942. GNUNET_free (sli->service_addr);
  943. GNUNET_array_append (lsocks, ls, -1);
  944. start_service (NULL, sli->serviceName, lsocks);
  945. ls = 0;
  946. while (lsocks[ls] != -1)
  947. GNUNET_break (0 == close (lsocks[ls++]));
  948. GNUNET_array_grow (lsocks, ls, 0);
  949. GNUNET_free (sli->serviceName);
  950. GNUNET_free (sli);
  951. }
  952. /**
  953. * Creating a listening socket for each of the service's addresses and
  954. * wait for the first incoming connection to it
  955. *
  956. * @param sa address associated with the service
  957. * @param addr_len length of sa
  958. * @param serviceName the name of the service in question
  959. */
  960. static void
  961. createListeningSocket (struct sockaddr *sa, socklen_t addr_len,
  962. const char *serviceName)
  963. {
  964. const static int on = 1;
  965. struct GNUNET_NETWORK_Handle *sock;
  966. struct ServiceListeningInfo *serviceListeningInfo;
  967. switch (sa->sa_family)
  968. {
  969. case AF_INET:
  970. sock = GNUNET_NETWORK_socket_create (PF_INET, SOCK_STREAM, 0);
  971. break;
  972. case AF_INET6:
  973. sock = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
  974. break;
  975. case AF_UNIX:
  976. if (strcmp (GNUNET_a2s (sa, addr_len), "@") == 0) /* Do not bind to blank UNIX path! */
  977. return;
  978. sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0);
  979. break;
  980. default:
  981. GNUNET_break (0);
  982. sock = NULL;
  983. errno = EAFNOSUPPORT;
  984. break;
  985. }
  986. if (NULL == sock)
  987. {
  988. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  989. _("Unable to create socket for service `%s': %s\n"),
  990. serviceName, STRERROR (errno));
  991. GNUNET_free (sa);
  992. return;
  993. }
  994. if (GNUNET_NETWORK_socket_setsockopt
  995. (sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != GNUNET_OK)
  996. GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
  997. "setsockopt");
  998. #ifdef IPV6_V6ONLY
  999. if ((sa->sa_family == AF_INET6) &&
  1000. (GNUNET_NETWORK_socket_setsockopt
  1001. (sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)) != GNUNET_OK))
  1002. GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
  1003. "setsockopt");
  1004. #endif
  1005. if (GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) sa, addr_len)
  1006. != GNUNET_OK)
  1007. {
  1008. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  1009. _
  1010. ("Unable to bind listening socket for service `%s' to address `%s': %s\n"),
  1011. serviceName, GNUNET_a2s (sa, addr_len), STRERROR (errno));
  1012. GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
  1013. GNUNET_free (sa);
  1014. return;
  1015. }
  1016. if (GNUNET_NETWORK_socket_listen (sock, 5) != GNUNET_OK)
  1017. {
  1018. GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "listen");
  1019. GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
  1020. GNUNET_free (sa);
  1021. return;
  1022. }
  1023. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  1024. _("ARM now monitors connections to service `%s' at `%s'\n"),
  1025. serviceName, GNUNET_a2s (sa, addr_len));
  1026. serviceListeningInfo = GNUNET_malloc (sizeof (struct ServiceListeningInfo));
  1027. serviceListeningInfo->serviceName = GNUNET_strdup (serviceName);
  1028. serviceListeningInfo->service_addr = sa;
  1029. serviceListeningInfo->service_addr_len = addr_len;
  1030. serviceListeningInfo->listeningSocket = sock;
  1031. serviceListeningInfo->acceptTask =
  1032. GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, sock,
  1033. &acceptConnection, serviceListeningInfo);
  1034. GNUNET_CONTAINER_DLL_insert (serviceListeningInfoList_head,
  1035. serviceListeningInfoList_tail,
  1036. serviceListeningInfo);
  1037. }
  1038. /**
  1039. * Callback function, checks whether the current tokens are representing a service,
  1040. * gets its addresses and create listening socket for it.
  1041. *
  1042. * @param cls callback data, not used
  1043. * @param section configuration section
  1044. * @param option configuration option
  1045. * @param value the option's value
  1046. */
  1047. static void
  1048. checkPortNumberCB (void *cls, const char *section, const char *option,
  1049. const char *value)
  1050. {
  1051. struct sockaddr **addrs;
  1052. socklen_t *addr_lens;
  1053. int ret;
  1054. unsigned int i;
  1055. if ((strcasecmp (section, "arm") == 0) ||
  1056. (strcasecmp (option, "AUTOSTART") != 0) ||
  1057. (strcasecmp (value, "YES") != 0) ||
  1058. (isInDefaultList (section) == GNUNET_YES))
  1059. return;
  1060. if (0 >=
  1061. (ret =
  1062. GNUNET_SERVICE_get_server_addresses (section, cfg, &addrs, &addr_lens)))
  1063. return;
  1064. /* this will free (or capture) addrs[i] */
  1065. for (i = 0; i < ret; i++)
  1066. createListeningSocket (addrs[i], addr_lens[i], section);
  1067. GNUNET_free (addrs);
  1068. GNUNET_free (addr_lens);
  1069. }
  1070. /**
  1071. * Entry point to the Service Manager
  1072. *
  1073. * @param configurationHandle configuration to use to get services
  1074. */
  1075. void
  1076. prepareServices (const struct GNUNET_CONFIGURATION_Handle *configurationHandle)
  1077. {
  1078. char *defaultServicesString;
  1079. cfg = configurationHandle;
  1080. /* Split the default services into a list */
  1081. if (GNUNET_OK ==
  1082. GNUNET_CONFIGURATION_get_value_string (cfg, "arm", "DEFAULTSERVICES",
  1083. &defaultServicesString))
  1084. {
  1085. addDefaultServicesToList (defaultServicesString);
  1086. GNUNET_free (defaultServicesString);
  1087. }
  1088. /* Spot the services from the configuration and create a listening
  1089. * socket for each */
  1090. GNUNET_CONFIGURATION_iterate (cfg, &checkPortNumberCB, NULL);
  1091. }
  1092. /* end of gnunet-service-arm_interceptor.c */