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