diff options
Diffstat (limited to 'src/mesh/gnunet-service-mesh_dht.c')
-rw-r--r-- | src/mesh/gnunet-service-mesh_dht.c | 196 |
1 files changed, 192 insertions, 4 deletions
diff --git a/src/mesh/gnunet-service-mesh_dht.c b/src/mesh/gnunet-service-mesh_dht.c index 7f8450637..a194bd0b7 100644 --- a/src/mesh/gnunet-service-mesh_dht.c +++ b/src/mesh/gnunet-service-mesh_dht.c | |||
@@ -24,6 +24,7 @@ | |||
24 | 24 | ||
25 | #include "gnunet_dht_service.h" | 25 | #include "gnunet_dht_service.h" |
26 | 26 | ||
27 | #include "mesh_path.h" | ||
27 | #include "gnunet-service-mesh_dht.h" | 28 | #include "gnunet-service-mesh_dht.h" |
28 | #include "gnunet-service-mesh_peer.h" | 29 | #include "gnunet-service-mesh_peer.h" |
29 | 30 | ||
@@ -35,11 +36,38 @@ | |||
35 | #define DEBUG_DHT(...) | 36 | #define DEBUG_DHT(...) |
36 | #endif | 37 | #endif |
37 | 38 | ||
39 | #define LOG (level, ...) GNUNET_log_from ("mesh-dht", level, __VA_ARGS__) | ||
40 | |||
41 | |||
42 | |||
43 | /** | ||
44 | * Callback called on each path found over the DHT. | ||
45 | * | ||
46 | * @param cls Closure. | ||
47 | * @param path An unchecked, unoptimized path to the target node. | ||
48 | * After callback will no longer be valid! | ||
49 | */ | ||
50 | typedef void (*GMD_search_callback) (void *cls, | ||
51 | const struct MeshPeerPath *path); | ||
52 | |||
38 | /******************************************************************************/ | 53 | /******************************************************************************/ |
39 | /******************************** STRUCTS **********************************/ | 54 | /******************************** STRUCTS **********************************/ |
40 | /******************************************************************************/ | 55 | /******************************************************************************/ |
41 | 56 | ||
57 | /** | ||
58 | * Handle for DHT searches. | ||
59 | */ | ||
60 | struct GMD_search_handle | ||
61 | { | ||
62 | /** DHT_GET handle. */ | ||
63 | struct GNUNET_DHT_GetHandle *dhtget; | ||
64 | |||
65 | /** Provided callback to call when a path is found. */ | ||
66 | GMD_search_callback callback; | ||
42 | 67 | ||
68 | /** Provided closure. */ | ||
69 | void *cls; | ||
70 | }; | ||
43 | 71 | ||
44 | 72 | ||
45 | /******************************************************************************/ | 73 | /******************************************************************************/ |
@@ -67,9 +95,14 @@ static unsigned long long dht_replication_level; | |||
67 | static GNUNET_SCHEDULER_TaskIdentifier announce_id_task; | 95 | static GNUNET_SCHEDULER_TaskIdentifier announce_id_task; |
68 | 96 | ||
69 | /** | 97 | /** |
98 | * Own ID (short value). | ||
99 | */ | ||
100 | static GNUNET_PEER_Id short_id; | ||
101 | |||
102 | /** | ||
70 | * Own ID (full value). | 103 | * Own ID (full value). |
71 | */ | 104 | */ |
72 | static struct GNUNET_PeerIdentity *id; | 105 | static struct GNUNET_PeerIdentity *full_id; |
73 | 106 | ||
74 | /** | 107 | /** |
75 | * Own private key. | 108 | * Own private key. |
@@ -83,6 +116,130 @@ static struct GNUNET_CRYPTO_EccPrivateKey *private_key; | |||
83 | 116 | ||
84 | 117 | ||
85 | /** | 118 | /** |
119 | * Build a PeerPath from the paths returned from the DHT, reversing the paths | ||
120 | * to obtain a local peer -> destination path and interning the peer ids. | ||
121 | * | ||
122 | * @return Newly allocated and created path | ||
123 | */ | ||
124 | static struct MeshPeerPath * | ||
125 | path_build_from_dht (const struct GNUNET_PeerIdentity *get_path, | ||
126 | unsigned int get_path_length, | ||
127 | const struct GNUNET_PeerIdentity *put_path, | ||
128 | unsigned int put_path_length) | ||
129 | { | ||
130 | struct MeshPeerPath *p; | ||
131 | GNUNET_PEER_Id id; | ||
132 | int i; | ||
133 | |||
134 | p = path_new (1); | ||
135 | p->peers[0] = myid; | ||
136 | GNUNET_PEER_change_rc (myid, 1); | ||
137 | i = get_path_length; | ||
138 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " GET has %d hops.\n", i); | ||
139 | for (i--; i >= 0; i--) | ||
140 | { | ||
141 | id = GNUNET_PEER_intern (&get_path[i]); | ||
142 | if (p->length > 0 && id == p->peers[p->length - 1]) | ||
143 | { | ||
144 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Optimizing 1 hop out.\n"); | ||
145 | GNUNET_PEER_change_rc (id, -1); | ||
146 | } | ||
147 | else | ||
148 | { | ||
149 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Adding from GET: %s.\n", | ||
150 | GNUNET_i2s (&get_path[i])); | ||
151 | p->length++; | ||
152 | p->peers = GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * p->length); | ||
153 | p->peers[p->length - 1] = id; | ||
154 | } | ||
155 | } | ||
156 | i = put_path_length; | ||
157 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " PUT has %d hops.\n", i); | ||
158 | for (i--; i >= 0; i--) | ||
159 | { | ||
160 | id = GNUNET_PEER_intern (&put_path[i]); | ||
161 | if (id == myid) | ||
162 | { | ||
163 | /* PUT path went through us, so discard the path up until now and start | ||
164 | * from here to get a much shorter (and loop-free) path. | ||
165 | */ | ||
166 | path_destroy (p); | ||
167 | p = path_new (0); | ||
168 | } | ||
169 | if (p->length > 0 && id == p->peers[p->length - 1]) | ||
170 | { | ||
171 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Optimizing 1 hop out.\n"); | ||
172 | GNUNET_PEER_change_rc (id, -1); | ||
173 | } | ||
174 | else | ||
175 | { | ||
176 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Adding from PUT: %s.\n", | ||
177 | GNUNET_i2s (&put_path[i])); | ||
178 | p->length++; | ||
179 | p->peers = GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * p->length); | ||
180 | p->peers[p->length - 1] = id; | ||
181 | } | ||
182 | } | ||
183 | #if MESH_DEBUG | ||
184 | if (get_path_length > 0) | ||
185 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " (first of GET: %s)\n", | ||
186 | GNUNET_i2s (&get_path[0])); | ||
187 | if (put_path_length > 0) | ||
188 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " (first of PUT: %s)\n", | ||
189 | GNUNET_i2s (&put_path[0])); | ||
190 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " In total: %d hops\n", | ||
191 | p->length); | ||
192 | for (i = 0; i < p->length; i++) | ||
193 | { | ||
194 | struct GNUNET_PeerIdentity peer_id; | ||
195 | |||
196 | GNUNET_PEER_resolve (p->peers[i], &peer_id); | ||
197 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " %u: %s\n", p->peers[i], | ||
198 | GNUNET_i2s (&peer_id)); | ||
199 | } | ||
200 | #endif | ||
201 | return p; | ||
202 | } | ||
203 | |||
204 | |||
205 | /** | ||
206 | * Function to process paths received for a new peer addition. The recorded | ||
207 | * paths form the initial tunnel, which can be optimized later. | ||
208 | * Called on each result obtained for the DHT search. | ||
209 | * | ||
210 | * @param cls closure | ||
211 | * @param exp when will this value expire | ||
212 | * @param key key of the result | ||
213 | * @param get_path path of the get request | ||
214 | * @param get_path_length lenght of get_path | ||
215 | * @param put_path path of the put request | ||
216 | * @param put_path_length length of the put_path | ||
217 | * @param type type of the result | ||
218 | * @param size number of bytes in data | ||
219 | * @param data pointer to the result data | ||
220 | */ | ||
221 | static void | ||
222 | dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, | ||
223 | const struct GNUNET_HashCode * key, | ||
224 | const struct GNUNET_PeerIdentity *get_path, | ||
225 | unsigned int get_path_length, | ||
226 | const struct GNUNET_PeerIdentity *put_path, | ||
227 | unsigned int put_path_length, enum GNUNET_BLOCK_Type type, | ||
228 | size_t size, const void *data) | ||
229 | { | ||
230 | struct GMD_search_handle *h = cls; | ||
231 | struct MeshPeerPath *p; | ||
232 | |||
233 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Got results!\n"); | ||
234 | p = path_build_from_dht (get_path, get_path_length, | ||
235 | put_path, put_path_length); | ||
236 | h->callback (h->cls, p); | ||
237 | path_destroy (p); | ||
238 | return; | ||
239 | } | ||
240 | |||
241 | |||
242 | /** | ||
86 | * Periodically announce self id in the DHT | 243 | * Periodically announce self id in the DHT |
87 | * | 244 | * |
88 | * @param cls closure | 245 | * @param cls closure |
@@ -105,8 +262,8 @@ announce_id (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
105 | */ | 262 | */ |
106 | DEBUG_DHT ("DHT_put for ID %s started.\n", GNUNET_i2s (id)); | 263 | DEBUG_DHT ("DHT_put for ID %s started.\n", GNUNET_i2s (id)); |
107 | 264 | ||
108 | block.id = *id; | 265 | block.id = *full_id; |
109 | GNUNET_CRYPTO_hash (id, sizeof (struct GNUNET_PeerIdentity), &phash); | 266 | GNUNET_CRYPTO_hash (full_id, sizeof (struct GNUNET_PeerIdentity), &phash); |
110 | GNUNET_DHT_put (dht_handle, /* DHT handle */ | 267 | GNUNET_DHT_put (dht_handle, /* DHT handle */ |
111 | &phash, /* Key to use */ | 268 | &phash, /* Key to use */ |
112 | dht_replication_level, /* Replication level */ | 269 | dht_replication_level, /* Replication level */ |
@@ -137,7 +294,7 @@ void | |||
137 | GMD_init (const struct GNUNET_CONFIGURATION_Handle *c, | 294 | GMD_init (const struct GNUNET_CONFIGURATION_Handle *c, |
138 | struct GNUNET_PeerIdentity *peer_id) | 295 | struct GNUNET_PeerIdentity *peer_id) |
139 | { | 296 | { |
140 | id = peer_id; | 297 | full_id = peer_id; |
141 | if (GNUNET_OK != | 298 | if (GNUNET_OK != |
142 | GNUNET_CONFIGURATION_get_value_number (c, "MESH", "DHT_REPLICATION_LEVEL", | 299 | GNUNET_CONFIGURATION_get_value_number (c, "MESH", "DHT_REPLICATION_LEVEL", |
143 | &dht_replication_level)) | 300 | &dht_replication_level)) |
@@ -184,3 +341,34 @@ GMD_shutdown(void ) | |||
184 | announce_id_task = GNUNET_SCHEDULER_NO_TASK; | 341 | announce_id_task = GNUNET_SCHEDULER_NO_TASK; |
185 | } | 342 | } |
186 | } | 343 | } |
344 | |||
345 | struct GMD_search_handle * | ||
346 | GMD_search (const struct GNUNET_PeerIdentity *peer_id, | ||
347 | GMD_search_callback callback, void *cls) | ||
348 | { | ||
349 | struct GNUNET_HashCode phash; | ||
350 | struct GMD_search_handle *h; | ||
351 | |||
352 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
353 | " Starting DHT GET for peer %s\n", GNUNET_i2s (peer_id)); | ||
354 | GNUNET_CRYPTO_hash (peer_id, sizeof (struct GNUNET_PeerIdentity), &phash); | ||
355 | h = GNUNET_new (struct GMD_search_handle); | ||
356 | h->cls = cls; | ||
357 | h->dhtget = GNUNET_DHT_get_start (dht_handle, /* handle */ | ||
358 | GNUNET_BLOCK_TYPE_MESH_PEER, /* type */ | ||
359 | &phash, /* key to search */ | ||
360 | dht_replication_level, /* replication level */ | ||
361 | GNUNET_DHT_RO_RECORD_ROUTE | | ||
362 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, | ||
363 | NULL, /* xquery */ | ||
364 | 0, /* xquery bits */ | ||
365 | &dht_get_id_handler, h); | ||
366 | return h; | ||
367 | } | ||
368 | |||
369 | void | ||
370 | GMD_search_stop (struct GMD_search_handle *h) | ||
371 | { | ||
372 | GNUNET_DHT_get_stop (h->dhtget); | ||
373 | GNUNET_free (h); | ||
374 | } \ No newline at end of file | ||