aboutsummaryrefslogtreecommitdiff
path: root/src/lib/hello/gnunet-hello.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/hello/gnunet-hello.c')
-rw-r--r--src/lib/hello/gnunet-hello.c427
1 files changed, 427 insertions, 0 deletions
diff --git a/src/lib/hello/gnunet-hello.c b/src/lib/hello/gnunet-hello.c
new file mode 100644
index 000000000..7f43e77b9
--- /dev/null
+++ b/src/lib/hello/gnunet-hello.c
@@ -0,0 +1,427 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2012 GNUnet e.V.
4
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.
9
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.
14
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/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file hello/gnunet-hello.c
22 * @brief change HELLO files to never expire
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "gnunet_protocols.h"
27#include "gnunet_hello_lib.h"
28#include "gnunet_hello_uri_lib.h"
29#include "gnunet_transport_plugin.h"
30
31/**
32 * Closure for #add_to_buf().
33 */
34struct AddContext
35{
36 /**
37 * Where to add.
38 */
39 char *buf;
40
41 /**
42 * Maximum number of bytes left
43 */
44 size_t max;
45
46 /**
47 * Number of bytes added so far.
48 */
49 size_t ret;
50
51 struct GNUNET_HELLO_Builder *builder;
52};
53
54/**
55 * Entry in doubly-linked list of all of our plugins.
56 */
57struct TransportPlugin
58{
59 /**
60 * This is a doubly-linked list.
61 */
62 struct TransportPlugin *next;
63
64 /**
65 * This is a doubly-linked list.
66 */
67 struct TransportPlugin *prev;
68
69 /**
70 * API of the transport as returned by the plugin's
71 * initialization function.
72 */
73 struct GNUNET_TRANSPORT_PluginFunctions *api;
74
75 /**
76 * Short name for the plugin (e.g. "tcp").
77 */
78 char *short_name;
79
80 /**
81 * Name of the library (e.g. "gnunet_plugin_transport_tcp").
82 */
83 char *lib_name;
84
85 /**
86 * Environment this transport service is using
87 * for this plugin.
88 */
89 struct GNUNET_TRANSPORT_PluginEnvironment env;
90};
91
92static int address_count;
93
94/**
95 * Our private key.
96 */
97static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
98
99/**
100 * Local peer own ID.
101 */
102struct GNUNET_PeerIdentity my_full_id;
103
104/**
105 * The file with hello in old style which we like to replace with the new one.
106 */
107static char *hello_file;
108
109/**
110 * Head of DLL of all loaded plugins.
111 */
112static struct TransportPlugin *plugins_head;
113
114/**
115 * Head of DLL of all loaded plugins.
116 */
117static struct TransportPlugin *plugins_tail;
118
119static void
120plugins_load (const struct GNUNET_CONFIGURATION_Handle *cfg)
121{
122 struct TransportPlugin *plug;
123 struct TransportPlugin *next;
124 char *libname;
125 char *plugs;
126 char *pos;
127
128 if (NULL != plugins_head)
129 return; /* already loaded */
130 if (GNUNET_OK !=
131 GNUNET_CONFIGURATION_get_value_string (cfg, "TRANSPORT", "PLUGINS",
132 &plugs))
133 return;
134 fprintf (stdout,"Starting transport plugins `%s'\n",
135 plugs);
136 for (pos = strtok (plugs, " "); pos != NULL; pos = strtok (NULL, " "))
137 {
138 fprintf (stdout,"Loading `%s' transport plugin\n",
139 pos);
140 GNUNET_asprintf (&libname, "libgnunet_plugin_transport_%s", pos);
141 plug = GNUNET_new (struct TransportPlugin);
142 plug->short_name = GNUNET_strdup (pos);
143 plug->lib_name = libname;
144 plug->env.cfg = cfg;
145 plug->env.cls = plug->short_name;
146 GNUNET_CONTAINER_DLL_insert (plugins_head, plugins_tail, plug);
147 }
148 GNUNET_free (plugs);
149 next = plugins_head;
150 while (next != NULL)
151 {
152 plug = next;
153 next = plug->next;
154 plug->api = GNUNET_PLUGIN_load (plug->lib_name, &plug->env);
155 if (plug->api == NULL)
156 {
157 fprintf (stdout,"Failed to load transport plugin for `%s'\n",
158 plug->lib_name);
159 GNUNET_CONTAINER_DLL_remove (plugins_head, plugins_tail, plug);
160 GNUNET_free (plug->short_name);
161 GNUNET_free (plug->lib_name);
162 GNUNET_free (plug);
163 }
164 }
165}
166
167
168static int
169add_to_builder (void *cls,
170 const struct GNUNET_HELLO_Address *address,
171 struct GNUNET_TIME_Absolute expiration)
172{
173 struct GNUNET_HELLO_Builder *builder= cls;
174 struct TransportPlugin *pos = plugins_head;
175 const char *addr;
176 char *uri;
177
178 while (NULL != pos)
179 {
180 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
181 "short_name: %s transport_name: %s\n",
182 pos->short_name,
183 address->transport_name);
184 if (0 == strcmp (address->transport_name, pos->short_name))
185 {
186 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
187 "short_name: %s transport_name: %s are the same\n",
188 pos->short_name,
189 address->transport_name);
190 addr = strchr (strchr (pos->api->address_to_string (pos, address, address->address_length), '.')+1, '.') + 1;
191 }
192 pos = pos->next;
193 }
194
195 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
196 "Hello address string: %s\n",
197 addr);
198 GNUNET_asprintf (&uri, "%s://%s", address->transport_name, addr);
199 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
200 "Hello address uri string: %s\n",
201 uri);
202 GNUNET_HELLO_builder_add_address (builder,
203 uri);
204}
205
206
207/**
208 * Add the given address with infinite expiration to the buffer.
209 *
210 * @param cls closure
211 * @param address address to add
212 * @param expiration old expiration
213 * @return #GNUNET_OK keep iterating
214 */
215static int
216add_to_buf (void *cls,
217 const struct GNUNET_HELLO_Address *address,
218 struct GNUNET_TIME_Absolute expiration)
219{
220 struct AddContext *ac = cls;
221 size_t ret;
222
223 ret = GNUNET_HELLO_add_address (address,
224 GNUNET_TIME_UNIT_FOREVER_ABS,
225 ac->buf,
226 ac->max);
227
228 ac->buf += ret;
229 ac->max -= ret;
230 ac->ret += ret;
231 address_count++;
232 return GNUNET_OK;
233}
234
235
236/**
237 * Add addresses from the address list to the HELLO.
238 *
239 * @param cls the HELLO with the addresses to add
240 * @param max maximum space available
241 * @param buf where to add the addresses
242 * @return number of bytes added, 0 to terminate
243 */
244static ssize_t
245add_from_hello (void *cls, size_t max, void *buf)
246{
247 struct GNUNET_HELLO_Message **orig = cls;
248 struct AddContext ac;
249
250 if (NULL == *orig)
251 return GNUNET_SYSERR; /* already done */
252 ac.buf = buf;
253 ac.max = max;
254 ac.ret = 0;
255 GNUNET_assert (
256 NULL ==
257 GNUNET_HELLO_iterate_addresses (*orig, GNUNET_NO, &add_to_buf, &ac));
258 *orig = NULL;
259 return ac.ret;
260}
261
262
263/**
264 * Main function that will be run without the scheduler.
265 *
266 * @param cls closure
267 * @param args remaining command-line arguments
268 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
269 * @param c configuration
270 */
271static void
272run (void *cls,
273 char *const *args,
274 const char *cfgfile,
275 const struct GNUNET_CONFIGURATION_Handle *c)
276{
277 struct GNUNET_DISK_FileHandle *fh;
278 struct GNUNET_HELLO_Message *orig;
279 struct GNUNET_HELLO_Message *result;
280 struct GNUNET_PeerIdentity pid;
281 uint64_t fsize;
282 ssize_t size_written;
283 struct GNUNET_HELLO_Builder *builder;
284 char *url;
285 const struct GNUNET_MessageHeader *msg;
286 struct GNUNET_MQ_Envelope *env;
287
288 plugins_load (c);
289 address_count = 0;
290
291 my_private_key =
292 GNUNET_CRYPTO_eddsa_key_create_from_configuration (c);
293 GNUNET_CRYPTO_eddsa_key_get_public (my_private_key,
294 &my_full_id.public_key);
295 fprintf (stdout,"We are peer %s\n", GNUNET_i2s (&my_full_id));
296
297 GNUNET_log_setup ("gnunet-hello", "DEBUG", NULL);
298
299 if (GNUNET_OK !=
300 GNUNET_DISK_file_size (hello_file, &fsize, GNUNET_YES, GNUNET_YES))
301 {
302 fprintf (stderr,
303 _ ("Error accessing file `%s': %s\n"),
304 hello_file,
305 strerror (errno));
306 return;
307 }
308 if (fsize > 65536)
309 {
310 fprintf (stderr, _ ("File `%s' is too big to be a HELLO\n"), hello_file);
311 return;
312 }
313 if (fsize < sizeof(struct GNUNET_MessageHeader))
314 {
315 fprintf (stderr, _ ("File `%s' is too small to be a HELLO\n"), hello_file);
316 return;
317 }
318 fh = GNUNET_DISK_file_open (hello_file,
319 GNUNET_DISK_OPEN_READ,
320 GNUNET_DISK_PERM_USER_READ);
321 if (NULL == fh)
322 {
323 fprintf (stderr,
324 _ ("Error opening file `%s': %s\n"),
325 hello_file,
326 strerror (errno));
327 return;
328 }
329 {
330 char buf[fsize] GNUNET_ALIGN;
331
332 GNUNET_assert (fsize == GNUNET_DISK_file_read (fh, buf, fsize));
333 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh));
334 orig = (struct GNUNET_HELLO_Message *) buf;
335 if ((fsize < GNUNET_HELLO_size (orig)) ||
336 (GNUNET_OK != GNUNET_HELLO_get_id (orig, &pid)))
337 {
338 fprintf (stderr,
339 _ ("Did not find well-formed HELLO in file `%s'\n"),
340 hello_file);
341 return;
342 }
343 {
344 char *pids;
345
346 pids = GNUNET_CRYPTO_eddsa_public_key_to_string (&my_full_id.public_key);
347 fprintf (stdout, "Processing HELLO for peer `%s'\n", pids);
348 GNUNET_free (pids);
349 }
350 /* result = GNUNET_HELLO_create (&pid.public_key, */
351 /* &add_from_hello, */
352 /* &orig, */
353 /* GNUNET_HELLO_is_friend_only (orig)); */
354
355 builder = GNUNET_HELLO_builder_new (&my_full_id);
356 GNUNET_assert (
357 NULL ==
358 GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *) orig, GNUNET_NO, &add_to_builder, builder));
359 url = GNUNET_HELLO_builder_to_url (builder, my_private_key);
360 fprintf (stdout,"url: %s\n", url);
361 env = GNUNET_HELLO_builder_to_env (builder,
362 my_private_key,
363 GNUNET_TIME_UNIT_FOREVER_REL);
364 msg = GNUNET_MQ_env_get_msg (env);
365 //GNUNET_assert (NULL != result);
366 GNUNET_assert (NULL != msg);
367 fh =
368 GNUNET_DISK_file_open (hello_file,
369 GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_TRUNCATE,
370 GNUNET_DISK_PERM_USER_READ
371 | GNUNET_DISK_PERM_USER_WRITE);
372 if (NULL == fh)
373 {
374 fprintf (stderr,
375 _ ("Error opening file `%s': %s\n"),
376 hello_file,
377 strerror (errno));
378 GNUNET_free (result);
379 return;
380 }
381 //fsize = GNUNET_HELLO_size (result);
382 size_written = GNUNET_DISK_file_write (fh, msg, ntohs (msg->size));
383 if (ntohs (msg->size) != size_written)
384 {
385 fprintf (stderr,
386 _ ("Error writing HELLO to file `%s': %s expected size %u size written %u\n"),
387 hello_file,
388 strerror (errno));
389 (void) GNUNET_DISK_file_close (fh);
390 return;
391 }
392 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh));
393 }
394 fprintf (stderr,
395 _ ("Modified %u addresses, wrote %u bytes\n"),
396 address_count,
397 (unsigned int) ntohs (msg->size));
398 GNUNET_HELLO_builder_free (builder);
399}
400
401
402int
403main (int argc, char *argv[])
404{
405 struct GNUNET_GETOPT_CommandLineOption options[] =
406 { GNUNET_GETOPT_option_string ('h',
407 "hello-file",
408 "HELLO_FILE",
409 gettext_noop ("Hello file to read"),
410 &hello_file),
411 GNUNET_GETOPT_OPTION_END };
412 int ret;
413
414 ret = (GNUNET_OK ==
415 GNUNET_PROGRAM_run2 (argc,
416 argv,
417 "gnunet-peerinfo",
418 gettext_noop ("Print information about peers."),
419 options,
420 &run,
421 NULL,
422 GNUNET_YES));
423 return ret;
424}
425
426
427/* end of gnunet-hello.c */