aboutsummaryrefslogtreecommitdiff
path: root/src/mesh/gnunet-service-mesh_dht.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesh/gnunet-service-mesh_dht.c')
-rw-r--r--src/mesh/gnunet-service-mesh_dht.c196
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 */
50typedef 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 */
60struct 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;
67static GNUNET_SCHEDULER_TaskIdentifier announce_id_task; 95static GNUNET_SCHEDULER_TaskIdentifier announce_id_task;
68 96
69/** 97/**
98 * Own ID (short value).
99 */
100static GNUNET_PEER_Id short_id;
101
102/**
70 * Own ID (full value). 103 * Own ID (full value).
71 */ 104 */
72static struct GNUNET_PeerIdentity *id; 105static 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 */
124static struct MeshPeerPath *
125path_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 */
221static void
222dht_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
137GMD_init (const struct GNUNET_CONFIGURATION_Handle *c, 294GMD_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
345struct GMD_search_handle *
346GMD_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
369void
370GMD_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