gnunet-service-ats_addresses.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2011-2015 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 ats/gnunet-service-ats_addresses.c
  18. * @brief ats service address management
  19. * @author Matthias Wachs
  20. * @author Christian Grothoff
  21. */
  22. #include "platform.h"
  23. #include "gnunet-service-ats_addresses.h"
  24. #include "gnunet-service-ats_performance.h"
  25. #include "gnunet-service-ats_normalization.h"
  26. #include "gnunet-service-ats_plugins.h"
  27. /**
  28. * A multihashmap to store all addresses
  29. */
  30. struct GNUNET_CONTAINER_MultiPeerMap *GSA_addresses;
  31. /**
  32. * Update statistic on number of addresses.
  33. */
  34. static void
  35. update_addresses_stat ()
  36. {
  37. GNUNET_STATISTICS_set (GSA_stats,
  38. "# addresses",
  39. GNUNET_CONTAINER_multipeermap_size (GSA_addresses),
  40. GNUNET_NO);
  41. }
  42. /**
  43. * Free the given address
  44. *
  45. * @param addr address to destroy
  46. */
  47. static void
  48. free_address (struct ATS_Address *addr)
  49. {
  50. GNUNET_assert (GNUNET_YES ==
  51. GNUNET_CONTAINER_multipeermap_remove (GSA_addresses,
  52. &addr->peer,
  53. addr));
  54. update_addresses_stat ();
  55. GAS_plugin_delete_address (addr);
  56. GAS_performance_notify_all_clients (&addr->peer,
  57. addr->plugin,
  58. addr->addr,
  59. addr->addr_len,
  60. GNUNET_NO,
  61. NULL,
  62. addr->local_address_info,
  63. GNUNET_BANDWIDTH_ZERO,
  64. GNUNET_BANDWIDTH_ZERO);
  65. GNUNET_free (addr->plugin);
  66. GNUNET_free (addr);
  67. }
  68. /**
  69. * Initialize @a norm. Sets all historic values to undefined.
  70. *
  71. * @param norm normalization data to initialize
  72. */
  73. static void
  74. init_norm (struct GAS_NormalizationInfo *norm)
  75. {
  76. unsigned int c;
  77. for (c = 0; c < GAS_normalization_queue_length; c++)
  78. norm->atsi_abs[c] = UINT64_MAX;
  79. }
  80. /**
  81. * Create a ATS_address with the given information
  82. *
  83. * @param peer peer
  84. * @param plugin_name plugin
  85. * @param plugin_addr address
  86. * @param plugin_addr_len address length
  87. * @param local_address_info additional local info for the address
  88. * @param session_id session identifier, can never be 0
  89. * @return the ATS_Address
  90. */
  91. static struct ATS_Address *
  92. create_address (const struct GNUNET_PeerIdentity *peer,
  93. const char *plugin_name,
  94. const void *plugin_addr,
  95. size_t plugin_addr_len,
  96. uint32_t local_address_info,
  97. uint32_t session_id)
  98. {
  99. struct ATS_Address *aa;
  100. aa = GNUNET_malloc (sizeof (struct ATS_Address) + plugin_addr_len);
  101. aa->peer = *peer;
  102. aa->addr_len = plugin_addr_len;
  103. aa->addr = &aa[1];
  104. GNUNET_memcpy (&aa[1],
  105. plugin_addr,
  106. plugin_addr_len);
  107. aa->plugin = GNUNET_strdup (plugin_name);
  108. aa->session_id = session_id;
  109. aa->local_address_info = local_address_info;
  110. init_norm (&aa->norm_delay);
  111. init_norm (&aa->norm_distance);
  112. init_norm (&aa->norm_utilization_in);
  113. init_norm (&aa->norm_utilization_out);
  114. return aa;
  115. }
  116. /**
  117. * Closure for #find_address_cb()
  118. */
  119. struct FindAddressContext
  120. {
  121. /**
  122. * Session Id to look for.
  123. */
  124. uint32_t session_id;
  125. /**
  126. * Where to store matching address result.
  127. */
  128. struct ATS_Address *exact_address;
  129. };
  130. /**
  131. * Find session matching given session ID.
  132. *
  133. * @param cls a `struct FindAddressContext`
  134. * @param key peer id
  135. * @param value the address to compare with
  136. * @return #GNUNET_YES to continue, #GNUNET_NO if address is found
  137. */
  138. static int
  139. find_address_cb (void *cls,
  140. const struct GNUNET_PeerIdentity *key,
  141. void *value)
  142. {
  143. struct FindAddressContext *fac = cls;
  144. struct ATS_Address *aa = value;
  145. if (aa->session_id == fac->session_id)
  146. {
  147. fac->exact_address = aa;
  148. return GNUNET_NO;
  149. }
  150. return GNUNET_YES;
  151. }
  152. /**
  153. * Find the exact address
  154. *
  155. * @param peer peer
  156. * @param session_id session id, can never be 0
  157. * @return an ATS_address or NULL
  158. */
  159. static struct ATS_Address *
  160. find_exact_address (const struct GNUNET_PeerIdentity *peer,
  161. uint32_t session_id)
  162. {
  163. struct FindAddressContext fac;
  164. fac.exact_address = NULL;
  165. fac.session_id = session_id;
  166. GNUNET_CONTAINER_multipeermap_get_multiple (GSA_addresses,
  167. peer,
  168. &find_address_cb, &fac);
  169. return fac.exact_address;
  170. }
  171. /**
  172. * Add a new address for a peer.
  173. *
  174. * @param peer peer
  175. * @param plugin_name transport plugin name
  176. * @param plugin_addr plugin address
  177. * @param plugin_addr_len length of the plugin address in @a plugin_addr
  178. * @param local_address_info the local address for the address
  179. * @param session_id session id, can be 0
  180. * @param prop performance information for this address
  181. */
  182. void
  183. GAS_addresses_add (const struct GNUNET_PeerIdentity *peer,
  184. const char *plugin_name,
  185. const void *plugin_addr,
  186. size_t plugin_addr_len,
  187. uint32_t local_address_info,
  188. uint32_t session_id,
  189. const struct GNUNET_ATS_Properties *prop)
  190. {
  191. struct ATS_Address *new_address;
  192. if (NULL != find_exact_address (peer,
  193. session_id))
  194. {
  195. GNUNET_break (0);
  196. return;
  197. }
  198. GNUNET_break (GNUNET_NT_UNSPECIFIED != prop->scope);
  199. new_address = create_address (peer,
  200. plugin_name,
  201. plugin_addr,
  202. plugin_addr_len,
  203. local_address_info,
  204. session_id);
  205. /* Add a new address */
  206. new_address->properties = *prop;
  207. new_address->t_added = GNUNET_TIME_absolute_get();
  208. new_address->t_last_activity = GNUNET_TIME_absolute_get();
  209. GNUNET_assert(GNUNET_OK ==
  210. GNUNET_CONTAINER_multipeermap_put (GSA_addresses,
  211. peer,
  212. new_address,
  213. GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
  214. update_addresses_stat ();
  215. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  216. "Adding new address for peer `%s' slot %u\n",
  217. GNUNET_i2s (peer),
  218. session_id);
  219. /* Tell solver about new address */
  220. GAS_plugin_solver_lock ();
  221. GAS_plugin_new_address (new_address);
  222. GAS_normalization_update_property (new_address); // FIXME: needed?
  223. GAS_plugin_solver_unlock ();
  224. /* Notify performance clients about new address */
  225. GAS_performance_notify_all_clients (&new_address->peer,
  226. new_address->plugin,
  227. new_address->addr,
  228. new_address->addr_len,
  229. new_address->active,
  230. &new_address->properties,
  231. new_address->local_address_info,
  232. GNUNET_BANDWIDTH_value_init (new_address->assigned_bw_out),
  233. GNUNET_BANDWIDTH_value_init (new_address->assigned_bw_in));
  234. }
  235. /**
  236. * Update an address with new performance information for a peer.
  237. *
  238. * @param peer peer
  239. * @param session_id session id, never 0
  240. * @param prop performance information for this address
  241. */
  242. void
  243. GAS_addresses_update (const struct GNUNET_PeerIdentity *peer,
  244. uint32_t session_id,
  245. const struct GNUNET_ATS_Properties *prop)
  246. {
  247. struct ATS_Address *aa;
  248. /* Get existing address */
  249. aa = find_exact_address (peer,
  250. session_id);
  251. if (NULL == aa)
  252. {
  253. GNUNET_break (0);
  254. return;
  255. }
  256. if (NULL == aa->solver_information)
  257. {
  258. GNUNET_break (0);
  259. return;
  260. }
  261. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  262. "Received ADDRESS_UPDATE for peer `%s' slot %u\n",
  263. GNUNET_i2s (peer),
  264. (unsigned int) session_id);
  265. GNUNET_break (GNUNET_NT_UNSPECIFIED != prop->scope);
  266. /* Update address */
  267. aa->t_last_activity = GNUNET_TIME_absolute_get();
  268. aa->properties = *prop;
  269. /* Notify performance clients about updated address */
  270. GAS_performance_notify_all_clients (&aa->peer,
  271. aa->plugin,
  272. aa->addr,
  273. aa->addr_len,
  274. aa->active,
  275. prop,
  276. aa->local_address_info,
  277. GNUNET_BANDWIDTH_value_init (aa->assigned_bw_out),
  278. GNUNET_BANDWIDTH_value_init (aa->assigned_bw_in));
  279. GAS_normalization_update_property (aa);
  280. }
  281. /**
  282. * Remove an address for a peer.
  283. *
  284. * @param peer peer
  285. * @param session_id session id, can never be 0
  286. */
  287. void
  288. GAS_addresses_destroy (const struct GNUNET_PeerIdentity *peer,
  289. uint32_t session_id)
  290. {
  291. struct ATS_Address *ea;
  292. /* Get existing address */
  293. ea = find_exact_address (peer,
  294. session_id);
  295. if (NULL == ea)
  296. {
  297. GNUNET_break (0);
  298. return;
  299. }
  300. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  301. "Received ADDRESS_DESTROYED for peer `%s' session %u\n",
  302. GNUNET_i2s (peer),
  303. session_id);
  304. free_address (ea);
  305. }
  306. /**
  307. * Initialize address subsystem. The addresses subsystem manages the addresses
  308. * known and current performance information. It has a solver component
  309. * responsible for the resource allocation. It tells the solver about changes
  310. * and receives updates when the solver changes the resource allocation.
  311. */
  312. void
  313. GAS_addresses_init ()
  314. {
  315. GSA_addresses
  316. = GNUNET_CONTAINER_multipeermap_create (128,
  317. GNUNET_NO);
  318. update_addresses_stat ();
  319. }
  320. /**
  321. * Destroy all addresses iterator
  322. *
  323. * @param cls NULL
  324. * @param key peer identity (unused)
  325. * @param value the 'struct ATS_Address' to free
  326. * @return #GNUNET_OK (continue to iterate)
  327. */
  328. static int
  329. destroy_all_address_it (void *cls,
  330. const struct GNUNET_PeerIdentity *key,
  331. void *value)
  332. {
  333. struct ATS_Address *aa = value;
  334. free_address (aa);
  335. return GNUNET_OK;
  336. }
  337. /**
  338. * Remove all addresses
  339. */
  340. void
  341. GAS_addresses_destroy_all ()
  342. {
  343. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  344. "Destroying all addresses\n");
  345. if (0 ==
  346. GNUNET_CONTAINER_multipeermap_size (GSA_addresses))
  347. return;
  348. GAS_plugin_solver_lock ();
  349. GNUNET_CONTAINER_multipeermap_iterate (GSA_addresses,
  350. &destroy_all_address_it,
  351. NULL);
  352. GAS_plugin_solver_unlock ();
  353. }
  354. /**
  355. * Shutdown address subsystem.
  356. */
  357. void
  358. GAS_addresses_done ()
  359. {
  360. GNUNET_log(GNUNET_ERROR_TYPE_INFO,
  361. "Shutting down addresses\n");
  362. GAS_plugin_solver_lock ();
  363. GAS_addresses_destroy_all ();
  364. GAS_plugin_solver_unlock ();
  365. GNUNET_CONTAINER_multipeermap_destroy (GSA_addresses);
  366. GSA_addresses = NULL;
  367. }
  368. /**
  369. * Closure for #peerinfo_it().
  370. */
  371. struct PeerInfoIteratorContext
  372. {
  373. /**
  374. * Function to call for each address.
  375. */
  376. GNUNET_ATS_PeerInfo_Iterator it;
  377. /**
  378. * Closure for @e it.
  379. */
  380. void *it_cls;
  381. };
  382. /**
  383. * Iterator to iterate over a peer's addresses
  384. *
  385. * @param cls a `struct PeerInfoIteratorContext`
  386. * @param key the peer id
  387. * @param value the `struct ATS_address`
  388. * @return #GNUNET_OK to continue
  389. */
  390. static int
  391. peerinfo_it (void *cls,
  392. const struct GNUNET_PeerIdentity *key,
  393. void *value)
  394. {
  395. struct PeerInfoIteratorContext *pi_ctx = cls;
  396. struct ATS_Address *addr = value;
  397. pi_ctx->it (pi_ctx->it_cls,
  398. &addr->peer,
  399. addr->plugin,
  400. addr->addr,
  401. addr->addr_len,
  402. addr->active,
  403. &addr->properties,
  404. addr->local_address_info,
  405. GNUNET_BANDWIDTH_value_init (addr->assigned_bw_out),
  406. GNUNET_BANDWIDTH_value_init (addr->assigned_bw_in));
  407. return GNUNET_OK;
  408. }
  409. /**
  410. * Return information all peers currently known to ATS
  411. *
  412. * @param peer the respective peer, NULL for 'all' peers
  413. * @param pi_it the iterator to call for every peer
  414. * @param pi_it_cls the closure for @a pi_it
  415. */
  416. void
  417. GAS_addresses_get_peer_info (const struct GNUNET_PeerIdentity *peer,
  418. GNUNET_ATS_PeerInfo_Iterator pi_it,
  419. void *pi_it_cls)
  420. {
  421. struct PeerInfoIteratorContext pi_ctx;
  422. if (NULL == pi_it)
  423. {
  424. /* does not make sense without callback */
  425. GNUNET_break (0);
  426. return;
  427. }
  428. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  429. "Returning information for %s from a total of %u known addresses\n",
  430. (NULL == peer)
  431. ? "all peers"
  432. : GNUNET_i2s (peer),
  433. (unsigned int) GNUNET_CONTAINER_multipeermap_size (GSA_addresses));
  434. pi_ctx.it = pi_it;
  435. pi_ctx.it_cls = pi_it_cls;
  436. if (NULL == peer)
  437. GNUNET_CONTAINER_multipeermap_iterate (GSA_addresses,
  438. &peerinfo_it,
  439. &pi_ctx);
  440. else
  441. GNUNET_CONTAINER_multipeermap_get_multiple (GSA_addresses,
  442. peer,
  443. &peerinfo_it, &pi_ctx);
  444. pi_it (pi_it_cls,
  445. NULL, NULL, NULL, 0,
  446. GNUNET_NO,
  447. NULL,
  448. GNUNET_HELLO_ADDRESS_INFO_NONE,
  449. GNUNET_BANDWIDTH_ZERO,
  450. GNUNET_BANDWIDTH_ZERO);
  451. }
  452. /**
  453. * Information we need for the callbacks to return a list of addresses
  454. * back to the client.
  455. */
  456. struct AddressIteration
  457. {
  458. /**
  459. * Actual handle to the client.
  460. */
  461. struct GNUNET_SERVICE_Client *client;
  462. /**
  463. * Are we sending all addresses, or only those that are active?
  464. */
  465. int all;
  466. /**
  467. * Which ID should be included in the response?
  468. */
  469. uint32_t id;
  470. };
  471. /**
  472. * Send a #GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_RESPONSE with the
  473. * given address details to the client identified in @a ai.
  474. *
  475. * @param ai our address information context (identifies the client)
  476. * @param id the peer id this address is for
  477. * @param plugin_name name of the plugin that supports this address
  478. * @param plugin_addr address
  479. * @param plugin_addr_len length of @a plugin_addr
  480. * @param active #GNUNET_YES if this address is actively used
  481. * @param prop performance information
  482. * @param local_address_info flags for the address
  483. * @param bandwidth_out current outbound bandwidth assigned to address
  484. * @param bandwidth_in current inbound bandwidth assigned to address
  485. */
  486. static void
  487. transmit_req_addr (struct AddressIteration *ai,
  488. const struct GNUNET_PeerIdentity *id,
  489. const char *plugin_name,
  490. const void *plugin_addr,
  491. size_t plugin_addr_len,
  492. int active,
  493. const struct GNUNET_ATS_Properties *prop,
  494. enum GNUNET_HELLO_AddressInfo local_address_info,
  495. struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
  496. struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
  497. {
  498. struct GNUNET_MQ_Envelope *env;
  499. struct PeerInformationMessage *msg;
  500. char *addrp;
  501. size_t plugin_name_length;
  502. size_t msize;
  503. if (NULL != plugin_name)
  504. plugin_name_length = strlen (plugin_name) + 1;
  505. else
  506. plugin_name_length = 0;
  507. msize = plugin_addr_len + plugin_name_length;
  508. GNUNET_assert (sizeof (struct PeerInformationMessage) + msize
  509. < GNUNET_MAX_MESSAGE_SIZE);
  510. env = GNUNET_MQ_msg_extra (msg,
  511. msize,
  512. GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_RESPONSE);
  513. msg->id = htonl (ai->id);
  514. if (NULL != id)
  515. msg->peer = *id;
  516. msg->address_length = htons (plugin_addr_len);
  517. msg->address_active = ntohl (active);
  518. msg->plugin_name_length = htons (plugin_name_length);
  519. msg->bandwidth_out = bandwidth_out;
  520. msg->bandwidth_in = bandwidth_in;
  521. if (NULL != prop)
  522. GNUNET_ATS_properties_hton (&msg->properties,
  523. prop);
  524. msg->address_local_info = htonl ((uint32_t) local_address_info);
  525. addrp = (char *) &msg[1];
  526. GNUNET_memcpy (addrp,
  527. plugin_addr,
  528. plugin_addr_len);
  529. if (NULL != plugin_name)
  530. strcpy (&addrp[plugin_addr_len],
  531. plugin_name);
  532. GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (ai->client),
  533. env);
  534. }
  535. /**
  536. * Iterator for #GAS_addresses_get_peer_info(), called with peer-specific
  537. * information to be passed back to the client.
  538. *
  539. * @param cls closure with our `struct AddressIteration *`
  540. * @param id the peer id
  541. * @param plugin_name plugin name
  542. * @param plugin_addr address
  543. * @param plugin_addr_len length of @a plugin_addr
  544. * @param active is address actively used
  545. * @param prop performance information
  546. * @param local_address_info additional local info for the address
  547. * @param bandwidth_out current outbound bandwidth assigned to address
  548. * @param bandwidth_in current inbound bandwidth assigned to address
  549. */
  550. static void
  551. req_addr_peerinfo_it (void *cls,
  552. const struct GNUNET_PeerIdentity *id,
  553. const char *plugin_name,
  554. const void *plugin_addr,
  555. size_t plugin_addr_len,
  556. int active,
  557. const struct GNUNET_ATS_Properties *prop,
  558. enum GNUNET_HELLO_AddressInfo local_address_info,
  559. struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
  560. struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
  561. {
  562. struct AddressIteration *ai = cls;
  563. if ( (NULL == id) &&
  564. (NULL == plugin_name) &&
  565. (NULL == plugin_addr) )
  566. {
  567. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  568. "Address iteration done for one peer\n");
  569. return;
  570. }
  571. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  572. "Callback for %s peer `%s' plugin `%s' BW out %u, BW in %u\n",
  573. (active == GNUNET_YES) ? "ACTIVE" : "INACTIVE",
  574. GNUNET_i2s (id),
  575. plugin_name,
  576. (unsigned int) ntohl (bandwidth_out.value__),
  577. (unsigned int) ntohl (bandwidth_in.value__));
  578. /* Transmit result (either if address is active, or if
  579. client wanted all addresses) */
  580. if ( (GNUNET_YES != ai->all) &&
  581. (GNUNET_YES != active))
  582. return;
  583. transmit_req_addr (ai,
  584. id,
  585. plugin_name,
  586. plugin_addr, plugin_addr_len,
  587. active,
  588. prop,
  589. local_address_info,
  590. bandwidth_out,
  591. bandwidth_in);
  592. }
  593. /**
  594. * Handle 'address list request' messages from clients.
  595. *
  596. * @param cls client that sent the request
  597. * @param alrm the request message
  598. */
  599. void
  600. GAS_handle_request_address_list (struct GNUNET_SERVICE_Client *client,
  601. const struct AddressListRequestMessage *alrm)
  602. {
  603. struct AddressIteration ai;
  604. struct GNUNET_PeerIdentity allzeros;
  605. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  606. "Received ADDRESSLIST_REQUEST message\n");
  607. ai.all = ntohl (alrm->all);
  608. ai.id = ntohl (alrm->id);
  609. ai.client = client;
  610. memset (&allzeros,
  611. '\0',
  612. sizeof (struct GNUNET_PeerIdentity));
  613. if (0 == memcmp (&alrm->peer,
  614. &allzeros,
  615. sizeof (struct GNUNET_PeerIdentity)))
  616. {
  617. /* Return addresses for all peers */
  618. GAS_addresses_get_peer_info (NULL,
  619. &req_addr_peerinfo_it,
  620. &ai);
  621. }
  622. else
  623. {
  624. /* Return addresses for a specific peer */
  625. GAS_addresses_get_peer_info (&alrm->peer,
  626. &req_addr_peerinfo_it,
  627. &ai);
  628. }
  629. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  630. "Finished handling `%s' message\n",
  631. "ADDRESSLIST_REQUEST");
  632. transmit_req_addr (&ai,
  633. NULL, NULL, NULL,
  634. 0, GNUNET_NO,
  635. NULL,
  636. GNUNET_HELLO_ADDRESS_INFO_NONE,
  637. GNUNET_BANDWIDTH_ZERO,
  638. GNUNET_BANDWIDTH_ZERO);
  639. }
  640. /* end of gnunet-service-ats_addresses.c */