2 This file is part of GNUnet.
3 Copyright (C) 2010,2011 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @file transport/gnunet-service-transport_hello.c
23 * @brief hello management implementation
24 * @author Christian Grothoff
27 #include "gnunet_constants.h"
28 #include "gnunet_hello_lib.h"
29 #include "gnunet_peerinfo_service.h"
30 #include "gnunet_statistics_service.h"
31 #include "gnunet-service-transport_hello.h"
32 #include "gnunet-service-transport.h"
33 #include "gnunet-service-transport_plugins.h"
37 * How often do we refresh our HELLO (due to expiration concerns)?
39 #define HELLO_REFRESH_PERIOD GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_HOURS, 6)
42 * Hello address expiration
44 extern struct GNUNET_TIME_Relative hello_expiration;
48 * Entry in linked list of network addresses for ourselves. Also
49 * includes a cached signature for 'struct TransportPongMessage's.
51 struct OwnAddressList {
53 * This is a doubly-linked list.
55 struct OwnAddressList *next;
58 * This is a doubly-linked list.
60 struct OwnAddressList *prev;
65 struct GNUNET_HELLO_Address *address;
68 * How long until the current signature expires? (ZERO if the
69 * signature was never created).
71 struct GNUNET_TIME_Absolute pong_sig_expires;
74 * Signature for a 'struct TransportPongMessage' for this address.
76 struct GNUNET_CRYPTO_EddsaSignature pong_signature;
79 * How often has this address been added/removed? Used as
80 * some plugins may learn the same external address from
90 static struct GNUNET_HELLO_Message *our_hello;
93 * Function to call on HELLO changes.
95 static GST_HelloCallback hello_cb;
98 * Closure for #hello_cb.
100 static void *hello_cb_cls;
103 * Head of my addresses.
105 static struct OwnAddressList *oal_head;
108 * Tail of my addresses.
110 static struct OwnAddressList *oal_tail;
113 * Should we use a friend-only HELLO?
115 static int friend_option;
118 * Identifier of #refresh_hello_task().
120 static struct GNUNET_SCHEDULER_Task *hello_task;
124 * Closure for #address_generator().
126 struct GeneratorContext {
128 * Where are we in the DLL?
130 struct OwnAddressList *addr_pos;
133 * When do addresses expire?
135 struct GNUNET_TIME_Absolute expiration;
140 * Add an address from the `struct OwnAddressList` to the buffer.
142 * @param cls the `struct GeneratorContext`
143 * @param max maximum number of bytes left
144 * @param buf where to write the address
145 * @return bytes written or #GNUNET_SYSERR to signal the
146 * end of the iteration.
149 address_generator(void *cls,
153 struct GeneratorContext *gc = cls;
156 if (NULL == gc->addr_pos)
157 return GNUNET_SYSERR; /* Done */
158 ret = GNUNET_HELLO_add_address(gc->addr_pos->address,
162 gc->addr_pos = gc->addr_pos->next;
168 * Construct our HELLO message from all of the addresses of
169 * all of the transports.
174 refresh_hello_task(void *cls)
176 struct GeneratorContext gc;
179 gc.addr_pos = oal_head;
180 gc.expiration = GNUNET_TIME_relative_to_absolute(hello_expiration);
182 GNUNET_free_non_null(our_hello);
183 our_hello = GNUNET_HELLO_create(&GST_my_identity.public_key,
187 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
188 "Refreshed my %s HELLO, new size is %d\n",
189 (GNUNET_YES == friend_option) ? "friend-only" : "public",
190 GNUNET_HELLO_size(our_hello));
191 GNUNET_STATISTICS_update(GST_stats,
192 gettext_noop("# refreshed my HELLO"),
195 if (NULL != hello_cb)
196 hello_cb(hello_cb_cls,
198 GNUNET_PEERINFO_add_peer(GST_peerinfo,
203 GNUNET_SCHEDULER_add_delayed(HELLO_REFRESH_PERIOD,
210 * Schedule task to refresh hello (but only if such a
211 * task exists already, as otherwise the module might
212 * have been shutdown).
217 if (NULL != hello_task)
219 GNUNET_SCHEDULER_cancel(hello_task);
220 hello_task = GNUNET_SCHEDULER_add_now(&refresh_hello_task,
227 * Initialize the HELLO module.
229 * @param friend_only use a friend only hello
230 * @param cb function to call whenever our HELLO changes
231 * @param cb_cls closure for @a cb
234 GST_hello_start(int friend_only,
235 GST_HelloCallback cb,
239 hello_cb_cls = cb_cls;
240 friend_option = friend_only;
241 refresh_hello_task(NULL);
246 * Shutdown the HELLO module.
253 if (NULL != hello_task)
255 GNUNET_SCHEDULER_cancel(hello_task);
258 if (NULL != our_hello)
260 GNUNET_free(our_hello);
267 * Obtain this peers HELLO message.
269 * @return our HELLO message
271 const struct GNUNET_MessageHeader *
274 return (const struct GNUNET_MessageHeader *)our_hello;
279 * Add or remove an address from this peer's HELLO message.
281 * @param addremove #GNUNET_YES to add, #GNUNET_NO to remove
282 * @param address address to add or remove
285 GST_hello_modify_addresses(int addremove,
286 const struct GNUNET_HELLO_Address *address)
288 struct OwnAddressList *al;
290 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
291 (GNUNET_YES == addremove)
292 ? "Adding `%s' to the set of our addresses\n"
293 : "Removing `%s' from the set of our addresses\n",
294 GST_plugins_a2s(address));
295 GNUNET_assert(NULL != address);
296 for (al = oal_head; al != NULL; al = al->next)
297 if (0 == GNUNET_HELLO_address_cmp(address, al->address))
299 if (GNUNET_NO == addremove)
303 /* address to be removed not found!? */
309 return; /* RC not yet zero */
310 GNUNET_CONTAINER_DLL_remove(oal_head,
313 GNUNET_HELLO_address_free(al->address);
320 /* address added twice or more */
324 al = GNUNET_new(struct OwnAddressList);
326 GNUNET_CONTAINER_DLL_insert(oal_head,
329 al->address = GNUNET_HELLO_address_copy(address);
335 * Test if a particular address is one of ours.
337 * @param address address to test
338 * @param sig location where to cache PONG signatures for this address [set]
339 * @param sig_expiration how long until the current 'sig' expires?
340 * (ZERO if sig was never created) [set]
341 * @return #GNUNET_YES if this is one of our addresses,
345 GST_hello_test_address(const struct GNUNET_HELLO_Address *address,
346 struct GNUNET_CRYPTO_EddsaSignature **sig,
347 struct GNUNET_TIME_Absolute **sig_expiration)
349 struct OwnAddressList *al;
351 for (al = oal_head; al != NULL; al = al->next)
352 if (0 == GNUNET_HELLO_address_cmp(address,
355 *sig = &al->pong_signature;
356 *sig_expiration = &al->pong_sig_expires;
360 *sig_expiration = NULL;
365 /* end of file gnunet-service-transport_hello.c */