aboutsummaryrefslogtreecommitdiff
path: root/src/hello
diff options
context:
space:
mode:
Diffstat (limited to 'src/hello')
-rw-r--r--src/hello/.gitignore3
-rw-r--r--src/hello/Makefile.am60
-rw-r--r--src/hello/address.c157
-rw-r--r--src/hello/gnunet-hello.c215
-rw-r--r--src/hello/hello-ng.c197
-rw-r--r--src/hello/hello.c1271
-rw-r--r--src/hello/test_friend_hello.c185
-rw-r--r--src/hello/test_hello-ng.c37
-rw-r--r--src/hello/test_hello.c253
9 files changed, 0 insertions, 2378 deletions
diff --git a/src/hello/.gitignore b/src/hello/.gitignore
deleted file mode 100644
index bb49ceb20..000000000
--- a/src/hello/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
1gnunet-hello
2test_friend_hello
3test_hello
diff --git a/src/hello/Makefile.am b/src/hello/Makefile.am
deleted file mode 100644
index 6a250e42f..000000000
--- a/src/hello/Makefile.am
+++ /dev/null
@@ -1,60 +0,0 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4if USE_COVERAGE
5 AM_CFLAGS = --coverage -O0
6 XLIB = -lgcov
7endif
8
9lib_LTLIBRARIES = libgnunethello.la
10
11libgnunethello_la_SOURCES = \
12 hello.c \
13 address.c \
14 hello-ng.c
15libgnunethello_la_LIBADD = \
16 $(top_builddir)/src/util/libgnunetutil.la $(XLIB) \
17 $(LTLIBINTL)
18libgnunethello_la_LDFLAGS = \
19 $(GN_LIB_LDFLAGS) \
20 -version-info 1:0:1
21
22noinst_PROGRAMS = \
23 gnunet-hello
24
25check_PROGRAMS = \
26 test_hello \
27 test_friend_hello \
28 test_hello-ng
29
30if ENABLE_TEST_RUN
31AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
32TESTS = $(check_PROGRAMS)
33endif
34
35test_hello_SOURCES = \
36 test_hello.c
37test_hello_LDADD = \
38 libgnunethello.la \
39 $(top_builddir)/src/util/libgnunetutil.la
40
41test_hello_ng_SOURCES = \
42 test_hello-ng.c
43test_hello_ng_LDADD = \
44 libgnunethello.la \
45 $(top_builddir)/src/util/libgnunetutil.la
46
47
48test_friend_hello_SOURCES = \
49 test_friend_hello.c
50test_friend_hello_LDADD = \
51 libgnunethello.la \
52 $(top_builddir)/src/util/libgnunetutil.la
53
54gnunet_hello_SOURCES = \
55 gnunet-hello.c
56gnunet_hello_LDADD = \
57 libgnunethello.la \
58 $(top_builddir)/src/util/libgnunetutil.la
59gnunet_hello_LDFLAGS = \
60 $(GN_LIBINTL)
diff --git a/src/hello/address.c b/src/hello/address.c
deleted file mode 100644
index e22f3850f..000000000
--- a/src/hello/address.c
+++ /dev/null
@@ -1,157 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009 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/**
22 * @file hello/address.c
23 * @brief helper functions for handling addresses
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_hello_lib.h"
28#include "gnunet_util_lib.h"
29
30
31/**
32 * Check if an address has a local option set
33 *
34 * @param address the address to check
35 * @param option the respective option to check for
36 * @return #GNUNET_YES or #GNUNET_NO
37 */
38int
39GNUNET_HELLO_address_check_option (const struct GNUNET_HELLO_Address *address,
40 enum GNUNET_HELLO_AddressInfo option)
41{
42 if (option == (address->local_info & option))
43 return GNUNET_YES;
44 return GNUNET_NO;
45}
46
47
48/**
49 * Get the size of an address struct.
50 *
51 * @param address address
52 * @return the size
53 */
54size_t
55GNUNET_HELLO_address_get_size (const struct GNUNET_HELLO_Address *address)
56{
57 return sizeof(struct GNUNET_HELLO_Address) + address->address_length
58 + strlen (address->transport_name) + 1;
59}
60
61
62/**
63 * Allocate an address struct.
64 *
65 * @param peer the peer
66 * @param transport_name plugin name
67 * @param address binary address
68 * @param address_length number of bytes in 'address'
69 * @param local_info additional local information for the address
70 * @return the address struct
71 */
72struct GNUNET_HELLO_Address *
73GNUNET_HELLO_address_allocate (const struct GNUNET_PeerIdentity *peer,
74 const char *transport_name,
75 const void *address,
76 size_t address_length,
77 enum GNUNET_HELLO_AddressInfo local_info)
78{
79 struct GNUNET_HELLO_Address *addr;
80 size_t slen;
81 char *end;
82
83 slen = strlen (transport_name) + 1;
84 addr = GNUNET_malloc (sizeof(struct GNUNET_HELLO_Address)
85 + address_length + slen);
86 addr->peer = *peer;
87 addr->address = &addr[1];
88 addr->address_length = address_length;
89 addr->local_info = local_info;
90 end = (char *) &addr[1];
91 addr->transport_name = &end[address_length];
92 GNUNET_memcpy (end,
93 address,
94 address_length);
95 GNUNET_memcpy (&end[address_length],
96 transport_name,
97 slen);
98 return addr;
99}
100
101
102/**
103 * Copy an address struct.
104 *
105 * @param address address to copy
106 * @return a copy of the address struct
107 */
108struct GNUNET_HELLO_Address *
109GNUNET_HELLO_address_copy (const struct GNUNET_HELLO_Address *address)
110{
111 if (NULL == address)
112 return NULL;
113 return GNUNET_HELLO_address_allocate (&address->peer,
114 address->transport_name,
115 address->address,
116 address->address_length,
117 address->local_info);
118}
119
120
121/**
122 * Compare two addresses. Does NOT compare the peer identity,
123 * that is assumed already to match!
124 *
125 * @param a1 first address
126 * @param a2 second address
127 * @return 0 if the addresses are equal, -1 if a1<a2, 1 if a1>a2.
128 */
129int
130GNUNET_HELLO_address_cmp (const struct GNUNET_HELLO_Address *a1,
131 const struct GNUNET_HELLO_Address *a2)
132{
133 int ret;
134
135 if ((NULL == a1) &&
136 (NULL == a2))
137 return 0;
138 if (NULL == a1)
139 return 1;
140 if (NULL == a2)
141 return -1;
142 ret = strcmp (a1->transport_name, a2->transport_name);
143 if (0 != ret)
144 return ret;
145 if (a1->local_info != a2->local_info)
146 return (((int) a1->local_info) < ((int) a2->local_info)) ? -1 : 1;
147 if (a1->address_length < a2->address_length)
148 return -1;
149 if (a1->address_length > a2->address_length)
150 return 1;
151 return memcmp (a1->address,
152 a2->address,
153 a1->address_length);
154}
155
156
157/* end of address.c */
diff --git a/src/hello/gnunet-hello.c b/src/hello/gnunet-hello.c
deleted file mode 100644
index 1f110ac18..000000000
--- a/src/hello/gnunet-hello.c
+++ /dev/null
@@ -1,215 +0,0 @@
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
29/**
30 * Closure for #add_to_buf().
31 */
32struct AddContext
33{
34 /**
35 * Where to add.
36 */
37 char *buf;
38
39 /**
40 * Maximum number of bytes left
41 */
42 size_t max;
43
44 /**
45 * Number of bytes added so far.
46 */
47 size_t ret;
48};
49
50static int address_count;
51
52
53/**
54 * Add the given address with infinite expiration to the buffer.
55 *
56 * @param cls closure
57 * @param address address to add
58 * @param expiration old expiration
59 * @return #GNUNET_OK keep iterating
60 */
61static int
62add_to_buf (void *cls,
63 const struct GNUNET_HELLO_Address *address,
64 struct GNUNET_TIME_Absolute expiration)
65{
66 struct AddContext *ac = cls;
67 size_t ret;
68
69 ret = GNUNET_HELLO_add_address (address,
70 GNUNET_TIME_UNIT_FOREVER_ABS,
71 ac->buf,
72 ac->max);
73 ac->buf += ret;
74 ac->max -= ret;
75 ac->ret += ret;
76 address_count++;
77 return GNUNET_OK;
78}
79
80
81/**
82 * Add addresses from the address list to the HELLO.
83 *
84 * @param cls the HELLO with the addresses to add
85 * @param max maximum space available
86 * @param buf where to add the addresses
87 * @return number of bytes added, 0 to terminate
88 */
89static ssize_t
90add_from_hello (void *cls, size_t max, void *buf)
91{
92 struct GNUNET_HELLO_Message **orig = cls;
93 struct AddContext ac;
94
95 if (NULL == *orig)
96 return GNUNET_SYSERR; /* already done */
97 ac.buf = buf;
98 ac.max = max;
99 ac.ret = 0;
100 GNUNET_assert (
101 NULL ==
102 GNUNET_HELLO_iterate_addresses (*orig, GNUNET_NO, &add_to_buf, &ac));
103 *orig = NULL;
104 return ac.ret;
105}
106
107
108int
109main (int argc, char *argv[])
110{
111 struct GNUNET_DISK_FileHandle *fh;
112 struct GNUNET_HELLO_Message *orig;
113 struct GNUNET_HELLO_Message *result;
114 struct GNUNET_PeerIdentity pid;
115 uint64_t fsize;
116
117 address_count = 0;
118
119 GNUNET_log_setup ("gnunet-hello", "INFO", NULL);
120 if (argc != 2)
121 {
122 fprintf (stderr, "%s", _ ("Call with name of HELLO file to modify.\n"));
123 return 1;
124 }
125 if (GNUNET_OK !=
126 GNUNET_DISK_file_size (argv[1], &fsize, GNUNET_YES, GNUNET_YES))
127 {
128 fprintf (stderr,
129 _ ("Error accessing file `%s': %s\n"),
130 argv[1],
131 strerror (errno));
132 return 1;
133 }
134 if (fsize > 65536)
135 {
136 fprintf (stderr, _ ("File `%s' is too big to be a HELLO\n"), argv[1]);
137 return 1;
138 }
139 if (fsize < sizeof(struct GNUNET_MessageHeader))
140 {
141 fprintf (stderr, _ ("File `%s' is too small to be a HELLO\n"), argv[1]);
142 return 1;
143 }
144 fh = GNUNET_DISK_file_open (argv[1],
145 GNUNET_DISK_OPEN_READ,
146 GNUNET_DISK_PERM_USER_READ);
147 if (NULL == fh)
148 {
149 fprintf (stderr,
150 _ ("Error opening file `%s': %s\n"),
151 argv[1],
152 strerror (errno));
153 return 1;
154 }
155 {
156 char buf[fsize] GNUNET_ALIGN;
157
158 GNUNET_assert (fsize == GNUNET_DISK_file_read (fh, buf, fsize));
159 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh));
160 orig = (struct GNUNET_HELLO_Message *) buf;
161 if ((fsize < GNUNET_HELLO_size (orig)) ||
162 (GNUNET_OK != GNUNET_HELLO_get_id (orig, &pid)))
163 {
164 fprintf (stderr,
165 _ ("Did not find well-formed HELLO in file `%s'\n"),
166 argv[1]);
167 return 1;
168 }
169 {
170 char *pids;
171
172 pids = GNUNET_CRYPTO_eddsa_public_key_to_string (&pid.public_key);
173 fprintf (stdout, "Processing HELLO for peer `%s'\n", pids);
174 GNUNET_free (pids);
175 }
176 result = GNUNET_HELLO_create (&pid.public_key,
177 &add_from_hello,
178 &orig,
179 GNUNET_HELLO_is_friend_only (orig));
180 GNUNET_assert (NULL != result);
181 fh =
182 GNUNET_DISK_file_open (argv[1],
183 GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_TRUNCATE,
184 GNUNET_DISK_PERM_USER_READ
185 | GNUNET_DISK_PERM_USER_WRITE);
186 if (NULL == fh)
187 {
188 fprintf (stderr,
189 _ ("Error opening file `%s': %s\n"),
190 argv[1],
191 strerror (errno));
192 GNUNET_free (result);
193 return 1;
194 }
195 fsize = GNUNET_HELLO_size (result);
196 if (fsize != GNUNET_DISK_file_write (fh, result, fsize))
197 {
198 fprintf (stderr,
199 _ ("Error writing HELLO to file `%s': %s\n"),
200 argv[1],
201 strerror (errno));
202 (void) GNUNET_DISK_file_close (fh);
203 return 1;
204 }
205 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh));
206 }
207 fprintf (stderr,
208 _ ("Modified %u addresses, wrote %u bytes\n"),
209 address_count,
210 (unsigned int) fsize);
211 return 0;
212}
213
214
215/* end of gnunet-hello.c */
diff --git a/src/hello/hello-ng.c b/src/hello/hello-ng.c
deleted file mode 100644
index 96856a692..000000000
--- a/src/hello/hello-ng.c
+++ /dev/null
@@ -1,197 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2018 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/**
22 * @file hello/hello-ng.c
23 * @brief helper library for handling HELLOs
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_signatures.h"
28#include "gnunet_hello_lib.h"
29#include "gnunet_protocols.h"
30#include "gnunet_util_lib.h"
31#include "gnunet_ats_service.h"
32
33GNUNET_NETWORK_STRUCT_BEGIN
34/**
35 * Binary block we sign when we sign an address.
36 */
37struct SignedAddress
38{
39 /**
40 * Purpose must be #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS
41 */
42 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
43
44 /**
45 * When was the address generated.
46 */
47 struct GNUNET_TIME_AbsoluteNBO mono_time;
48
49 /**
50 * Hash of the address.
51 */
52 struct GNUNET_HashCode addr_hash GNUNET_PACKED;
53};
54GNUNET_NETWORK_STRUCT_END
55
56/**
57 * Build address record by signing raw information with private key.
58 *
59 * @param address text address at @a communicator to sign
60 * @param nt network type of @a address
61 * @param mono_time monotonic time at which @a address was valid
62 * @param private_key signing key to use
63 * @param result[out] where to write address record (allocated)
64 * @param result_size[out] set to size of @a result
65 */
66void
67GNUNET_HELLO_sign_address (
68 const char *address,
69 enum GNUNET_NetworkType nt,
70 struct GNUNET_TIME_Absolute mono_time,
71 const struct GNUNET_CRYPTO_EddsaPrivateKey *private_key,
72 void **result,
73 size_t *result_size)
74{
75 struct SignedAddress sa;
76 struct GNUNET_CRYPTO_EddsaSignature sig;
77 char *sig_str;
78
79 sa.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS);
80 sa.purpose.size = htonl (sizeof(sa));
81 sa.mono_time = GNUNET_TIME_absolute_hton (mono_time);
82 GNUNET_CRYPTO_hash (address, strlen (address), &sa.addr_hash);
83 GNUNET_CRYPTO_eddsa_sign (private_key, &sa, &sig);
84 sig_str = NULL;
85 (void) GNUNET_STRINGS_base64_encode (&sig, sizeof(sig), &sig_str);
86 *result_size =
87 1 + GNUNET_asprintf ((char **) result,
88 "%s;%llu;%u;%s",
89 sig_str,
90 (unsigned long long) mono_time.abs_value_us,
91 (unsigned int) nt,
92 address);
93 GNUNET_free (sig_str);
94}
95
96
97/**
98 * Check signature and extract address record.
99 *
100 * @param raw raw signed address
101 * @param raw_size size of @a raw
102 * @param pid public key to use for signature verification
103 * @param nt[out] set to network type
104 * @param mono_time[out] when was the address generated
105 * @return NULL on error, otherwise the address
106 */
107char *
108GNUNET_HELLO_extract_address (const void *raw,
109 size_t raw_size,
110 const struct GNUNET_PeerIdentity *pid,
111 enum GNUNET_NetworkType *nt,
112 struct GNUNET_TIME_Absolute *mono_time)
113{
114 const struct GNUNET_CRYPTO_EddsaPublicKey *public_key = &pid->public_key;
115 const char *raws = raw;
116 unsigned long long raw_us = 0;
117 unsigned int raw_nt = 0;
118 const char *sc;
119 const char *sc2;
120 const char *sc3;
121 const char *raw_addr;
122 char *data = NULL;
123 struct GNUNET_TIME_Absolute raw_mono_time;
124 struct SignedAddress sa;
125 struct GNUNET_CRYPTO_EddsaSignature *sig;
126
127 if ('\0' != raws[raw_size-1])
128 {
129 GNUNET_break_op (0);
130 return NULL;
131 }
132 if (NULL == (sc = strchr (raws, ';')))
133 {
134 GNUNET_break_op (0);
135 return NULL;
136 }
137 if (NULL == (sc2 = strchr (sc + 1, ';')))
138 {
139 GNUNET_break_op (0);
140 return NULL;
141 }
142 if (NULL == (sc3 = strchr (sc2 + 1, ';')))
143 {
144 GNUNET_break_op (0);
145 return NULL;
146 }
147 if (2 != sscanf (sc + 1, "%llu;%u;%*s", &raw_us, &raw_nt))
148 {
149 GNUNET_break_op (0);
150 return NULL;
151 }
152 raw_addr = sc3 + 1;
153 raw_mono_time.abs_value_us = raw_us;
154 if (sizeof(struct GNUNET_CRYPTO_EddsaSignature) !=
155 GNUNET_STRINGS_base64_decode (raws, sc - raws, (void **) &data))
156 {
157 GNUNET_break_op (0);
158 GNUNET_free (data);
159 return NULL;
160 }
161 sig = (struct GNUNET_CRYPTO_EddsaSignature*) data;
162 sa.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS);
163 sa.purpose.size = htonl (sizeof(sa));
164 sa.mono_time = GNUNET_TIME_absolute_hton (raw_mono_time);
165 GNUNET_CRYPTO_hash (raw_addr, strlen (raw_addr), &sa.addr_hash);
166 if (GNUNET_YES !=
167 GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS,
168 &sa,
169 sig,
170 public_key))
171 {
172 GNUNET_break_op (0);
173 return NULL;
174 }
175 *mono_time = raw_mono_time;
176 *nt = raw_nt;
177 return GNUNET_strdup (raw_addr);
178}
179
180
181/**
182 * Given an address as a string, extract the prefix that identifies
183 * the communicator offering transmissions to that address.
184 *
185 * @param address a peer's address
186 * @return NULL if the address is mal-formed, otherwise the prefix
187 */
188char *
189GNUNET_HELLO_address_to_prefix (const char *address)
190{
191 const char *dash;
192
193 dash = strchr (address, '-');
194 if (NULL == dash)
195 return NULL;
196 return GNUNET_strndup (address, dash - address);
197}
diff --git a/src/hello/hello.c b/src/hello/hello.c
deleted file mode 100644
index 12b576ceb..000000000
--- a/src/hello/hello.c
+++ /dev/null
@@ -1,1271 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2015 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/**
22 * @file hello/hello.c
23 * @brief helper library for handling HELLOs
24 * @author Christian Grothoff
25 * @author Matthias Wachs
26 */
27#include "platform.h"
28#include "gnunet_hello_lib.h"
29#include "gnunet_protocols.h"
30#include "gnunet_util_lib.h"
31#include "gnunet_transport_plugin.h"
32
33/**
34 * Context used for building our own URI.
35 */
36struct GNUNET_HELLO_ComposeUriContext
37{
38 /**
39 * Final URI.
40 */
41 char *uri;
42
43 /**
44 * Function for finding transport plugins by name.
45 */
46 GNUNET_HELLO_TransportPluginsFind plugins_find;
47};
48
49
50/**
51 * Context for #add_address_to_hello().
52 */
53struct GNUNET_HELLO_ParseUriContext
54{
55 /**
56 * Position in the URI with the next address to parse.
57 */
58 const char *pos;
59
60 /**
61 * Set to #GNUNET_SYSERR to indicate parse errors.
62 */
63 int ret;
64
65 /**
66 * Counter
67 */
68 unsigned int counter_total;
69
70 /**
71 * Counter skipped addresses
72 */
73 unsigned int counter_added;
74
75 /**
76 * Function for finding transport plugins by name.
77 */
78 GNUNET_HELLO_TransportPluginsFind plugins_find;
79};
80
81
82/**
83 * Return HELLO type
84 *
85 * @param h HELLO Message to test
86 * @return #GNUNET_YES for friend-only or #GNUNET_NO otherwise
87 */
88int
89GNUNET_HELLO_is_friend_only (const struct GNUNET_HELLO_Message *h)
90{
91 if (GNUNET_YES == ntohl (h->friend_only))
92 return GNUNET_YES;
93 return GNUNET_NO;
94}
95
96
97/**
98 * Copy the given address information into
99 * the given buffer using the format of HELLOs.
100 *
101 * @param address the address
102 * @param expiration expiration for the @a address
103 * @param target where to copy the @a address
104 * @param max maximum number of bytes to copy to target
105 * @return number of bytes copied, 0 if
106 * the target buffer was not big enough.
107 */
108size_t
109GNUNET_HELLO_add_address (const struct GNUNET_HELLO_Address *address,
110 struct GNUNET_TIME_Absolute expiration,
111 char *target,
112 size_t max)
113{
114 uint16_t alen;
115 size_t slen;
116 struct GNUNET_TIME_AbsoluteNBO exp;
117
118 slen = strlen (address->transport_name) + 1;
119 if (slen + sizeof(uint16_t) + sizeof(struct GNUNET_TIME_AbsoluteNBO)
120 + address->address_length > max)
121 return 0;
122 exp = GNUNET_TIME_absolute_hton (expiration);
123 alen = htons ((uint16_t) address->address_length);
124 GNUNET_memcpy (target, address->transport_name, slen);
125 GNUNET_memcpy (&target[slen], &alen, sizeof(uint16_t));
126 slen += sizeof(uint16_t);
127 GNUNET_memcpy (&target[slen], &exp, sizeof(struct GNUNET_TIME_AbsoluteNBO));
128 slen += sizeof(struct GNUNET_TIME_AbsoluteNBO);
129 GNUNET_memcpy (&target[slen], address->address, address->address_length);
130 slen += address->address_length;
131 return slen;
132}
133
134
135/**
136 * Get the size of an address entry in a HELLO message.
137 *
138 * @param buf pointer to the start of the address entry
139 * @param max maximum size of the entry (end of @a buf)
140 * @param ralen set to the address length
141 * @return size of the entry, or 0 if @a max is not large enough
142 */
143static size_t
144get_hello_address_size (const char *buf,
145 size_t max,
146 uint16_t *ralen)
147{
148 const char *pos;
149 uint16_t alen;
150 size_t left;
151 size_t slen;
152
153 left = max;
154 pos = buf;
155 slen = 1;
156 while ((left > 0) && ('\0' != *pos))
157 {
158 left--;
159 pos++;
160 slen++;
161 }
162 if (0 == left)
163 {
164 /* 0-termination not found */
165 GNUNET_break_op (0);
166 return 0;
167 }
168 pos++;
169 if (left < sizeof(uint16_t) + sizeof(struct GNUNET_TIME_AbsoluteNBO))
170 {
171 /* not enough space for addrlen */
172 GNUNET_break_op (0);
173 return 0;
174 }
175 GNUNET_memcpy (&alen, pos, sizeof(uint16_t));
176 alen = ntohs (alen);
177 *ralen = alen;
178 slen += alen + sizeof(uint16_t) + sizeof(struct GNUNET_TIME_AbsoluteNBO);
179 if (max < slen)
180 {
181 /* not enough space for addr */
182 GNUNET_break_op (0);
183 return 0;
184 }
185 return slen;
186}
187
188
189/**
190 * Construct a HELLO message given the public key,
191 * expiration time and an iterator that spews the
192 * transport addresses.
193 *
194 * If friend only is set to #GNUNET_YES we create a FRIEND_HELLO which
195 * will not be gossiped to other peers.
196 *
197 * @param public_key public key to include in the HELLO
198 * @param addrgen callback to invoke to get addresses
199 * @param addrgen_cls closure for @a addrgen
200 * @param friend_only should the returned HELLO be only visible to friends?
201 * @return the hello message
202 */
203struct GNUNET_HELLO_Message *
204GNUNET_HELLO_create (const struct GNUNET_CRYPTO_EddsaPublicKey *public_key,
205 GNUNET_HELLO_GenerateAddressListCallback addrgen,
206 void *addrgen_cls,
207 int friend_only)
208{
209 char buffer[GNUNET_MAX_MESSAGE_SIZE - 1 - 256
210 - sizeof(struct GNUNET_HELLO_Message)];
211 size_t max;
212 size_t used;
213 size_t ret;
214 struct GNUNET_HELLO_Message *hello;
215
216 GNUNET_assert (NULL != public_key);
217 GNUNET_assert ((GNUNET_YES == friend_only) ||
218 (GNUNET_NO == friend_only));
219 max = sizeof(buffer);
220 used = 0;
221 if (NULL != addrgen)
222 {
223 while (GNUNET_SYSERR != (ret = addrgen (addrgen_cls,
224 max,
225 &buffer[used])))
226 {
227 max -= ret;
228 used += ret;
229 }
230 }
231 hello = GNUNET_malloc (sizeof(struct GNUNET_HELLO_Message) + used);
232 hello->header.type = htons (GNUNET_MESSAGE_TYPE_HELLO);
233 hello->header.size = htons (sizeof(struct GNUNET_HELLO_Message) + used);
234 hello->friend_only = htonl (friend_only);
235 hello->publicKey = *public_key;
236 GNUNET_memcpy (&hello[1],
237 buffer,
238 used);
239 return hello;
240}
241
242
243/**
244 * Iterate over all of the addresses in the HELLO.
245 *
246 * @param msg HELLO to iterate over
247 * @param return_modified if a modified copy should be returned,
248 * otherwise NULL will be returned
249 * @param it iterator to call on each address
250 * @param it_cls closure for @a it
251 * @return modified HELLO message
252 */
253struct GNUNET_HELLO_Message *
254GNUNET_HELLO_iterate_addresses (const struct GNUNET_HELLO_Message *msg,
255 int return_modified,
256 GNUNET_HELLO_AddressIterator it,
257 void *it_cls)
258{
259 struct GNUNET_HELLO_Address address;
260 uint16_t msize;
261 struct GNUNET_HELLO_Message *ret;
262 const char *inptr;
263 size_t insize;
264 size_t esize;
265 size_t wpos;
266 char *woff;
267 uint16_t alen;
268 struct GNUNET_TIME_AbsoluteNBO expire;
269 int iret;
270
271 msize = GNUNET_HELLO_size (msg);
272 if ((msize < sizeof(struct GNUNET_HELLO_Message)) ||
273 (ntohs (msg->header.type) != GNUNET_MESSAGE_TYPE_HELLO))
274 {
275 GNUNET_break_op (0);
276 return NULL;
277 }
278 ret = NULL;
279 if (return_modified)
280 {
281 ret = GNUNET_malloc (msize);
282 GNUNET_memcpy (ret,
283 msg,
284 msize);
285 }
286 inptr = (const char *) &msg[1];
287 insize = msize - sizeof(struct GNUNET_HELLO_Message);
288 wpos = 0;
289 woff = (NULL != ret) ? (char *) &ret[1] : NULL;
290 address.peer.public_key = msg->publicKey;
291 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
292 "HELLO has %u bytes of address data\n",
293 (unsigned int) insize);
294
295 while (insize > 0)
296 {
297 esize = get_hello_address_size (inptr,
298 insize,
299 &alen);
300 if (0 == esize)
301 {
302 GNUNET_break (0);
303 GNUNET_free (ret);
304 return NULL;
305 }
306 /* need GNUNET_memcpy() due to possibility of misalignment */
307 GNUNET_memcpy (&expire,
308 &inptr[esize - alen - sizeof(struct
309 GNUNET_TIME_AbsoluteNBO)],
310 sizeof(struct GNUNET_TIME_AbsoluteNBO));
311 address.address = &inptr[esize - alen];
312 address.address_length = alen;
313 address.transport_name = inptr;
314 address.local_info = GNUNET_HELLO_ADDRESS_INFO_NONE;
315 iret = it (it_cls,
316 &address,
317 GNUNET_TIME_absolute_ntoh (expire));
318 if (GNUNET_SYSERR == iret)
319 break;
320 if ((GNUNET_OK == iret) &&
321 (NULL != ret))
322 {
323 /* copy address over */
324 GNUNET_memcpy (woff,
325 inptr,
326 esize);
327 woff += esize;
328 wpos += esize;
329 }
330 insize -= esize;
331 inptr += esize;
332 }
333 if (NULL != ret)
334 ret->header.size = ntohs (sizeof(struct GNUNET_HELLO_Message) + wpos);
335 return ret;
336}
337
338
339/**
340 * Closure for #get_match_exp().
341 */
342struct ExpireContext
343{
344 /**
345 * Address we are looking for.
346 */
347 const struct GNUNET_HELLO_Address *address;
348
349 /**
350 * Set to #GNUNET_YES if we found the @e address.
351 */
352 int found;
353
354 /**
355 * Set to the expiration of the match if @e found is #GNUNET_YES.
356 */
357 struct GNUNET_TIME_Absolute expiration;
358};
359
360
361/**
362 * Store the expiration time of an address that matches the template.
363 *
364 * @param cls the `struct ExpireContext`
365 * @param address address to match against the template
366 * @param expiration expiration time of @a address, to store in @a cls
367 * @return #GNUNET_SYSERR if we found a matching address, #GNUNET_OK otherwise
368 */
369static int
370get_match_exp (void *cls,
371 const struct GNUNET_HELLO_Address *address,
372 struct GNUNET_TIME_Absolute expiration)
373{
374 struct ExpireContext *ec = cls;
375
376 if (0 != GNUNET_HELLO_address_cmp (address,
377 ec->address))
378 return GNUNET_OK;
379 ec->found = GNUNET_YES;
380 ec->expiration = expiration;
381 return GNUNET_SYSERR; /* done here */
382}
383
384
385/**
386 * Context for a #GNUNET_HELLO_Merge operation.
387 */
388struct MergeContext
389{
390 /**
391 * First HELLO we are merging.
392 */
393 const struct GNUNET_HELLO_Message *h1;
394
395 /**
396 * Second HELLO we are merging.
397 */
398 const struct GNUNET_HELLO_Message *h2;
399
400 /**
401 * Either @e h1 or @e h2, used when copying
402 * to compare against (so we only copy the
403 * most recent entry).
404 */
405 const struct GNUNET_HELLO_Message *other;
406
407 /**
408 * Buffer where we copy to.
409 */
410 char *buf;
411
412 /**
413 * Number of bytes allocated in @e buf
414 */
415 size_t max;
416
417 /**
418 * Current (write) offset in @e buf.
419 */
420 size_t ret;
421
422 /**
423 * Should we copy addresses with an identical value
424 * and expiration time in @e other, or do we only
425 * copy addresses with strictly later expiration times?
426 */
427 int take_equal;
428};
429
430
431/**
432 * Append the address @a address to the buffer from
433 * the merge context IF it is more recent than equivalent
434 * addresses in `other`.
435 *
436 * @param cls the `struct MergeContext`
437 * @param address the HELLO address we might copy
438 * @param expiration expiration time for @a address
439 * @return always #GNUNET_OK
440 */
441static int
442copy_latest (void *cls,
443 const struct GNUNET_HELLO_Address *address,
444 struct GNUNET_TIME_Absolute expiration)
445{
446 struct MergeContext *mc = cls;
447 struct ExpireContext ec;
448
449 ec.address = address;
450 ec.found = GNUNET_NO;
451 /* check if address exists in other */
452 GNUNET_HELLO_iterate_addresses (mc->other,
453 GNUNET_NO,
454 &get_match_exp,
455 &ec);
456 if ((GNUNET_NO == ec.found) ||
457 (ec.expiration.abs_value_us < expiration.abs_value_us) ||
458 ((ec.expiration.abs_value_us == expiration.abs_value_us) &&
459 (GNUNET_YES == mc->take_equal)))
460 {
461 /* copy address to buffer */
462 mc->ret +=
463 GNUNET_HELLO_add_address (address,
464 expiration,
465 &mc->buf[mc->ret],
466 mc->max - mc->ret);
467 }
468 return GNUNET_OK;
469}
470
471
472/**
473 * Function called to build the HELLO during
474 * #GNUNET_HELLO_merge() by merging addresses from
475 * two original HELLOs.
476 *
477 * @param cls the `struct MergeContext`
478 * @param max number of bytes we can write at most in @a buf
479 * @param buf where to copy the addresses
480 * @return #GNUNET_SYSERR to end iteration, otherwise number of bytes written to @a buf
481 */
482static ssize_t
483merge_addr (void *cls,
484 size_t max,
485 void *buf)
486{
487 struct MergeContext *mc = cls;
488
489 if (NULL == mc->h1)
490 return GNUNET_SYSERR; /* Stop iteration */
491 mc->ret = 0;
492 mc->max = max;
493 mc->buf = buf;
494 mc->take_equal = GNUNET_NO;
495 mc->other = mc->h2;
496 /* copy addresses from h1, if strictly larger expiration than h2 */
497 GNUNET_HELLO_iterate_addresses (mc->h1,
498 GNUNET_NO,
499 &copy_latest,
500 mc);
501 mc->take_equal = GNUNET_YES;
502 mc->other = mc->h1;
503 /* copy addresses from h2, if larger or equal expiration than h1 */
504 GNUNET_HELLO_iterate_addresses (mc->h2,
505 GNUNET_NO,
506 &copy_latest,
507 mc);
508 /* set marker to stop iteration */
509 mc->h1 = NULL;
510 return mc->ret;
511}
512
513
514/**
515 * Construct a HELLO message by merging the
516 * addresses in two existing HELLOs (which
517 * must be for the same peer).
518 *
519 * @param h1 first HELLO message
520 * @param h2 the second HELLO message
521 * @return the combined HELLO message
522 */
523struct GNUNET_HELLO_Message *
524GNUNET_HELLO_merge (const struct GNUNET_HELLO_Message *h1,
525 const struct GNUNET_HELLO_Message *h2)
526{
527 struct MergeContext mc = { h1, h2, NULL, NULL, 0, 0, 0 };
528 int friend_only;
529
530 if (h1->friend_only != h2->friend_only)
531 friend_only = GNUNET_YES; /* One of the HELLOs is friend only */
532 else
533 friend_only = ntohl (h1->friend_only); /* Both HELLO's have the same type */
534
535 return GNUNET_HELLO_create (&h1->publicKey,
536 &merge_addr,
537 &mc,
538 friend_only);
539}
540
541
542/**
543 * Context used in #GNUNET_HELLO_iterate_new_addresses() to
544 * figure out which addresses are in fact 'new'.
545 */
546struct DeltaContext
547{
548 /**
549 * We should ignore addresses that expire before this time.
550 */
551 struct GNUNET_TIME_Absolute expiration_limit;
552
553 /**
554 * Function to call on addresses that are indeed new.
555 */
556 GNUNET_HELLO_AddressIterator it;
557
558 /**
559 * Closure for @e it.
560 */
561 void *it_cls;
562
563 /**
564 * HELLO with known addresses, addresses in this HELLO
565 * we must always ignore.
566 */
567 const struct GNUNET_HELLO_Message *old_hello;
568};
569
570
571/**
572 * Check if the given address is 'new', and if so, call
573 * the iterator. Compares the existing address against
574 * addresses in the context's `old_hello` and calls the
575 * iterator on those that are new (and not expired).
576 *
577 * @param cls the `struct DeltaContext`
578 * @param address an address to check whether it is new
579 * @param expiration expiration time for @a address
580 * @return #GNUNET_YES if the address is ignored, otherwise
581 * whatever the iterator returned.
582 */
583static int
584delta_match (void *cls,
585 const struct GNUNET_HELLO_Address *address,
586 struct GNUNET_TIME_Absolute expiration)
587{
588 struct DeltaContext *dc = cls;
589 int ret;
590 struct ExpireContext ec;
591
592 ec.address = address;
593 ec.found = GNUNET_NO;
594 GNUNET_HELLO_iterate_addresses (dc->old_hello,
595 GNUNET_NO,
596 &get_match_exp,
597 &ec);
598 if ((GNUNET_YES == ec.found) &&
599 ((ec.expiration.abs_value_us > expiration.abs_value_us) ||
600 (ec.expiration.abs_value_us >= dc->expiration_limit.abs_value_us)))
601 return GNUNET_YES; /* skip: found and boring */
602 ret = dc->it (dc->it_cls,
603 address,
604 expiration);
605 return ret;
606}
607
608
609/**
610 * Iterate over addresses in @a new_hello that are NOT already present
611 * in @a old_hello. Note that if the address is present in @a old_hello
612 * but the expiration time in @a new_hello is more recent, the iterator
613 * is also called.
614 *
615 * @param new_hello a HELLO message
616 * @param old_hello a HELLO message
617 * @param expiration_limit ignore addresses in @a old_hello
618 * that expired before the given time stamp
619 * @param it iterator to call on each address
620 * @param it_cls closure for @a it
621 */
622void
623GNUNET_HELLO_iterate_new_addresses (const struct
624 GNUNET_HELLO_Message *new_hello,
625 const struct
626 GNUNET_HELLO_Message *old_hello,
627 struct GNUNET_TIME_Absolute
628 expiration_limit,
629 GNUNET_HELLO_AddressIterator it,
630 void *it_cls)
631{
632 struct DeltaContext dc;
633
634 dc.expiration_limit = expiration_limit;
635 dc.it = it;
636 dc.it_cls = it_cls;
637 dc.old_hello = old_hello;
638 GNUNET_assert (NULL ==
639 GNUNET_HELLO_iterate_addresses (new_hello,
640 GNUNET_NO,
641 &delta_match,
642 &dc));
643}
644
645
646/**
647 * Return the size of the given HELLO message.
648 * @param hello to inspect
649 * @return the size, 0 if HELLO is invalid
650 */
651uint16_t
652GNUNET_HELLO_size (const struct GNUNET_HELLO_Message *hello)
653{
654 uint16_t ret = ntohs (hello->header.size);
655
656 if ((ret < sizeof(struct GNUNET_HELLO_Message)) ||
657 (ntohs (hello->header.type) != GNUNET_MESSAGE_TYPE_HELLO))
658 return 0;
659 return ret;
660}
661
662
663/**
664 * Get the peer identity from a HELLO message.
665 *
666 * @param hello the hello message
667 * @param peer where to store the peer's identity
668 * @return #GNUNET_SYSERR if the HELLO was malformed
669 */
670int
671GNUNET_HELLO_get_id (const struct GNUNET_HELLO_Message *hello,
672 struct GNUNET_PeerIdentity *peer)
673{
674 uint16_t ret = ntohs (hello->header.size);
675
676 if ((ret < sizeof(struct GNUNET_HELLO_Message)) ||
677 (ntohs (hello->header.type) != GNUNET_MESSAGE_TYPE_HELLO))
678 return GNUNET_SYSERR;
679 peer->public_key = hello->publicKey;
680 return GNUNET_OK;
681}
682
683
684/**
685 * Get the header from a HELLO message, used so other code
686 * can correctly send HELLO messages.
687 *
688 * @param hello the hello message
689 *
690 * @return header or NULL if the HELLO was malformed
691 */
692struct GNUNET_MessageHeader *
693GNUNET_HELLO_get_header (struct GNUNET_HELLO_Message *hello)
694{
695 uint16_t ret = ntohs (hello->header.size);
696
697 if ((ret < sizeof(struct GNUNET_HELLO_Message)) ||
698 (ntohs (hello->header.type) != GNUNET_MESSAGE_TYPE_HELLO))
699 return NULL;
700
701 return &hello->header;
702}
703
704
705/**
706 * Context used for comparing HELLOs in #GNUNET_HELLO_equals().
707 */
708struct EqualsContext
709{
710 /**
711 * Addresses that expired before this date are ignored for
712 * the comparison.
713 */
714 struct GNUNET_TIME_Absolute expiration_limit;
715
716 /**
717 * Earliest expiration time for which we found a match
718 * with a difference in expiration times.
719 * At this time, the two HELLOs may start to diverge.
720 */
721 struct GNUNET_TIME_Absolute result;
722
723 /**
724 * HELLO message to compare against. (First set to the second
725 * HELLO, then set to the first HELLO.)
726 */
727 const struct GNUNET_HELLO_Message *ref;
728
729 /**
730 * Address we are currently looking for.
731 */
732 const struct GNUNET_HELLO_Address *address;
733
734 /**
735 * Expiration time of @e address.
736 */
737 struct GNUNET_TIME_Absolute expiration;
738
739 /**
740 * Did we find the address we were looking for?
741 */
742 int found;
743};
744
745
746/**
747 * Check if the given address matches the address we are currently
748 * looking for. If so, sets `found` to #GNUNET_YES and, if the
749 * expiration times for the two addresses differ, updates `result` to
750 * the minimum of our @a expiration and the existing value
751 *
752 * @param cls the `struct EqualsContext`
753 * @param address address from the reference HELLO
754 * @param expiration expiration time for @a address
755 * @return #GNUNET_YES if the address is expired or does not match
756 * #GNUNET_SYSERR if the address does match.
757 */
758static int
759find_other_matching (void *cls,
760 const struct GNUNET_HELLO_Address *address,
761 struct GNUNET_TIME_Absolute expiration)
762{
763 struct EqualsContext *ec = cls;
764
765 if (expiration.abs_value_us < ec->expiration_limit.abs_value_us)
766 return GNUNET_YES;
767 if (0 == GNUNET_HELLO_address_cmp (address, ec->address))
768 {
769 ec->found = GNUNET_YES;
770 if (expiration.abs_value_us < ec->expiration.abs_value_us)
771 ec->result = GNUNET_TIME_absolute_min (expiration,
772 ec->result);
773 return GNUNET_SYSERR;
774 }
775 return GNUNET_YES;
776}
777
778
779/**
780 * Helper function for #GNUNET_HELLO_equals(). Checks
781 * if the given @a address exists also in the other HELLO;
782 * if not, the result time is set to zero and the iteration
783 * is aborted.
784 *
785 * @param cls the `struct EqualsContext`
786 * @param address address to locate
787 * @param expiration expiration time of the current address
788 * @return #GNUNET_OK if the address exists or is expired,
789 * #GNUNET_SYSERR if it was not found
790 */
791static int
792find_matching (void *cls,
793 const struct GNUNET_HELLO_Address *address,
794 struct GNUNET_TIME_Absolute expiration)
795{
796 struct EqualsContext *ec = cls;
797
798 if (expiration.abs_value_us < ec->expiration_limit.abs_value_us)
799 return GNUNET_OK; /* expired, we don't care */
800 ec->address = address;
801 ec->expiration = expiration;
802 ec->found = GNUNET_NO;
803 GNUNET_HELLO_iterate_addresses (ec->ref,
804 GNUNET_NO,
805 &find_other_matching,
806 ec);
807 if (GNUNET_NO == ec->found)
808 {
809 /* not found, we differ *now* */
810 ec->result = GNUNET_TIME_UNIT_ZERO_ABS;
811 return GNUNET_SYSERR;
812 }
813 return GNUNET_OK;
814}
815
816
817/**
818 * Test if two HELLO messages contain the same addresses.
819 * If they only differ in expiration time, the lowest
820 * expiration time larger than @a now where they differ
821 * is returned.
822 *
823 * @param h1 first HELLO message
824 * @param h2 the second HELLO message
825 * @param now time to use for deciding which addresses have
826 * expired and should not be considered at all
827 * @return absolute time forever if the two HELLOs are
828 * totally identical; smallest timestamp >= @a now if
829 * they only differ in timestamps;
830 * zero if the some addresses with expirations >= @a now
831 * do not match at all
832 */
833struct GNUNET_TIME_Absolute
834GNUNET_HELLO_equals (const struct GNUNET_HELLO_Message *h1,
835 const struct GNUNET_HELLO_Message *h2,
836 struct GNUNET_TIME_Absolute now)
837{
838 struct EqualsContext ec;
839
840 if (h1->header.type != h2->header.type)
841 return GNUNET_TIME_UNIT_ZERO_ABS;
842 if (0 !=
843 GNUNET_memcmp (&h1->publicKey,
844 &h2->publicKey))
845 return GNUNET_TIME_UNIT_ZERO_ABS;
846 ec.expiration_limit = now;
847 ec.result = GNUNET_TIME_UNIT_FOREVER_ABS;
848 ec.ref = h2;
849 GNUNET_HELLO_iterate_addresses (h1,
850 GNUNET_NO,
851 &find_matching,
852 &ec);
853 if (ec.result.abs_value_us == GNUNET_TIME_UNIT_ZERO.rel_value_us)
854 return ec.result;
855 ec.ref = h1;
856 GNUNET_HELLO_iterate_addresses (h2,
857 GNUNET_NO,
858 &find_matching,
859 &ec);
860 return ec.result;
861}
862
863
864/**
865 * Iterator to find the time when the last address will expire.
866 * Updates the maximum value stored in @a cls.
867 *
868 * @param cls where to store the max, a `struct GNUNET_TIME_Absolute`
869 * @param address an address (ignored)
870 * @param expiration expiration time for @a address
871 * @return #GNUNET_OK (always)
872 */
873static int
874find_max_expire (void *cls,
875 const struct GNUNET_HELLO_Address *address,
876 struct GNUNET_TIME_Absolute expiration)
877{
878 struct GNUNET_TIME_Absolute *max = cls;
879
880 *max = GNUNET_TIME_absolute_max (*max, expiration);
881 return GNUNET_OK;
882}
883
884
885/**
886 * When does the last address in the given HELLO expire?
887 *
888 * @param msg HELLO to inspect
889 * @return time the last address expires, 0 if there are no addresses in the HELLO
890 */
891struct GNUNET_TIME_Absolute
892GNUNET_HELLO_get_last_expiration (const struct GNUNET_HELLO_Message *msg)
893{
894 struct GNUNET_TIME_Absolute ret;
895
896 ret = GNUNET_TIME_UNIT_ZERO_ABS;
897 GNUNET_HELLO_iterate_addresses (msg,
898 GNUNET_NO,
899 &find_max_expire,
900 &ret);
901 return ret;
902}
903
904
905/**
906 * GNUnet URIs are of the general form "gnunet://MODULE/IDENTIFIER".
907 * The specific structure of "IDENTIFIER" depends on the module and
908 * maybe differentiated into additional subcategories if applicable.
909 * This module only deals with hello identifiers (MODULE = "hello").
910 * <p>
911 *
912 * The concrete URI format is:
913 *
914 * "gnunet://hello/PEER[+YYYYMMDDHHMMSS+<TYPE>+<ADDRESS>]...".
915 * These URIs can be used to add a peer record to peerinfo service.
916 * PEER is the string representation of peer's public key.
917 * YYYYMMDDHHMMSS is the expiration date.
918 * TYPE is a transport type.
919 * ADDRESS is the address, its format depends upon the transport type.
920 * The concrete transport types and corresponding address formats are:
921 *
922 * <ul><li>
923 *
924 * <TCP|UDP>!IPADDRESS
925 * IPVDDRESS is either IPV4 .-delimited address in form of XXX.XXX.XXX.XXX:PPPPP
926 * or IPV6 :-delimited address with '[' and ']' (according to RFC2732):
927 * [XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX]:PPPPP
928 * PPPPP is the port number. May be 0.
929 *
930 * </li><li>
931 *
932 * [add SMTP, HTTP and other addresses here]
933 *
934 * </li></ul>
935 *
936 * The encoding for hexadecimal values is defined in the crypto_hash.c
937 * module in the gnunetutil library and discussed there.
938 *
939 * Examples:
940 *
941 * gnunet://hello/V8XXK9GAN5ZJFRFQP8MQX3D83BZTSBQVHKWWD0JPE63Z821906EG+20120302010059+TCP+192.168.0.1:2086+TCP+64.23.8.174:0
942 * gnunet://hello/V8XXK9GAN5ZJFRFQP8MQX3D83BZTSBQVHKWWD0JPE63Z821906EG+20120302010059+TCP+[2001:db8:85a3:8d3:1319:8a2e:370:7348]:2086
943 *
944 * <p>
945 */
946
947
948/**
949 * Function that is called on each address of this peer.
950 * Expands the corresponding URI string.
951 *
952 * @param cls the `struct GNUNET_HELLO_ComposeUriContext`
953 * @param address address to add
954 * @param expiration expiration time for the address
955 * @return #GNUNET_OK (continue iteration).
956 */
957static int
958add_address_to_uri (void *cls,
959 const struct GNUNET_HELLO_Address *address,
960 struct GNUNET_TIME_Absolute expiration)
961{
962 struct GNUNET_HELLO_ComposeUriContext *ctx = cls;
963 struct GNUNET_TRANSPORT_PluginFunctions *papi;
964 const char *addr;
965 char *ret;
966 char *addr_dup;
967 char *pos;
968 char tbuf[16] = "";
969 char *client_str = "_client";
970 struct tm *t;
971 time_t seconds;
972
973 papi = ctx->plugins_find (address->transport_name);
974 if (NULL == papi)
975 {
976 /* Not an error - we might just not have the right plugin. */
977 return GNUNET_OK;
978 }
979 if (NULL == papi->address_to_string)
980 {
981 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
982 "URI conversion not implemented for plugin `%s'\n",
983 address->transport_name);
984 return GNUNET_OK;
985 }
986 addr = papi->address_to_string (papi->cls,
987 address->address,
988 address->address_length);
989 if ((NULL == addr) ||
990 (0 == strlen (addr)))
991 return GNUNET_OK;
992
993 addr_dup = GNUNET_strdup (addr);
994 if (NULL != (pos = strstr (addr_dup, "_server")))
995 GNUNET_memcpy (pos,
996 client_str,
997 strlen (client_str)); /* Replace all server addresses with client addresses */
998
999 seconds = expiration.abs_value_us / 1000LL / 1000LL;
1000 t = gmtime (&seconds);
1001
1002 GNUNET_asprintf (&ret,
1003 "%s%c%s%c%s%c%s",
1004 ctx->uri,
1005 GNUNET_HELLO_URI_SEP,
1006 strftime (tbuf,
1007 sizeof(tbuf),
1008 "%Y%m%d%H%M%S",
1009 t) ? tbuf : "0",
1010 GNUNET_HELLO_URI_SEP,
1011 address->transport_name,
1012 GNUNET_HELLO_URI_SEP,
1013 addr_dup);
1014 GNUNET_free (addr_dup);
1015 GNUNET_free (ctx->uri);
1016 ctx->uri = ret;
1017 return GNUNET_OK;
1018}
1019
1020
1021/**
1022 * Compose a hello URI string from a hello message.
1023 *
1024 * @param hello Hello message
1025 * @param plugins_find Function to find transport plugins by name
1026 * @return Hello URI string
1027 */
1028char *
1029GNUNET_HELLO_compose_uri (const struct GNUNET_HELLO_Message *hello,
1030 GNUNET_HELLO_TransportPluginsFind plugins_find)
1031{
1032 struct GNUNET_HELLO_ComposeUriContext ctx;
1033 char *pkey;
1034
1035 ctx.plugins_find = plugins_find;
1036 pkey = GNUNET_CRYPTO_eddsa_public_key_to_string (&hello->publicKey);
1037 GNUNET_asprintf (&ctx.uri,
1038 "%s%s",
1039 (GNUNET_YES == GNUNET_HELLO_is_friend_only (hello))
1040 ? GNUNET_FRIEND_HELLO_URI_PREFIX
1041 : GNUNET_HELLO_URI_PREFIX,
1042 pkey);
1043 GNUNET_free (pkey);
1044 GNUNET_HELLO_iterate_addresses (hello,
1045 GNUNET_NO,
1046 &add_address_to_uri,
1047 &ctx);
1048 return ctx.uri;
1049}
1050
1051
1052/* ************************* Parse HELLO URI ********************* */
1053
1054
1055/**
1056 * We're building a HELLO. Parse the next address from the
1057 * parsing context and append it.
1058 *
1059 * @param cls the `struct GNUNET_HELLO_ParseUriContext`
1060 * @param max number of bytes available for HELLO construction
1061 * @param buffer where to copy the next address (in binary format)
1062 * @return number of bytes added to buffer, #GNUNET_SYSERR on error
1063 */
1064static ssize_t
1065add_address_to_hello (void *cls,
1066 size_t max,
1067 void *buffer)
1068{
1069 struct GNUNET_HELLO_ParseUriContext *ctx = cls;
1070 const char *tname;
1071 const char *address;
1072 char *uri_address;
1073 const char *end;
1074 char *plugin_name;
1075 struct tm expiration_time;
1076 time_t expiration_seconds;
1077 struct GNUNET_TIME_Absolute expire;
1078 struct GNUNET_TRANSPORT_PluginFunctions *papi;
1079 void *addr;
1080 size_t addr_len;
1081 struct GNUNET_HELLO_Address haddr;
1082 ssize_t ret;
1083
1084 if (NULL == ctx->pos)
1085 return GNUNET_SYSERR;
1086 if (GNUNET_HELLO_URI_SEP != ctx->pos[0])
1087 {
1088 ctx->ret = GNUNET_SYSERR;
1089 GNUNET_break (0);
1090 return GNUNET_SYSERR;
1091 }
1092 ctx->pos++;
1093
1094 if (('0' == ctx->pos[0]) &&
1095 (GNUNET_HELLO_URI_SEP == ctx->pos[1]))
1096 {
1097 expire = GNUNET_TIME_UNIT_FOREVER_ABS;
1098 tname = ctx->pos + 1;
1099 }
1100 else
1101 {
1102 memset (&expiration_time, 0, sizeof(expiration_time));
1103 tname = strptime (ctx->pos,
1104 "%Y%m%d%H%M%S",
1105 &expiration_time);
1106 if (NULL == tname)
1107 {
1108 ctx->ret = GNUNET_SYSERR;
1109 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1110 _ (
1111 "Failed to parse HELLO message: missing expiration time\n"));
1112 GNUNET_break (0);
1113 return GNUNET_SYSERR;
1114 }
1115
1116 expiration_seconds = mktime (&expiration_time);
1117 if (expiration_seconds == (time_t) -1)
1118 {
1119 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1120 _ (
1121 "Failed to parse HELLO message: invalid expiration time\n"));
1122 ctx->ret = GNUNET_SYSERR;
1123 GNUNET_break (0);
1124 return GNUNET_SYSERR;
1125 }
1126 expire.abs_value_us = expiration_seconds * 1000LL * 1000LL;
1127 }
1128 if (GNUNET_HELLO_URI_SEP != tname[0])
1129 {
1130 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1131 _ ("Failed to parse HELLO message: malformed\n"));
1132 ctx->ret = GNUNET_SYSERR;
1133 GNUNET_break (0);
1134 return GNUNET_SYSERR;
1135 }
1136 tname++;
1137 address = strchr (tname,
1138 (int) GNUNET_HELLO_URI_SEP);
1139 if (NULL == address)
1140 {
1141 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1142 _ (
1143 "Failed to parse HELLO message: missing transport plugin\n"));
1144 ctx->ret = GNUNET_SYSERR;
1145 GNUNET_break (0);
1146 return GNUNET_SYSERR;
1147 }
1148 address++;
1149 end = strchr (address, (int) GNUNET_HELLO_URI_SEP);
1150 ctx->pos = end;
1151 ctx->counter_total++;
1152 plugin_name = GNUNET_strndup (tname, address - (tname + 1));
1153 papi = ctx->plugins_find (plugin_name);
1154 if (NULL == papi)
1155 {
1156 /* Not an error - we might just not have the right plugin.
1157 * Skip this part, advance to the next one and recurse.
1158 * But only if this is not the end of string.
1159 */
1160 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1161 _ ("Plugin `%s' not found, skipping address\n"),
1162 plugin_name);
1163 GNUNET_free (plugin_name);
1164 return 0;
1165 }
1166 if (NULL == papi->string_to_address)
1167 {
1168 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1169 _ ("Plugin `%s' does not support URIs yet\n"),
1170 plugin_name);
1171 GNUNET_free (plugin_name);
1172 GNUNET_break (0);
1173 return 0;
1174 }
1175 uri_address = GNUNET_strndup (address, end - address);
1176 if (GNUNET_OK !=
1177 papi->string_to_address (papi->cls,
1178 uri_address,
1179 strlen (uri_address) + 1,
1180 &addr,
1181 &addr_len))
1182 {
1183 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1184 _ ("Failed to parse `%s' as an address for plugin `%s'\n"),
1185 uri_address,
1186 plugin_name);
1187 GNUNET_free (plugin_name);
1188 GNUNET_free (uri_address);
1189 return 0;
1190 }
1191 GNUNET_free (uri_address);
1192 /* address.peer is unset - not used by add_address() */
1193 haddr.address_length = addr_len;
1194 haddr.address = addr;
1195 haddr.transport_name = plugin_name;
1196 ret = GNUNET_HELLO_add_address (&haddr,
1197 expire,
1198 buffer,
1199 max);
1200 ctx->counter_added++;
1201 GNUNET_free (addr);
1202 GNUNET_free (plugin_name);
1203 return ret;
1204}
1205
1206
1207/**
1208 * Parse a hello URI string to a hello message.
1209 *
1210 * @param uri URI string to parse
1211 * @param pubkey Pointer to struct where public key is parsed
1212 * @param hello Pointer to struct where hello message is parsed
1213 * @param plugins_find Function to find transport plugins by name
1214 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the URI was invalid, #GNUNET_NO on other errors
1215 */
1216int
1217GNUNET_HELLO_parse_uri (const char *uri,
1218 struct GNUNET_CRYPTO_EddsaPublicKey *pubkey,
1219 struct GNUNET_HELLO_Message **hello,
1220 GNUNET_HELLO_TransportPluginsFind plugins_find)
1221{
1222 const char *pks;
1223 const char *exc;
1224 int friend_only;
1225 struct GNUNET_HELLO_ParseUriContext ctx;
1226
1227 if (0 == strncmp (uri,
1228 GNUNET_HELLO_URI_PREFIX,
1229 strlen (GNUNET_HELLO_URI_PREFIX)))
1230 {
1231 pks = &uri[strlen (GNUNET_HELLO_URI_PREFIX)];
1232 friend_only = GNUNET_NO;
1233 }
1234 else if (0 == strncmp (uri,
1235 GNUNET_FRIEND_HELLO_URI_PREFIX,
1236 strlen (GNUNET_FRIEND_HELLO_URI_PREFIX)))
1237 {
1238 pks = &uri[strlen (GNUNET_FRIEND_HELLO_URI_PREFIX)];
1239 friend_only = GNUNET_YES;
1240 }
1241 else
1242 return GNUNET_SYSERR;
1243 exc = strchr (pks, GNUNET_HELLO_URI_SEP);
1244
1245 if (GNUNET_OK !=
1246 GNUNET_STRINGS_string_to_data (pks,
1247 (NULL == exc) ? strlen (pks) : (exc - pks),
1248 (unsigned char *) pubkey,
1249 sizeof(*pubkey)))
1250 return GNUNET_SYSERR;
1251
1252 ctx.pos = exc;
1253 ctx.ret = GNUNET_OK;
1254 ctx.counter_total = 0;
1255 ctx.counter_added = 0;
1256 ctx.plugins_find = plugins_find;
1257 *hello = GNUNET_HELLO_create (pubkey,
1258 &add_address_to_hello,
1259 &ctx,
1260 friend_only);
1261
1262 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1263 "HELLO URI contained %u addresses, added %u addresses\n",
1264 ctx.counter_total,
1265 ctx.counter_added);
1266
1267 return ctx.ret;
1268}
1269
1270
1271/* end of hello.c */
diff --git a/src/hello/test_friend_hello.c b/src/hello/test_friend_hello.c
deleted file mode 100644
index 1b092c0b8..000000000
--- a/src/hello/test_friend_hello.c
+++ /dev/null
@@ -1,185 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2009 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/test_friend_hello.c
22 * @brief test for hello.c
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "gnunet_hello_lib.h"
27
28
29static ssize_t
30my_addr_gen (void *cls,
31 size_t max,
32 void *buf)
33{
34 unsigned int *i = cls;
35 size_t ret;
36 struct GNUNET_HELLO_Address address;
37
38 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
39 "DEBUG: my_addr_gen called with i = %d\n", *i);
40 if (0 == *i)
41 return GNUNET_SYSERR; /* Stop iteration */
42 memset (&address.peer, 0, sizeof(struct GNUNET_PeerIdentity));
43 address.address = "address_information";
44 address.transport_name = "test";
45 address.address_length = *i;
46 ret =
47 GNUNET_HELLO_add_address (&address, GNUNET_TIME_absolute_get (), buf,
48 max);
49 (*i)--;
50 return ret;
51}
52
53
54static int
55check_addr (void *cls,
56 const struct GNUNET_HELLO_Address *address,
57 struct GNUNET_TIME_Absolute expiration)
58{
59 unsigned int *i = cls;
60
61 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
62 "DEBUG: check_addr called with i = %d and addrlen = %u\n",
63 *i, (unsigned int) address->address_length);
64 GNUNET_assert (address->address_length > 0);
65 GNUNET_assert (*i & (1 << (address->address_length - 1)));
66 *i -= (1 << (address->address_length - 1));
67 GNUNET_assert (0 ==
68 strncmp ("address_information", address->address,
69 address->address_length));
70 GNUNET_assert (0 == strcmp ("test", address->transport_name));
71 return GNUNET_OK;
72}
73
74
75static int
76remove_some (void *cls,
77 const struct GNUNET_HELLO_Address *address,
78 struct GNUNET_TIME_Absolute expiration)
79{
80 unsigned int *i = cls;
81
82 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
83 "DEBUG: remove_some called with i = %d and addrlen = %u\n",
84 *i, (unsigned int) address->address_length);
85 GNUNET_assert (address->address_length > 0);
86 if (*i & (1 << (address->address_length - 1)))
87 {
88 *i -= (1 << (address->address_length - 1));
89 return GNUNET_NO;
90 }
91 return GNUNET_OK;
92}
93
94
95int
96main (int argc, char *argv[])
97{
98 struct GNUNET_HELLO_Message *msg1;
99 struct GNUNET_HELLO_Message *msg2;
100 struct GNUNET_HELLO_Message *msg3;
101 struct GNUNET_CRYPTO_EddsaPublicKey publicKey;
102 struct GNUNET_TIME_Absolute startup_time;
103 unsigned int i;
104
105 GNUNET_log_setup ("test-hello", "DEBUG", NULL);
106 startup_time = GNUNET_TIME_absolute_get ();
107 memset (&publicKey, 42, sizeof(publicKey));
108 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
109 "Testing HELLO creation (without addresses)...\n");
110 i = 0;
111 msg1 = GNUNET_HELLO_create (&publicKey, &my_addr_gen, &i, GNUNET_YES);
112 GNUNET_assert (msg1 != NULL);
113 GNUNET_assert (0 < GNUNET_HELLO_size (msg1));
114
115 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
116 "Testing address iteration (empty set)...\n");
117 GNUNET_assert (NULL ==
118 GNUNET_HELLO_iterate_addresses (msg1, GNUNET_NO, &check_addr,
119 &i));
120 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
121 "Testing HELLO creation (with one address)...\n");
122 i = 1;
123 msg2 = GNUNET_HELLO_create (&publicKey, &my_addr_gen, &i, GNUNET_YES);
124 GNUNET_assert (msg2 != NULL);
125 GNUNET_assert (GNUNET_HELLO_size (msg1) < GNUNET_HELLO_size (msg2));
126
127 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
128 "Testing address iteration (one address)...\n");
129 i = 1;
130 GNUNET_assert (NULL ==
131 GNUNET_HELLO_iterate_addresses (msg2, GNUNET_NO, &check_addr,
132 &i));
133 GNUNET_assert (i == 0);
134 GNUNET_free (msg1);
135
136 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
137 "Testing HELLO creation (with two addresses)...\n");
138 i = 2;
139 msg3 = GNUNET_HELLO_create (&publicKey, &my_addr_gen, &i, GNUNET_YES);
140 GNUNET_assert (msg3 != NULL);
141 GNUNET_assert (GNUNET_HELLO_size (msg2) < GNUNET_HELLO_size (msg3));
142
143 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
144 "Testing address iteration (two addresses)...\n");
145 i = 3;
146 GNUNET_assert (NULL ==
147 GNUNET_HELLO_iterate_addresses (msg3, GNUNET_NO, &check_addr,
148 &i));
149 GNUNET_assert (i == 0);
150
151 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
152 "Testing HELLO merge...\n");
153 msg1 = GNUNET_HELLO_merge (msg2, msg3);
154 GNUNET_assert (GNUNET_HELLO_size (msg1) == GNUNET_HELLO_size (msg3));
155
156 i = 3;
157 GNUNET_assert (NULL ==
158 GNUNET_HELLO_iterate_addresses (msg1, GNUNET_NO, &check_addr,
159 &i));
160 GNUNET_assert (i == 0);
161 GNUNET_free (msg1);
162
163 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
164 "Testing address iteration to copy HELLO...\n");
165 i = 2;
166 msg1 = GNUNET_HELLO_iterate_addresses (msg3, GNUNET_YES, &remove_some, &i);
167 GNUNET_assert (msg1 != NULL);
168 GNUNET_assert (i == 0);
169 i = 1;
170 GNUNET_assert (NULL ==
171 GNUNET_HELLO_iterate_addresses (msg1, GNUNET_NO, &check_addr,
172 &i));
173 GNUNET_assert (i == 0);
174 GNUNET_free (msg1);
175
176 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
177 "Testing delta address iteration...\n");
178 i = 2;
179 GNUNET_HELLO_iterate_new_addresses (msg3, msg2, startup_time, &check_addr,
180 &i);
181 GNUNET_assert (i == 0);
182 GNUNET_free (msg2);
183 GNUNET_free (msg3);
184 return 0; /* testcase passed */
185}
diff --git a/src/hello/test_hello-ng.c b/src/hello/test_hello-ng.c
deleted file mode 100644
index e6b1d42a0..000000000
--- a/src/hello/test_hello-ng.c
+++ /dev/null
@@ -1,37 +0,0 @@
1#include "platform.h"
2#include "gnunet_util_lib.h"
3#include "gnunet_nt_lib.h"
4#include "gnunet_hello_lib.h"
5
6int
7main (int argc,
8 char *argv[])
9{
10 struct GNUNET_CRYPTO_EddsaPublicKey pubKey;
11 struct GNUNET_CRYPTO_EddsaPrivateKey privKey;
12 struct GNUNET_PeerIdentity pid;
13 struct GNUNET_TIME_Absolute t = GNUNET_TIME_absolute_get ();
14 char *res;
15 size_t res_len;
16 enum GNUNET_NetworkType nt;
17
18 GNUNET_CRYPTO_eddsa_key_create (&privKey);
19 GNUNET_CRYPTO_eddsa_key_get_public (&privKey,
20 &pubKey);
21 pid.public_key = pubKey;
22 GNUNET_HELLO_sign_address ("127.0.0.1:8080",
23 GNUNET_NT_LAN,
24 t,
25 &privKey,
26 (void**)&res,
27 &res_len);
28 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
29 "%s\n", res);
30 GNUNET_assert (NULL !=
31 GNUNET_HELLO_extract_address ((void**)res,
32 res_len,
33 &pid,
34 &nt,
35 &t));
36 return 0;
37}
diff --git a/src/hello/test_hello.c b/src/hello/test_hello.c
deleted file mode 100644
index 8631d2af3..000000000
--- a/src/hello/test_hello.c
+++ /dev/null
@@ -1,253 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2009, 2015 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/test_hello.c
22 * @brief test for hello.c
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "gnunet_hello_lib.h"
27
28
29/**
30 *
31 *
32 * @param cls
33 * @param max
34 * @param buf
35 * @return
36 */
37static ssize_t
38my_addr_gen (void *cls,
39 size_t max,
40 void *buf)
41{
42 unsigned int *i = cls;
43 size_t ret;
44 struct GNUNET_HELLO_Address address;
45
46 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
47 "DEBUG: my_addr_gen called with i = %d\n",
48 *i);
49 if (0 == *i)
50 return GNUNET_SYSERR;
51 memset (&address.peer, 0, sizeof(struct GNUNET_PeerIdentity));
52 address.address = "address_information";
53 address.transport_name = "test";
54 address.address_length = *i;
55 ret = GNUNET_HELLO_add_address (&address,
56 GNUNET_TIME_absolute_get (),
57 buf,
58 max);
59 (*i)--;
60 return ret;
61}
62
63
64/**
65 *
66 *
67 * @param cls
68 * @param address
69 * @param expiration
70 * @return
71 */
72static int
73check_addr (void *cls,
74 const struct GNUNET_HELLO_Address *address,
75 struct GNUNET_TIME_Absolute expiration)
76{
77 unsigned int *i = cls;
78
79 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
80 "DEBUG: check_addr called with i = %d and addrlen = %u\n",
81 *i,
82 (unsigned int) address->address_length);
83 GNUNET_assert (address->address_length > 0);
84 GNUNET_assert (*i & (1 << (address->address_length - 1)));
85 *i -= (1 << (address->address_length - 1));
86 GNUNET_assert (0 ==
87 strncmp ("address_information",
88 address->address,
89 address->address_length));
90 GNUNET_assert (0 == strcmp ("test",
91 address->transport_name));
92 return GNUNET_OK;
93}
94
95
96/**
97 *
98 *
99 * @param cls
100 * @param address
101 * @param expiration
102 * @return
103 */
104static int
105remove_some (void *cls,
106 const struct GNUNET_HELLO_Address *address,
107 struct GNUNET_TIME_Absolute expiration)
108{
109 unsigned int *i = cls;
110
111 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
112 "DEBUG: remove_some called with i = %d and addrlen = %u\n",
113 *i,
114 (unsigned int) address->address_length);
115 GNUNET_assert (address->address_length > 0);
116 if (*i & (1 << (address->address_length - 1)))
117 {
118 *i -= (1 << (address->address_length - 1));
119 return GNUNET_NO;
120 }
121 return GNUNET_OK;
122}
123
124
125int
126main (int argc,
127 char *argv[])
128{
129 struct GNUNET_HELLO_Message *msg1;
130 struct GNUNET_HELLO_Message *msg2;
131 struct GNUNET_HELLO_Message *msg3;
132 struct GNUNET_CRYPTO_EddsaPublicKey publicKey;
133 struct GNUNET_PeerIdentity pid;
134 struct GNUNET_TIME_Absolute startup_time;
135 unsigned int i;
136
137 GNUNET_log_setup ("test-hello",
138 "DEBUG",
139 NULL);
140 startup_time = GNUNET_TIME_absolute_get ();
141 memset (&publicKey, 42, sizeof(publicKey));
142 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
143 "Testing HELLO creation (without addresses)...\n");
144 i = 0;
145 msg1 = GNUNET_HELLO_create (&publicKey,
146 &my_addr_gen,
147 &i,
148 GNUNET_NO);
149 GNUNET_assert (msg1 != NULL);
150 GNUNET_assert (0 < GNUNET_HELLO_size (msg1));
151
152 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
153 "Testing address iteration (empty set)...\n");
154 GNUNET_assert (NULL ==
155 GNUNET_HELLO_iterate_addresses (msg1,
156 GNUNET_NO,
157 &check_addr,
158 &i));
159 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
160 "Testing HELLO creation (with one address)...\n");
161 i = 1;
162 msg2 = GNUNET_HELLO_create (&publicKey,
163 &my_addr_gen,
164 &i,
165 GNUNET_NO);
166 GNUNET_assert (msg2 != NULL);
167 GNUNET_assert (GNUNET_HELLO_size (msg1) < GNUNET_HELLO_size (msg2));
168
169 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
170 "Testing address iteration (one address)...\n");
171 i = 1;
172 GNUNET_assert (NULL ==
173 GNUNET_HELLO_iterate_addresses (msg2,
174 GNUNET_NO,
175 &check_addr,
176 &i));
177 GNUNET_assert (i == 0);
178
179 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
180 "Testing get_key from HELLO...\n");
181 GNUNET_assert (GNUNET_OK == GNUNET_HELLO_get_id (msg2, &pid));
182 GNUNET_assert (0 == GNUNET_memcmp (&publicKey,
183 &pid.public_key));
184 GNUNET_free (msg1);
185
186 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
187 "Testing HELLO creation (with two addresses)...\n");
188 i = 2;
189 msg3 = GNUNET_HELLO_create (&publicKey,
190 &my_addr_gen,
191 &i,
192 GNUNET_NO);
193 GNUNET_assert (msg3 != NULL);
194 GNUNET_assert (GNUNET_HELLO_size (msg2) < GNUNET_HELLO_size (msg3));
195
196 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
197 "Testing address iteration (two addresses)...\n");
198 i = 3;
199 GNUNET_assert (NULL ==
200 GNUNET_HELLO_iterate_addresses (msg3,
201 GNUNET_NO,
202 &check_addr,
203 &i));
204 GNUNET_assert (i == 0);
205
206 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
207 "Testing HELLO merge...\n");
208 msg1 = GNUNET_HELLO_merge (msg2, msg3);
209 GNUNET_assert (GNUNET_HELLO_size (msg1) == GNUNET_HELLO_size (msg3));
210
211 i = 3;
212 GNUNET_assert (NULL ==
213 GNUNET_HELLO_iterate_addresses (msg1,
214 GNUNET_NO,
215 &check_addr,
216 &i));
217 GNUNET_assert (i == 0);
218 GNUNET_free (msg1);
219
220 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
221 "Testing address iteration to copy HELLO...\n");
222 i = 2;
223 msg1 = GNUNET_HELLO_iterate_addresses (msg3,
224 GNUNET_YES,
225 &remove_some,
226 &i);
227 GNUNET_assert (msg1 != NULL);
228 GNUNET_assert (i == 0);
229 i = 1;
230 GNUNET_assert (NULL ==
231 GNUNET_HELLO_iterate_addresses (msg1,
232 GNUNET_NO,
233 &check_addr,
234 &i));
235 GNUNET_assert (i == 0);
236 GNUNET_free (msg1);
237
238 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
239 "Testing delta address iteration...\n");
240 i = 2;
241 GNUNET_HELLO_iterate_new_addresses (msg3,
242 msg2,
243 startup_time,
244 &check_addr,
245 &i);
246 GNUNET_assert (i == 0);
247 GNUNET_free (msg2);
248 GNUNET_free (msg3);
249 return 0; /* testcase passed */
250}
251
252
253/* end of test_hello.c */