aboutsummaryrefslogtreecommitdiff
path: root/src/dht
diff options
context:
space:
mode:
authorArthur Dewarumez <arthur.dewarumez@etudiant.univ-lille1.fr>2015-04-27 11:12:21 +0000
committerArthur Dewarumez <arthur.dewarumez@etudiant.univ-lille1.fr>2015-04-27 11:12:21 +0000
commit0bff5a1b397f3f2c4f18a92b0828b2d6ab9bf74f (patch)
tree97bf32ecba33c3189c7974823cdb275b48ebd26b /src/dht
parentfe384d97cdfcb47c10a05f56f983f24619115a19 (diff)
downloadgnunet-0bff5a1b397f3f2c4f18a92b0828b2d6ab9bf74f.tar.gz
gnunet-0bff5a1b397f3f2c4f18a92b0828b2d6ab9bf74f.zip
Adding files for whanau.
Diffstat (limited to 'src/dht')
-rw-r--r--src/dht/Makefile.am24
-rw-r--r--src/dht/gnunet-service-wdht.c220
-rw-r--r--src/dht/gnunet-service-wdht.h60
-rw-r--r--src/dht/gnunet-service-wdht_clients.c1449
-rw-r--r--src/dht/gnunet-service-wdht_clients.h149
-rw-r--r--src/dht/gnunet-service-wdht_datacache.c381
-rw-r--r--src/dht/gnunet-service-wdht_datacache.h90
-rw-r--r--src/dht/gnunet-service-wdht_hello.c137
-rw-r--r--src/dht/gnunet-service-wdht_hello.h55
-rw-r--r--src/dht/gnunet-service-wdht_neighbours.c6290
-rw-r--r--src/dht/gnunet-service-wdht_neighbours.h146
-rw-r--r--src/dht/gnunet-service-wdht_nse.c116
-rw-r--r--src/dht/gnunet-service-wdht_nse.h52
-rw-r--r--src/dht/gnunet-service-wdht_routing.c363
-rw-r--r--src/dht/gnunet-service-wdht_routing.h138
15 files changed, 9668 insertions, 2 deletions
diff --git a/src/dht/Makefile.am b/src/dht/Makefile.am
index 835e1dc2a..0dca26901 100644
--- a/src/dht/Makefile.am
+++ b/src/dht/Makefile.am
@@ -48,7 +48,8 @@ libgnunet_plugin_block_dht_la_LDFLAGS = \
48 48
49libexec_PROGRAMS = \ 49libexec_PROGRAMS = \
50 gnunet-service-dht \ 50 gnunet-service-dht \
51 gnunet-service-dht-xvine 51 gnunet-service-dht-xvine\
52 gnunet-service-dht-whanau
52 53
53noinst_PROGRAMS = \ 54noinst_PROGRAMS = \
54 gnunet-dht-monitor \ 55 gnunet-dht-monitor \
@@ -98,7 +99,26 @@ gnunet_service_dht_xvine_LDADD = \
98 $(top_builddir)/src/util/libgnunetutil.la \ 99 $(top_builddir)/src/util/libgnunetutil.la \
99 -lm 100 -lm
100 101
101 102gnunet_service_dht_whanau_SOURCES = \
103 gnunet-service-wdht.c gnunet-service-wdht.h \
104 gnunet-service-wdht_clients.c gnunet-service-wdht_clients.h \
105 gnunet-service-wdht_datacache.c gnunet-service-wdht_datacache.h \
106 gnunet-service-wdht_hello.c gnunet-service-wdht_hello.h \
107 gnunet-service-wdht_nse.c gnunet-service-wdht_nse.h \
108 gnunet-service-wdht_neighbours.c gnunet-service-wdht_neighbours.h \
109 gnunet-service-wdht_routing.c gnunet-service-wdht_routing.h
110gnunet_service_dht_whanau_LDADD = \
111 $(top_builddir)/src/statistics/libgnunetstatistics.la \
112 $(top_builddir)/src/core/libgnunetcore.la \
113 $(top_builddir)/src/nse/libgnunetnse.la \
114 $(top_builddir)/src/ats/libgnunetats.la \
115 $(top_builddir)/src/transport/libgnunettransport.la \
116 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
117 $(top_builddir)/src/hello/libgnunethello.la \
118 $(top_builddir)/src/block/libgnunetblock.la \
119 $(top_builddir)/src/datacache/libgnunetdatacache.la \
120 $(top_builddir)/src/util/libgnunetutil.la \
121 -lm
102 122
103gnunet_dht_get_SOURCES = \ 123gnunet_dht_get_SOURCES = \
104 gnunet-dht-get.c 124 gnunet-dht-get.c
diff --git a/src/dht/gnunet-service-wdht.c b/src/dht/gnunet-service-wdht.c
new file mode 100644
index 000000000..13e60acf4
--- /dev/null
+++ b/src/dht/gnunet-service-wdht.c
@@ -0,0 +1,220 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file dht/gnunet-service-xdht.c
23 * @brief GNUnet DHT service
24 * @author Christian Grothoff
25 * @author Nathan Evans
26 */
27
28#include "platform.h"
29#include "gnunet_block_lib.h"
30#include "gnunet_util_lib.h"
31#include "gnunet_transport_service.h"
32#include "gnunet_hello_lib.h"
33#include "gnunet_dht_service.h"
34#include "gnunet_statistics_service.h"
35#include "gnunet-service-wdht.h"
36#include "gnunet-service-wdht_clients.h"
37#include "gnunet-service-wdht_datacache.h"
38#include "gnunet-service-wdht_hello.h"
39#include "gnunet-service-wdht_neighbours.h"
40#include "gnunet-service-wdht_nse.h"
41#include "gnunet-service-wdht_routing.h"
42
43
44
45/**
46 * Handle for the statistics service.
47 */
48struct GNUNET_STATISTICS_Handle *GDS_stats;
49
50/**
51 * Our handle to the BLOCK library.
52 */
53struct GNUNET_BLOCK_Context *GDS_block_context;
54
55/**
56 * The configuration the DHT service is running with
57 */
58const struct GNUNET_CONFIGURATION_Handle *GDS_cfg;
59
60/**
61 * Our HELLO
62 */
63struct GNUNET_MessageHeader *GDS_my_hello;
64
65/**
66 * Handle to the transport service, for getting our hello
67 */
68struct GNUNET_TRANSPORT_Handle *GDS_transport_handle;
69
70/**
71 * Handle to get our current HELLO.
72 */
73static struct GNUNET_TRANSPORT_GetHelloHandle *ghh;
74
75/**
76 * Hello address expiration
77 */
78struct GNUNET_TIME_Relative hello_expiration;
79
80/**
81 * Should we store our topology predecessor and successor IDs into statistics?
82 */
83extern unsigned int track_topology;
84
85#if ENABLE_MALICIOUS
86/**
87 * Should this peer act malicious?
88 */
89unsigned int malicious;
90#endif
91
92
93/**
94 * Receive the HELLO from transport service, free current and replace
95 * if necessary.
96 *
97 * @param cls NULL
98 * @param message HELLO message of peer
99 */
100static void
101process_hello (void *cls, const struct GNUNET_MessageHeader *message)
102{
103 GNUNET_assert (message != NULL);
104 GNUNET_free_non_null (GDS_my_hello);
105 GDS_my_hello = GNUNET_malloc (ntohs (message->size));
106 memcpy (GDS_my_hello, message, ntohs (message->size));
107}
108
109
110/**
111 * Task run during shutdown.
112 *
113 * @param cls unused
114 * @param tc unused
115 */
116static void
117shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
118{
119 if (NULL != ghh)
120 {
121 GNUNET_TRANSPORT_get_hello_cancel (ghh);
122 ghh = NULL;
123 }
124 if (GDS_transport_handle != NULL)
125 {
126 GNUNET_TRANSPORT_disconnect (GDS_transport_handle);
127 GDS_transport_handle = NULL;
128 }
129
130 GDS_NEIGHBOURS_done ();
131 GDS_DATACACHE_done ();
132 GDS_ROUTING_done ();
133 GDS_HELLO_done ();
134 GDS_NSE_done ();
135 if (GDS_block_context != NULL)
136 {
137 GNUNET_BLOCK_context_destroy (GDS_block_context);
138 GDS_block_context = NULL;
139 }
140 if (GDS_stats != NULL)
141 {
142 GNUNET_STATISTICS_destroy (GDS_stats, GNUNET_YES);
143 GDS_stats = NULL;
144 }
145 GNUNET_free_non_null (GDS_my_hello);
146 GDS_my_hello = NULL;
147}
148
149
150/**
151 * Process dht requests.
152 *
153 * @param cls closure
154 * @param server the initialized server
155 * @param c configuration to use
156 */
157static void
158run (void *cls, struct GNUNET_SERVER_Handle *server,
159 const struct GNUNET_CONFIGURATION_Handle *c)
160{
161 unsigned long long _track_topology;
162 GDS_cfg = c;
163 if (GNUNET_OK !=
164 GNUNET_CONFIGURATION_get_value_time (c, "transport", "HELLO_EXPIRATION", &hello_expiration))
165 {
166 hello_expiration = GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION;
167 }
168 GDS_block_context = GNUNET_BLOCK_context_create (GDS_cfg);
169 GDS_stats = GNUNET_STATISTICS_create ("dht", GDS_cfg);
170 GDS_ROUTING_init ();
171 GDS_NSE_init ();
172 GDS_DATACACHE_init ();
173 GDS_HELLO_init ();
174 GDS_CLIENTS_init (server);
175 if (GNUNET_OK ==
176 GNUNET_CONFIGURATION_get_value_number (c, "xdht", "track_toplogy",
177 &_track_topology))
178 {
179 track_topology = (unsigned int) _track_topology;
180 }
181 if (GNUNET_OK != GDS_NEIGHBOURS_init ())
182 {
183 shutdown_task (NULL, NULL);
184 return;
185 }
186 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
187 NULL);
188 GDS_transport_handle =
189 GNUNET_TRANSPORT_connect (GDS_cfg, NULL, NULL, NULL, NULL, NULL);
190 if (GDS_transport_handle == NULL)
191 {
192 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
193 _("Failed to connect to transport service!\n"));
194 return;
195 }
196 ghh = GNUNET_TRANSPORT_get_hello (GDS_transport_handle, &process_hello, NULL);
197}
198
199
200/**
201 * The main function for the dht service.
202 *
203 * @param argc number of arguments from the command line
204 * @param argv command line arguments
205 * @return 0 ok, 1 on error
206 */
207int
208main (int argc, char *const *argv)
209{
210 int ret;
211
212 ret =
213 (GNUNET_OK ==
214 GNUNET_SERVICE_run (argc, argv, "dht", GNUNET_SERVICE_OPTION_NONE, &run,
215 NULL)) ? 0 : 1;
216 GDS_CLIENTS_done ();
217 return ret;
218}
219
220/* end of gnunet-service-dht.c */
diff --git a/src/dht/gnunet-service-wdht.h b/src/dht/gnunet-service-wdht.h
new file mode 100644
index 000000000..2eee3a429
--- /dev/null
+++ b/src/dht/gnunet-service-wdht.h
@@ -0,0 +1,60 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file dht/gnunet-service-xdht.h
23 * @brief GNUnet DHT globals
24 * @author Christian Grothoff
25 */
26#ifndef GNUNET_SERVICE_XDHT_H
27#define GNUNET_SERVICE_XDHT_H
28
29#include "gnunet_util_lib.h"
30#include "gnunet_statistics_service.h"
31#include "gnunet_transport_service.h"
32
33#define DEBUG_DHT GNUNET_EXTRA_LOGGING
34
35/**
36 * Configuration we use.
37 */
38extern const struct GNUNET_CONFIGURATION_Handle *GDS_cfg;
39
40/**
41 * Our handle to the BLOCK library.
42 */
43extern struct GNUNET_BLOCK_Context *GDS_block_context;
44
45/**
46 * Handle for the statistics service.
47 */
48extern struct GNUNET_STATISTICS_Handle *GDS_stats;
49
50/**
51 * Our HELLO
52 */
53extern struct GNUNET_MessageHeader *GDS_my_hello;
54
55/**
56 * Handle to the transport service, for getting our hello
57 */
58extern struct GNUNET_TRANSPORT_Handle *GDS_transport_handle;
59
60#endif
diff --git a/src/dht/gnunet-service-wdht_clients.c b/src/dht/gnunet-service-wdht_clients.c
new file mode 100644
index 000000000..2e4d4ef0a
--- /dev/null
+++ b/src/dht/gnunet-service-wdht_clients.c
@@ -0,0 +1,1449 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file dht/gnunet-service-dht_clients.c
23 * @brief GNUnet DHT service's client management code
24 * @author Christian Grothoff
25 * @author Nathan Evans
26 */
27
28#include "platform.h"
29#include "gnunet_constants.h"
30#include "gnunet_protocols.h"
31#include "gnunet_statistics_service.h"
32#include "gnunet-service-wdht.h"
33#include "gnunet-service-wdht_clients.h"
34#include "gnunet-service-wdht_datacache.h"
35#include "gnunet-service-wdht_neighbours.h"
36#include "dht.h"
37
38
39/**
40 * Should routing details be logged to stderr (for debugging)?
41 */
42#define LOG_TRAFFIC(kind,...) GNUNET_log_from (kind, "dht-traffic",__VA_ARGS__)
43
44#define LOG(kind,...) GNUNET_log_from (kind, "dht-clients",__VA_ARGS__)
45
46#define DEBUG(...) \
47 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
48
49/**
50 * Linked list of messages to send to clients.
51 */
52struct PendingMessage
53{
54 /**
55 * Pointer to next item in the list
56 */
57 struct PendingMessage *next;
58
59 /**
60 * Pointer to previous item in the list
61 */
62 struct PendingMessage *prev;
63
64 /**
65 * Actual message to be sent, allocated at the end of the struct:
66 * // msg = (cast) &pm[1];
67 * // memcpy (&pm[1], data, len);
68 */
69 const struct GNUNET_MessageHeader *msg;
70
71};
72
73
74/**
75 * Struct containing information about a client,
76 * handle to connect to it, and any pending messages
77 * that need to be sent to it.
78 */
79struct ClientList
80{
81 /**
82 * Linked list of active clients
83 */
84 struct ClientList *next;
85
86 /**
87 * Linked list of active clients
88 */
89 struct ClientList *prev;
90
91 /**
92 * The handle to this client
93 */
94 struct GNUNET_SERVER_Client *client_handle;
95
96 /**
97 * Handle to the current transmission request, NULL
98 * if none pending.
99 */
100 struct GNUNET_SERVER_TransmitHandle *transmit_handle;
101
102 /**
103 * Linked list of pending messages for this client
104 */
105 struct PendingMessage *pending_head;
106
107 /**
108 * Tail of linked list of pending messages for this client
109 */
110 struct PendingMessage *pending_tail;
111
112};
113
114
115/**
116 * Entry in the local forwarding map for a client's GET request.
117 */
118struct ClientQueryRecord
119{
120
121 /**
122 * The key this request was about
123 */
124 struct GNUNET_HashCode key;
125
126 /**
127 * Client responsible for the request.
128 */
129 struct ClientList *client;
130
131 /**
132 * Extended query (see gnunet_block_lib.h), allocated at the end of this struct.
133 */
134 const void *xquery;
135
136 /**
137 * Replies we have already seen for this request.
138 */
139 struct GNUNET_HashCode *seen_replies;
140
141 /**
142 * Pointer to this nodes heap location in the retry-heap (for fast removal)
143 */
144 struct GNUNET_CONTAINER_HeapNode *hnode;
145
146 /**
147 * What's the delay between re-try operations that we currently use for this
148 * request?
149 */
150 struct GNUNET_TIME_Relative retry_frequency;
151
152 /**
153 * What's the next time we should re-try this request?
154 */
155 struct GNUNET_TIME_Absolute retry_time;
156
157 /**
158 * The unique identifier of this request
159 */
160 uint64_t unique_id;
161
162 /**
163 * Number of bytes in xquery.
164 */
165 size_t xquery_size;
166
167 /**
168 * Number of entries in 'seen_replies'.
169 */
170 unsigned int seen_replies_count;
171
172 /**
173 * Desired replication level
174 */
175 uint32_t replication;
176
177 /**
178 * Any message options for this request
179 */
180 uint32_t msg_options;
181
182 /**
183 * The type for the data for the GET request.
184 */
185 enum GNUNET_BLOCK_Type type;
186
187};
188
189
190/**
191 * Struct containing paremeters of monitoring requests.
192 */
193struct ClientMonitorRecord
194{
195
196 /**
197 * Next element in DLL.
198 */
199 struct ClientMonitorRecord *next;
200
201 /**
202 * Previous element in DLL.
203 */
204 struct ClientMonitorRecord *prev;
205
206 /**
207 * Type of blocks that are of interest
208 */
209 enum GNUNET_BLOCK_Type type;
210
211 /**
212 * Key of data of interest, NULL for all.
213 */
214 struct GNUNET_HashCode *key;
215
216 /**
217 * Flag whether to notify about GET messages.
218 */
219 int16_t get;
220
221 /**
222 * Flag whether to notify about GET_REPONSE messages.
223 */
224 int16_t get_resp;
225
226 /**
227 * Flag whether to notify about PUT messages.
228 */
229 uint16_t put;
230
231 /**
232 * Client to notify of these requests.
233 */
234 struct ClientList *client;
235};
236
237
238/**
239 * List of active clients.
240 */
241static struct ClientList *client_head;
242
243/**
244 * List of active clients.
245 */
246static struct ClientList *client_tail;
247
248/**
249 * List of active monitoring requests.
250 */
251static struct ClientMonitorRecord *monitor_head;
252
253/**
254 * List of active monitoring requests.
255 */
256static struct ClientMonitorRecord *monitor_tail;
257
258/**
259 * Hashmap for fast key based lookup, maps keys to `struct ClientQueryRecord` entries.
260 */
261static struct GNUNET_CONTAINER_MultiHashMap *forward_map;
262
263/**
264 * Heap with all of our client's request, sorted by retry time (earliest on top).
265 */
266static struct GNUNET_CONTAINER_Heap *retry_heap;
267
268/**
269 * Task that re-transmits requests (using retry_heap).
270 */
271static struct GNUNET_SCHEDULER_Task * retry_task;
272
273
274/**
275 * Task run to check for messages that need to be sent to a client.
276 *
277 * @param client a ClientList, containing the client and any messages to be sent to it
278 */
279static void
280process_pending_messages (struct ClientList *client);
281
282
283/**
284 * Callback called as a result of issuing a GNUNET_SERVER_notify_transmit_ready
285 * request. A ClientList is passed as closure, take the head of the list
286 * and copy it into buf, which has the result of sending the message to the
287 * client.
288 *
289 * @param cls closure to this call
290 * @param size maximum number of bytes available to send
291 * @param buf where to copy the actual message to
292 *
293 * @return the number of bytes actually copied, 0 indicates failure
294 */
295static size_t
296send_reply_to_client (void *cls, size_t size, void *buf)
297{
298 struct ClientList *client = cls;
299 char *cbuf = buf;
300 struct PendingMessage *reply;
301 size_t off;
302 size_t msize;
303
304 client->transmit_handle = NULL;
305 if (buf == NULL)
306 {
307 /* client disconnected */
308 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
309 "Client %p disconnected, pending messages will be discarded\n",
310 client->client_handle);
311 return 0;
312 }
313 off = 0;
314 while ((NULL != (reply = client->pending_head)) &&
315 (size >= off + (msize = ntohs (reply->msg->size))))
316 {
317 GNUNET_CONTAINER_DLL_remove (client->pending_head, client->pending_tail,
318 reply);
319 memcpy (&cbuf[off], reply->msg, msize);
320 GNUNET_free (reply);
321 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting %u bytes to client %p\n",
322 msize, client->client_handle);
323 off += msize;
324 }
325 process_pending_messages (client);
326 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitted %u/%u bytes to client %p\n",
327 (unsigned int) off, (unsigned int) size, client->client_handle);
328 return off;
329}
330
331
332/**
333 * Task run to check for messages that need to be sent to a client.
334 *
335 * @param client a ClientList, containing the client and any messages to be sent to it
336 */
337static void
338process_pending_messages (struct ClientList *client)
339{
340 if ((client->pending_head == NULL) || (client->transmit_handle != NULL))
341 {
342 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
343 "Not asking for transmission to %p now: %s\n",
344 client->client_handle,
345 client->pending_head ==
346 NULL ? "no more messages" : "request already pending");
347 return;
348 }
349 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
350 "Asking for transmission of %u bytes to client %p\n",
351 ntohs (client->pending_head->msg->size), client->client_handle);
352 client->transmit_handle =
353 GNUNET_SERVER_notify_transmit_ready (client->client_handle,
354 ntohs (client->pending_head->
355 msg->size),
356 GNUNET_TIME_UNIT_FOREVER_REL,
357 &send_reply_to_client, client);
358}
359
360
361/**
362 * Add a PendingMessage to the clients list of messages to be sent
363 *
364 * @param client the active client to send the message to
365 * @param pending_message the actual message to send
366 */
367static void
368add_pending_message (struct ClientList *client,
369 struct PendingMessage *pending_message)
370{
371 GNUNET_CONTAINER_DLL_insert_tail (client->pending_head, client->pending_tail,
372 pending_message);
373 process_pending_messages (client);
374}
375
376
377/**
378 * Closure for 'forward_reply'
379 */
380struct ForwardReplyContext
381{
382
383 /**
384 * Actual message to send to matching clients.
385 */
386 struct PendingMessage *pm;
387
388 /**
389 * Embedded payload.
390 */
391 const void *data;
392
393 /**
394 * Type of the data.
395 */
396 enum GNUNET_BLOCK_Type type;
397
398 /**
399 * Number of bytes in data.
400 */
401 size_t data_size;
402
403 /**
404 * Do we need to copy 'pm' because it was already used?
405 */
406 int do_copy;
407
408};
409
410
411/**
412 * Find a client if it exists, add it otherwise.
413 *
414 * @param client the server handle to the client
415 *
416 * @return the client if found, a new client otherwise
417 */
418static struct ClientList *
419find_active_client (struct GNUNET_SERVER_Client *client)
420{
421 struct ClientList *pos = client_head;
422 struct ClientList *ret;
423
424 while (pos != NULL)
425 {
426 if (pos->client_handle == client)
427 return pos;
428 pos = pos->next;
429 }
430 ret = GNUNET_new (struct ClientList);
431 ret->client_handle = client;
432 GNUNET_CONTAINER_DLL_insert (client_head, client_tail, ret);
433 return ret;
434}
435
436
437/**
438 * Iterator over hash map entries that frees all entries
439 * associated with the given client.
440 *
441 * @param cls client to search for in source routes
442 * @param key current key code (ignored)
443 * @param value value in the hash map, a ClientQueryRecord
444 * @return #GNUNET_YES (we should continue to iterate)
445 */
446static int
447remove_client_records (void *cls, const struct GNUNET_HashCode * key, void *value)
448{
449 struct ClientList *client = cls;
450 struct ClientQueryRecord *record = value;
451
452 if (record->client != client)
453 return GNUNET_YES;
454 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
455 "Removing client %p's record for key %s\n", client,
456 GNUNET_h2s (key));
457 GNUNET_assert (GNUNET_YES ==
458 GNUNET_CONTAINER_multihashmap_remove (forward_map, key,
459 record));
460 if (NULL != record->hnode)
461 GNUNET_CONTAINER_heap_remove_node (record->hnode);
462 GNUNET_array_grow (record->seen_replies, record->seen_replies_count, 0);
463 GNUNET_free (record);
464 return GNUNET_YES;
465}
466
467
468/**
469 * Iterator over hash map entries that send a given reply to
470 * each of the matching clients. With some tricky recycling
471 * of the buffer.
472 *
473 * @param cls the 'struct ForwardReplyContext'
474 * @param key current key
475 * @param value value in the hash map, a ClientQueryRecord
476 * @return GNUNET_YES (we should continue to iterate),
477 * if the result is mal-formed, GNUNET_NO
478 */
479static int
480forward_reply (void *cls, const struct GNUNET_HashCode * key, void *value)
481{
482 struct ForwardReplyContext *frc = cls;
483 struct ClientQueryRecord *record = value;
484 struct PendingMessage *pm;
485 struct GNUNET_DHT_ClientResultMessage *reply;
486 enum GNUNET_BLOCK_EvaluationResult eval;
487 int do_free;
488 struct GNUNET_HashCode ch;
489 unsigned int i;
490
491 LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG,
492 "XVINE CLIENT-RESULT %s\n",
493 GNUNET_h2s_full (key));
494#if 0
495 if ((record->type != GNUNET_BLOCK_TYPE_ANY) && (record->type != frc->type))
496 {
497 LOG (GNUNET_ERROR_TYPE_DEBUG,
498 "Record type missmatch, not passing request for key %s to local client\n",
499 GNUNET_h2s (key));
500
501 GNUNET_STATISTICS_update (GDS_stats,
502 gettext_noop
503 ("# Key match, type mismatches in REPLY to CLIENT"),
504 1, GNUNET_NO);
505 return GNUNET_YES; /* type mismatch */
506 }
507#endif
508 GNUNET_CRYPTO_hash (frc->data, frc->data_size, &ch);
509 for (i = 0; i < record->seen_replies_count; i++)
510 if (0 == memcmp (&record->seen_replies[i], &ch, sizeof (struct GNUNET_HashCode)))
511 {
512 LOG (GNUNET_ERROR_TYPE_DEBUG,
513 "Duplicate reply, not passing request for key %s to local client\n",
514 GNUNET_h2s (key));
515 GNUNET_STATISTICS_update (GDS_stats,
516 gettext_noop
517 ("# Duplicate REPLIES to CLIENT request dropped"),
518 1, GNUNET_NO);
519 return GNUNET_YES; /* duplicate */
520 }
521 eval =
522 GNUNET_BLOCK_evaluate (GDS_block_context,
523 record->type,
524 GNUNET_BLOCK_EO_NONE,
525 key, NULL, 0,
526 record->xquery,
527 record->xquery_size,
528 frc->data,
529 frc->data_size);
530 LOG (GNUNET_ERROR_TYPE_DEBUG,
531 "Evaluation result is %d for key %s for local client's query\n",
532 (int) eval, GNUNET_h2s (key));
533 switch (eval)
534 {
535 case GNUNET_BLOCK_EVALUATION_OK_LAST:
536 do_free = GNUNET_YES;
537 break;
538 case GNUNET_BLOCK_EVALUATION_OK_MORE:
539 GNUNET_array_append (record->seen_replies, record->seen_replies_count, ch);
540 do_free = GNUNET_NO;
541 break;
542 case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE:
543 /* should be impossible to encounter here */
544 GNUNET_break (0);
545 return GNUNET_YES;
546 case GNUNET_BLOCK_EVALUATION_RESULT_INVALID:
547 GNUNET_break_op (0);
548 return GNUNET_NO;
549 case GNUNET_BLOCK_EVALUATION_REQUEST_VALID:
550 GNUNET_break (0);
551 return GNUNET_NO;
552 case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID:
553 GNUNET_break (0);
554 return GNUNET_NO;
555 case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT:
556 return GNUNET_YES;
557 case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED:
558 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
559 _("Unsupported block type (%u) in request!\n"), record->type);
560 return GNUNET_NO;
561 default:
562 GNUNET_break (0);
563 return GNUNET_NO;
564 }
565 if (GNUNET_NO == frc->do_copy)
566 {
567 /* first time, we can use the original data */
568 pm = frc->pm;
569 frc->do_copy = GNUNET_YES;
570 }
571 else
572 {
573 /* two clients waiting for same reply, must copy for queueing */
574 pm = GNUNET_malloc (sizeof (struct PendingMessage) +
575 ntohs (frc->pm->msg->size));
576 memcpy (pm, frc->pm,
577 sizeof (struct PendingMessage) + ntohs (frc->pm->msg->size));
578 pm->next = pm->prev = NULL;
579 pm->msg = (struct GNUNET_MessageHeader *) &pm[1];
580 }
581 GNUNET_STATISTICS_update (GDS_stats,
582 gettext_noop ("# RESULTS queued for clients"), 1,
583 GNUNET_NO);
584 reply = (struct GNUNET_DHT_ClientResultMessage *) &pm[1];
585 reply->unique_id = record->unique_id;
586 LOG (GNUNET_ERROR_TYPE_DEBUG,
587 "Queueing reply to query %s for client %p\n",
588 GNUNET_h2s (key),
589 record->client->client_handle);
590 add_pending_message (record->client, pm);
591 if (GNUNET_YES == do_free)
592 remove_client_records (record->client, key, record);
593 return GNUNET_YES;
594}
595
596
597/**
598 * Handle a reply we've received from another peer. If the reply
599 * matches any of our pending queries, forward it to the respective
600 * client(s).
601 *
602 * @param expiration when will the reply expire
603 * @param key the query this reply is for
604 * @param get_path_length number of peers in @a get_path
605 * @param get_path path the reply took on get
606 * @param put_path_length number of peers in @a put_path
607 * @param put_path path the reply took on put
608 * @param type type of the reply
609 * @param data_size number of bytes in @a data
610 * @param data application payload data
611 */
612void
613GDS_CLIENTS_handle_reply (struct GNUNET_TIME_Absolute expiration,
614 const struct GNUNET_HashCode *key,
615 unsigned int get_path_length,
616 const struct GNUNET_PeerIdentity *get_path,
617 unsigned int put_path_length,
618 const struct GNUNET_PeerIdentity *put_path,
619 enum GNUNET_BLOCK_Type type, size_t data_size,
620 const void *data)
621{
622 struct ForwardReplyContext frc;
623 struct PendingMessage *pm;
624 struct GNUNET_DHT_ClientResultMessage *reply;
625 struct GNUNET_PeerIdentity *paths;
626 size_t msize;
627
628 LOG (GNUNET_ERROR_TYPE_DEBUG,
629 "reply for key %s\n",
630 GNUNET_h2s (key));
631
632 if (NULL == GNUNET_CONTAINER_multihashmap_get (forward_map, key))
633 {
634 GNUNET_STATISTICS_update (GDS_stats,
635 gettext_noop
636 ("# REPLIES ignored for CLIENTS (no match)"), 1,
637 GNUNET_NO);
638 return; /* no matching request, fast exit! */
639 }
640 msize =
641 sizeof (struct GNUNET_DHT_ClientResultMessage) + data_size +
642 (get_path_length + put_path_length) * sizeof (struct GNUNET_PeerIdentity);
643 if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
644 {
645 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
646 _("Could not pass reply to client, message too big!\n"));
647 return;
648 }
649 DEBUG("reply FOR DATA_SIZE = %lu\n",msize);
650 pm = GNUNET_malloc (msize + sizeof (struct PendingMessage));
651 reply = (struct GNUNET_DHT_ClientResultMessage *) &pm[1];
652 pm->msg = &reply->header;
653 reply->header.size = htons ((uint16_t) msize);
654 reply->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_CLIENT_RESULT);
655 reply->type = htonl (type);
656 reply->get_path_length = htonl (get_path_length);
657 reply->put_path_length = htonl (put_path_length);
658 reply->unique_id = 0; /* filled in later */
659 reply->expiration = GNUNET_TIME_absolute_hton (expiration);
660 reply->key = *key;
661 paths = (struct GNUNET_PeerIdentity *) &reply[1];
662 memcpy (paths, put_path,
663 sizeof (struct GNUNET_PeerIdentity) * put_path_length);
664 memcpy (&paths[put_path_length], get_path,
665 sizeof (struct GNUNET_PeerIdentity) * get_path_length);
666 memcpy (&paths[get_path_length + put_path_length], data, data_size);
667 frc.do_copy = GNUNET_NO;
668 frc.pm = pm;
669 frc.data = data;
670 frc.data_size = data_size;
671 frc.type = type;
672 GNUNET_CONTAINER_multihashmap_get_multiple (forward_map, key, &forward_reply,
673 &frc);
674 if (GNUNET_NO == frc.do_copy)
675 {
676 /* did not match any of the requests, free! */
677 GNUNET_STATISTICS_update (GDS_stats,
678 gettext_noop
679 ("# REPLIES ignored for CLIENTS (no match)"), 1,
680 GNUNET_NO);
681 GNUNET_free (pm);
682 }
683}
684
685/**
686 * Check if some client is monitoring GET messages and notify
687 * them in that case.
688 *
689 * @param options Options, for instance RecordRoute, DemultiplexEverywhere.
690 * @param type The type of data in the request.
691 * @param hop_count Hop count so far.
692 * @param path_length number of entries in path (or 0 if not recorded).
693 * @param path peers on the GET path (or NULL if not recorded).
694 * @param desired_replication_level Desired replication level.
695 * @param key Key of the requested data.
696 */
697void
698GDS_CLIENTS_process_get (uint32_t options,
699 enum GNUNET_BLOCK_Type type,
700 uint32_t hop_count,
701 uint32_t desired_replication_level,
702 unsigned int path_length,
703 const struct GNUNET_PeerIdentity *path,
704 const struct GNUNET_HashCode * key)
705{
706 struct ClientMonitorRecord *m;
707 struct ClientList **cl;
708 unsigned int cl_size;
709
710 cl = NULL;
711 cl_size = 0;
712 for (m = monitor_head; NULL != m; m = m->next)
713 {
714 if ((GNUNET_BLOCK_TYPE_ANY == m->type || m->type == type) &&
715 (NULL == m->key ||
716 memcmp (key, m->key, sizeof(struct GNUNET_HashCode)) == 0))
717 {
718 struct PendingMessage *pm;
719 struct GNUNET_DHT_MonitorGetMessage *mmsg;
720 struct GNUNET_PeerIdentity *msg_path;
721 size_t msize;
722 unsigned int i;
723
724 /* Don't send duplicates */
725 for (i = 0; i < cl_size; i++)
726 if (cl[i] == m->client)
727 break;
728 if (i < cl_size)
729 continue;
730 GNUNET_array_append (cl, cl_size, m->client);
731
732 msize = path_length * sizeof (struct GNUNET_PeerIdentity);
733 msize += sizeof (struct GNUNET_DHT_MonitorGetMessage);
734 msize += sizeof (struct PendingMessage);
735 pm = GNUNET_malloc (msize);
736 mmsg = (struct GNUNET_DHT_MonitorGetMessage *) &pm[1];
737 pm->msg = &mmsg->header;
738 mmsg->header.size = htons (msize - sizeof (struct PendingMessage));
739 mmsg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_MONITOR_GET);
740 mmsg->options = htonl(options);
741 mmsg->type = htonl(type);
742 mmsg->hop_count = htonl(hop_count);
743 mmsg->desired_replication_level = htonl(desired_replication_level);
744 mmsg->get_path_length = htonl(path_length);
745 memcpy (&mmsg->key, key, sizeof (struct GNUNET_HashCode));
746 msg_path = (struct GNUNET_PeerIdentity *) &mmsg[1];
747 if (path_length > 0)
748 memcpy (msg_path, path,
749 path_length * sizeof (struct GNUNET_PeerIdentity));
750 add_pending_message (m->client, pm);
751 }
752 }
753 GNUNET_free_non_null (cl);
754}
755
756
757/**
758 * Check if some client is monitoring PUT messages and notify
759 * them in that case.
760 *
761 * @param options Options, for instance RecordRoute, DemultiplexEverywhere.
762 * @param type The type of data in the request.
763 * @param hop_count Hop count so far.
764 * @param path_length number of entries in path (or 0 if not recorded).
765 * @param path peers on the PUT path (or NULL if not recorded).
766 * @param desired_replication_level Desired replication level.
767 * @param exp Expiration time of the data.
768 * @param key Key under which data is to be stored.
769 * @param data Pointer to the data carried.
770 * @param size Number of bytes in data.
771 */
772void
773GDS_CLIENTS_process_put (uint32_t options,
774 enum GNUNET_BLOCK_Type type,
775 uint32_t hop_count,
776 uint32_t desired_replication_level,
777 unsigned int path_length,
778 const struct GNUNET_PeerIdentity *path,
779 struct GNUNET_TIME_Absolute exp,
780 const struct GNUNET_HashCode * key,
781 const void *data,
782 size_t size)
783{
784 struct ClientMonitorRecord *m;
785 struct ClientList **cl;
786 unsigned int cl_size;
787
788 cl = NULL;
789 cl_size = 0;
790 for (m = monitor_head; NULL != m; m = m->next)
791 {
792 if ((GNUNET_BLOCK_TYPE_ANY == m->type || m->type == type) &&
793 (NULL == m->key ||
794 memcmp (key, m->key, sizeof(struct GNUNET_HashCode)) == 0))
795 {
796 struct PendingMessage *pm;
797 struct GNUNET_DHT_MonitorPutMessage *mmsg;
798 struct GNUNET_PeerIdentity *msg_path;
799 size_t msize;
800 unsigned int i;
801
802 /* Don't send duplicates */
803 for (i = 0; i < cl_size; i++)
804 if (cl[i] == m->client)
805 break;
806 if (i < cl_size)
807 continue;
808 GNUNET_array_append (cl, cl_size, m->client);
809
810 msize = size;
811 msize += path_length * sizeof (struct GNUNET_PeerIdentity);
812 msize += sizeof (struct GNUNET_DHT_MonitorPutMessage);
813 msize += sizeof (struct PendingMessage);
814 pm = GNUNET_malloc (msize);
815 mmsg = (struct GNUNET_DHT_MonitorPutMessage *) &pm[1];
816 pm->msg = (struct GNUNET_MessageHeader *) mmsg;
817 mmsg->header.size = htons (msize - sizeof (struct PendingMessage));
818 mmsg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_MONITOR_PUT);
819 mmsg->options = htonl(options);
820 mmsg->type = htonl(type);
821 mmsg->hop_count = htonl(hop_count);
822 mmsg->desired_replication_level = htonl(desired_replication_level);
823 mmsg->put_path_length = htonl(path_length);
824 msg_path = (struct GNUNET_PeerIdentity *) &mmsg[1];
825 if (path_length > 0)
826 {
827 memcpy (msg_path, path,
828 path_length * sizeof (struct GNUNET_PeerIdentity));
829 }
830 mmsg->expiration_time = GNUNET_TIME_absolute_hton(exp);
831 memcpy (&mmsg->key, key, sizeof (struct GNUNET_HashCode));
832 if (size > 0)
833 memcpy (&msg_path[path_length], data, size);
834 add_pending_message (m->client, pm);
835 }
836 }
837 GNUNET_free_non_null (cl);
838}
839
840
841/**
842 * Route the given request via the DHT.
843 */
844static void
845transmit_request (struct ClientQueryRecord *cqr)
846{
847 GNUNET_STATISTICS_update (GDS_stats,
848 gettext_noop
849 ("# GET requests from clients injected"), 1,
850 GNUNET_NO);
851
852 LOG (GNUNET_ERROR_TYPE_DEBUG,
853 "Initiating GET for %s, replication %u, already have %u replies\n",
854 GNUNET_h2s (&cqr->key),
855 cqr->replication,
856 cqr->seen_replies_count);
857
858 GDS_NEIGHBOURS_handle_get (&cqr->key, cqr->type, cqr->msg_options,
859 cqr->replication);
860
861 /* exponential back-off for retries.
862 * max GNUNET_TIME_STD_EXPONENTIAL_BACKOFF_THRESHOLD (15 min) */
863 cqr->retry_frequency = GNUNET_TIME_STD_BACKOFF (cqr->retry_frequency);
864 cqr->retry_time = GNUNET_TIME_relative_to_absolute (cqr->retry_frequency);
865}
866
867
868/**
869 * Task that looks at the 'retry_heap' and transmits all of the requests
870 * on the heap that are ready for transmission. Then re-schedules
871 * itself (unless the heap is empty).
872 *
873 * @param cls unused
874 * @param tc scheduler context
875 */
876static void
877transmit_next_request_task (void *cls,
878 const struct GNUNET_SCHEDULER_TaskContext *tc)
879{
880 struct ClientQueryRecord *cqr;
881 struct GNUNET_TIME_Relative delay;
882
883 retry_task = NULL;
884 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
885 return;
886 while (NULL != (cqr = GNUNET_CONTAINER_heap_remove_root (retry_heap)))
887 {
888 cqr->hnode = NULL;
889 delay = GNUNET_TIME_absolute_get_remaining (cqr->retry_time);
890 if (delay.rel_value_us > 0)
891 {
892 cqr->hnode =
893 GNUNET_CONTAINER_heap_insert (retry_heap, cqr,
894 cqr->retry_time.abs_value_us);
895 retry_task =
896 GNUNET_SCHEDULER_add_delayed (delay, &transmit_next_request_task,
897 NULL);
898 return;
899 }
900 transmit_request (cqr);
901 cqr->hnode =
902 GNUNET_CONTAINER_heap_insert (retry_heap, cqr,
903 cqr->retry_time.abs_value_us);
904 }
905}
906
907
908/**
909 * Handler for PUT messages.
910 *
911 * @param cls closure for the service
912 * @param client the client we received this message from
913 * @param message the actual message received
914 */
915static void
916handle_dht_local_put (void *cls, struct GNUNET_SERVER_Client *client,
917 const struct GNUNET_MessageHeader *message)
918{
919 const struct GNUNET_DHT_ClientPutMessage *put_msg;
920 struct PendingMessage *pm;
921 struct GNUNET_DHT_ClientPutConfirmationMessage *conf;
922 uint16_t size;
923
924 size = ntohs (message->size);
925 if (size < sizeof (struct GNUNET_DHT_ClientPutMessage))
926 {
927 GNUNET_break (0);
928 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
929 return;
930 }
931 GNUNET_STATISTICS_update (GDS_stats,
932 gettext_noop
933 ("# PUT requests received from clients"), 1,
934 GNUNET_NO);
935 put_msg = (const struct GNUNET_DHT_ClientPutMessage *) message;
936 LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG, "X-VINE DHT CLIENT-PUT %s\n",
937 GNUNET_h2s_full (&put_msg->key));
938 /* give to local clients */
939 LOG (GNUNET_ERROR_TYPE_DEBUG,
940 "Handling local PUT of %u-bytes for query %s\n",
941 size - sizeof (struct GNUNET_DHT_ClientPutMessage),
942 GNUNET_h2s (&put_msg->key));
943 DEBUG("PUT doing put i = %s\n",GNUNET_h2s(&(put_msg->key)));
944 GDS_CLIENTS_handle_reply (GNUNET_TIME_absolute_ntoh (put_msg->expiration),
945 &put_msg->key, 0, NULL, 0, NULL,
946 ntohl (put_msg->type),
947 size - sizeof (struct GNUNET_DHT_ClientPutMessage),
948 &put_msg[1]);
949
950 GDS_NEIGHBOURS_handle_put (&put_msg->key,
951 ntohl (put_msg->type), ntohl (put_msg->options),
952 ntohl (put_msg->desired_replication_level),
953 GNUNET_TIME_absolute_ntoh (put_msg->expiration),
954 &put_msg[1],
955 size - sizeof (struct GNUNET_DHT_ClientPutMessage));
956 pm = GNUNET_malloc (sizeof (struct PendingMessage) +
957 sizeof (struct GNUNET_DHT_ClientPutConfirmationMessage));
958 conf = (struct GNUNET_DHT_ClientPutConfirmationMessage *) &pm[1];
959 conf->header.size = htons (sizeof (struct GNUNET_DHT_ClientPutConfirmationMessage));
960 conf->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_CLIENT_PUT_OK);
961 conf->reserved = htonl (0);
962 conf->unique_id = put_msg->unique_id;
963 pm->msg = &conf->header;
964 add_pending_message (find_active_client (client), pm);
965 GNUNET_SERVER_receive_done (client, GNUNET_OK);
966}
967
968
969/**
970 * Handler for DHT GET messages from the client.
971 *
972 * @param cls closure for the service
973 * @param client the client we received this message from
974 * @param message the actual message received
975 */
976static void
977handle_dht_local_get (void *cls, struct GNUNET_SERVER_Client *client,
978 const struct GNUNET_MessageHeader *message)
979{
980 const struct GNUNET_DHT_ClientGetMessage *get;
981 struct ClientQueryRecord *cqr;
982 size_t xquery_size;
983 const char *xquery;
984 uint16_t size;
985
986 size = ntohs (message->size);
987 if (size < sizeof (struct GNUNET_DHT_ClientGetMessage))
988 {
989 GNUNET_break (0);
990 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
991 return;
992 }
993 xquery_size = size - sizeof (struct GNUNET_DHT_ClientGetMessage);
994 get = (const struct GNUNET_DHT_ClientGetMessage *) message;
995 xquery = (const char *) &get[1];
996 GNUNET_STATISTICS_update (GDS_stats,
997 gettext_noop
998 ("# GET requests received from clients"), 1,
999 GNUNET_NO);
1000 LOG (GNUNET_ERROR_TYPE_DEBUG,
1001 "Received GET request for %s from local client %p, xq: %.*s\n",
1002 GNUNET_h2s (&get->key), client, xquery_size, xquery);
1003
1004 LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG, "X-VINE CLIENT-GET %s\n",
1005 GNUNET_h2s_full (&get->key));
1006
1007
1008 cqr = GNUNET_malloc (sizeof (struct ClientQueryRecord) + xquery_size);
1009 cqr->key = get->key;
1010 cqr->client = find_active_client (client);
1011 cqr->xquery = (void *) &cqr[1];
1012 memcpy (&cqr[1], xquery, xquery_size);
1013 cqr->hnode = GNUNET_CONTAINER_heap_insert (retry_heap, cqr, 0);
1014 cqr->retry_frequency = GNUNET_TIME_UNIT_SECONDS;
1015 cqr->retry_time = GNUNET_TIME_absolute_get ();
1016 cqr->unique_id = get->unique_id;
1017 cqr->xquery_size = xquery_size;
1018 cqr->replication = ntohl (get->desired_replication_level);
1019 cqr->msg_options = ntohl (get->options);
1020 cqr->type = ntohl (get->type);
1021
1022 // FIXME use cqr->key, set multihashmap create to GNUNET_YES
1023 GNUNET_CONTAINER_multihashmap_put (forward_map, &get->key, cqr,
1024 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1025
1026 struct GNUNET_PeerIdentity my_identity;
1027 my_identity = GDS_NEIGHBOURS_get_my_id();
1028 GDS_CLIENTS_process_get (ntohl (get->options),
1029 ntohl (get->type),
1030 0,
1031 ntohl (get->desired_replication_level),
1032 1,
1033 &my_identity,
1034 &get->key);
1035 /* start remote requests */
1036 if (NULL != retry_task)
1037 GNUNET_SCHEDULER_cancel (retry_task);
1038 retry_task = GNUNET_SCHEDULER_add_now (&transmit_next_request_task, NULL);
1039 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1040}
1041
1042
1043/**
1044 * Closure for 'find_by_unique_id'.
1045 */
1046struct FindByUniqueIdContext
1047{
1048 /**
1049 * Where to store the result, if found.
1050 */
1051 struct ClientQueryRecord *cqr;
1052
1053 uint64_t unique_id;
1054};
1055
1056
1057/**
1058 * Function called for each existing DHT record for the given
1059 * query. Checks if it matches the UID given in the closure
1060 * and if so returns the entry as a result.
1061 *
1062 * @param cls the search context
1063 * @param key query for the lookup (not used)
1064 * @param value the 'struct ClientQueryRecord'
1065 * @return GNUNET_YES to continue iteration (result not yet found)
1066 */
1067static int
1068find_by_unique_id (void *cls,
1069 const struct GNUNET_HashCode *key,
1070 void *value)
1071{
1072 struct FindByUniqueIdContext *fui_ctx = cls;
1073 struct ClientQueryRecord *cqr = value;
1074
1075 if (cqr->unique_id != fui_ctx->unique_id)
1076 return GNUNET_YES;
1077 fui_ctx->cqr = cqr;
1078 return GNUNET_NO;
1079}
1080
1081
1082/**
1083 * Handler for "GET result seen" messages from the client.
1084 *
1085 * @param cls closure for the service
1086 * @param client the client we received this message from
1087 * @param message the actual message received
1088 */
1089static void
1090handle_dht_local_get_result_seen (void *cls, struct GNUNET_SERVER_Client *client,
1091 const struct GNUNET_MessageHeader *message)
1092{
1093 const struct GNUNET_DHT_ClientGetResultSeenMessage *seen;
1094 uint16_t size;
1095 unsigned int hash_count;
1096 unsigned int old_count;
1097 const struct GNUNET_HashCode *hc;
1098 struct FindByUniqueIdContext fui_ctx;
1099 struct ClientQueryRecord *cqr;
1100
1101 size = ntohs (message->size);
1102 if (size < sizeof (struct GNUNET_DHT_ClientGetResultSeenMessage))
1103 {
1104 GNUNET_break (0);
1105 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1106 return;
1107 }
1108 seen = (const struct GNUNET_DHT_ClientGetResultSeenMessage *) message;
1109 hash_count = (size - sizeof (struct GNUNET_DHT_ClientGetResultSeenMessage)) / sizeof (struct GNUNET_HashCode);
1110 if (size != sizeof (struct GNUNET_DHT_ClientGetResultSeenMessage) + hash_count * sizeof (struct GNUNET_HashCode))
1111 {
1112 GNUNET_break (0);
1113 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1114 return;
1115 }
1116 hc = (const struct GNUNET_HashCode*) &seen[1];
1117 fui_ctx.unique_id = seen->unique_id;
1118 fui_ctx.cqr = NULL;
1119 GNUNET_CONTAINER_multihashmap_get_multiple (forward_map,
1120 &seen->key,
1121 &find_by_unique_id,
1122 &fui_ctx);
1123 if (NULL == (cqr = fui_ctx.cqr))
1124 {
1125 GNUNET_break (0);
1126 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1127 return;
1128 }
1129 /* finally, update 'seen' list */
1130 old_count = cqr->seen_replies_count;
1131 GNUNET_array_grow (cqr->seen_replies,
1132 cqr->seen_replies_count,
1133 cqr->seen_replies_count + hash_count);
1134 memcpy (&cqr->seen_replies[old_count],
1135 hc,
1136 sizeof (struct GNUNET_HashCode) * hash_count);
1137}
1138
1139
1140/**
1141 * Closure for 'remove_by_unique_id'.
1142 */
1143struct RemoveByUniqueIdContext
1144{
1145 /**
1146 * Client that issued the removal request.
1147 */
1148 struct ClientList *client;
1149
1150 /**
1151 * Unique ID of the request.
1152 */
1153 uint64_t unique_id;
1154};
1155
1156
1157/**
1158 * Iterator over hash map entries that frees all entries
1159 * that match the given client and unique ID.
1160 *
1161 * @param cls unique ID and client to search for in source routes
1162 * @param key current key code
1163 * @param value value in the hash map, a ClientQueryRecord
1164 * @return GNUNET_YES (we should continue to iterate)
1165 */
1166static int
1167remove_by_unique_id (void *cls, const struct GNUNET_HashCode * key, void *value)
1168{
1169 const struct RemoveByUniqueIdContext *ctx = cls;
1170 struct ClientQueryRecord *record = value;
1171
1172 if (record->unique_id != ctx->unique_id)
1173 return GNUNET_YES;
1174 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1175 "Removing client %p's record for key %s (by unique id)\n",
1176 ctx->client->client_handle, GNUNET_h2s (key));
1177 return remove_client_records (ctx->client, key, record);
1178}
1179
1180
1181/**
1182 * Handler for any generic DHT stop messages, calls the appropriate handler
1183 * depending on message type (if processed locally)
1184 *
1185 * @param cls closure for the service
1186 * @param client the client we received this message from
1187 * @param message the actual message received
1188 *
1189 */
1190static void
1191handle_dht_local_get_stop (void *cls, struct GNUNET_SERVER_Client *client,
1192 const struct GNUNET_MessageHeader *message)
1193{
1194 const struct GNUNET_DHT_ClientGetStopMessage *dht_stop_msg =
1195 (const struct GNUNET_DHT_ClientGetStopMessage *) message;
1196 struct RemoveByUniqueIdContext ctx;
1197
1198 GNUNET_STATISTICS_update (GDS_stats,
1199 gettext_noop
1200 ("# GET STOP requests received from clients"), 1,
1201 GNUNET_NO);
1202 LOG (GNUNET_ERROR_TYPE_DEBUG,
1203 "Received GET STOP request for %s from local client %p\n",
1204 client, GNUNET_h2s (&dht_stop_msg->key));
1205 ctx.client = find_active_client (client);
1206 ctx.unique_id = dht_stop_msg->unique_id;
1207 GNUNET_CONTAINER_multihashmap_get_multiple (forward_map, &dht_stop_msg->key,
1208 &remove_by_unique_id, &ctx);
1209 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1210}
1211
1212
1213/**
1214 * Handler for monitor start messages
1215 *
1216 * @param cls closure for the service
1217 * @param client the client we received this message from
1218 * @param message the actual message received
1219 *
1220 */
1221static void
1222handle_dht_local_monitor (void *cls, struct GNUNET_SERVER_Client *client,
1223 const struct GNUNET_MessageHeader *message)
1224{
1225 struct ClientMonitorRecord *r;
1226 const struct GNUNET_DHT_MonitorStartStopMessage *msg;
1227
1228 msg = (struct GNUNET_DHT_MonitorStartStopMessage *) message;
1229 r = GNUNET_new (struct ClientMonitorRecord);
1230
1231 r->client = find_active_client(client);
1232 r->type = ntohl(msg->type);
1233 r->get = ntohs(msg->get);
1234 r->get_resp = ntohs(msg->get_resp);
1235 r->put = ntohs(msg->put);
1236 if (0 == ntohs(msg->filter_key))
1237 r->key = NULL;
1238 else
1239 {
1240 r->key = GNUNET_new (struct GNUNET_HashCode);
1241 memcpy (r->key, &msg->key, sizeof (struct GNUNET_HashCode));
1242 }
1243 GNUNET_CONTAINER_DLL_insert (monitor_head, monitor_tail, r);
1244 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1245}
1246
1247
1248/**
1249 * Handler for monitor stop messages
1250 *
1251 * @param cls closure for the service
1252 * @param client the client we received this message from
1253 * @param message the actual message received
1254 *
1255 */
1256static void
1257handle_dht_local_monitor_stop (void *cls, struct GNUNET_SERVER_Client *client,
1258 const struct GNUNET_MessageHeader *message)
1259{
1260 struct ClientMonitorRecord *r;
1261 const struct GNUNET_DHT_MonitorStartStopMessage *msg;
1262 int keys_match;
1263
1264 msg = (struct GNUNET_DHT_MonitorStartStopMessage *) message;
1265 r = monitor_head;
1266
1267 while (NULL != r)
1268 {
1269 if (NULL == r->key)
1270 keys_match = (0 == ntohs(msg->filter_key));
1271 else
1272 {
1273 keys_match = (0 != ntohs(msg->filter_key)
1274 && !memcmp(r->key, &msg->key, sizeof(struct GNUNET_HashCode)));
1275 }
1276 if (find_active_client(client) == r->client
1277 && ntohl(msg->type) == r->type
1278 && r->get == msg->get
1279 && r->get_resp == msg->get_resp
1280 && r->put == msg->put
1281 && keys_match
1282 )
1283 {
1284 GNUNET_CONTAINER_DLL_remove (monitor_head, monitor_tail, r);
1285 GNUNET_free_non_null (r->key);
1286 GNUNET_free (r);
1287 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1288 return; /* Delete only ONE entry */
1289 }
1290 r = r->next;
1291 }
1292
1293 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1294}
1295
1296
1297#if ENABLE_MALICIOUS
1298/**
1299 * Handler for act malicious message.
1300 *
1301 * @param cls closure for the service
1302 * @param client the client we received this message from
1303 * @param message the actual message received
1304 *
1305 */
1306static void
1307handle_dht_act_malicious (void *cls, struct GNUNET_SERVER_Client *client,
1308 const struct GNUNET_MessageHeader *message)
1309{
1310 const struct GNUNET_DHT_ActMaliciousMessage *msg;
1311 struct PendingMessage *pm;
1312 struct GNUNET_DHT_ClientActMaliciousConfirmationMessage *conf;
1313 unsigned int malicious_action;
1314
1315 msg = (const struct GNUNET_DHT_ActMaliciousMessage *)message;
1316 malicious_action = msg->action;
1317
1318 if(GNUNET_OK == GDS_NEIGHBOURS_act_malicious (malicious_action))
1319 {
1320 pm = GNUNET_malloc (sizeof (struct PendingMessage) +
1321 sizeof (struct GNUNET_DHT_ClientActMaliciousConfirmationMessage));
1322 conf = (struct GNUNET_DHT_ClientActMaliciousConfirmationMessage *) &pm[1];
1323 conf->header.size = htons (sizeof (struct GNUNET_DHT_ClientActMaliciousConfirmationMessage));
1324 conf->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_CLIENT_ACT_MALICIOUS_OK);
1325 pm->msg = &conf->header;
1326 add_pending_message (find_active_client (client), pm);
1327 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1328 }
1329}
1330#endif
1331
1332
1333/**
1334 * Functions with this signature are called whenever a client
1335 * is disconnected on the network level.
1336 *
1337 * @param cls closure (NULL for dht)
1338 * @param client identification of the client; NULL
1339 * for the last call when the server is destroyed
1340 */
1341static void
1342handle_client_disconnect (void *cls,
1343 struct GNUNET_SERVER_Client *client)
1344{
1345 struct ClientList *pos;
1346 struct PendingMessage *reply;
1347 struct ClientMonitorRecord *monitor;
1348
1349 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1350 "Local client %p disconnects\n",
1351 client);
1352 pos = find_active_client (client);
1353 GNUNET_CONTAINER_DLL_remove (client_head, client_tail, pos);
1354 if (pos->transmit_handle != NULL)
1355 GNUNET_SERVER_notify_transmit_ready_cancel (pos->transmit_handle);
1356 while (NULL != (reply = pos->pending_head))
1357 {
1358 GNUNET_CONTAINER_DLL_remove (pos->pending_head, pos->pending_tail, reply);
1359 GNUNET_free (reply);
1360 }
1361 monitor = monitor_head;
1362 while (NULL != monitor)
1363 {
1364 if (monitor->client == pos)
1365 {
1366 struct ClientMonitorRecord *next;
1367
1368 GNUNET_free_non_null (monitor->key);
1369 next = monitor->next;
1370 GNUNET_CONTAINER_DLL_remove (monitor_head, monitor_tail, monitor);
1371 GNUNET_free (monitor);
1372 monitor = next;
1373 }
1374 else
1375 monitor = monitor->next;
1376 }
1377 GNUNET_CONTAINER_multihashmap_iterate (forward_map, &remove_client_records,
1378 pos);
1379 GNUNET_free (pos);
1380}
1381
1382
1383
1384/**
1385 * Initialize client subsystem.
1386 *
1387 * @param server the initialized server
1388 */
1389void
1390GDS_CLIENTS_init (struct GNUNET_SERVER_Handle *server)
1391{
1392 static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = {
1393 {&handle_dht_local_put, NULL,
1394 GNUNET_MESSAGE_TYPE_DHT_CLIENT_PUT, 0},
1395 {&handle_dht_local_get, NULL,
1396 GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET, 0},
1397 {&handle_dht_local_get_stop, NULL,
1398 GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_STOP,
1399 sizeof (struct GNUNET_DHT_ClientGetStopMessage)},
1400 {&handle_dht_local_monitor, NULL,
1401 GNUNET_MESSAGE_TYPE_DHT_MONITOR_START,
1402 sizeof (struct GNUNET_DHT_MonitorStartStopMessage)},
1403 {&handle_dht_local_monitor_stop, NULL,
1404 GNUNET_MESSAGE_TYPE_DHT_MONITOR_STOP,
1405 sizeof (struct GNUNET_DHT_MonitorStartStopMessage)},
1406 {&handle_dht_local_get_result_seen, NULL,
1407 GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_RESULTS_KNOWN, 0},
1408 #if ENABLE_MALICIOUS
1409 {&handle_dht_act_malicious, NULL,
1410 GNUNET_MESSAGE_TYPE_DHT_ACT_MALICIOUS,
1411 sizeof (struct GNUNET_DHT_ActMaliciousMessage)},
1412 #endif
1413 {NULL, NULL, 0, 0}
1414 };
1415 forward_map = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_NO);
1416 retry_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1417 GNUNET_SERVER_add_handlers (server, plugin_handlers);
1418 GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
1419}
1420
1421
1422/**
1423 * Shutdown client subsystem.
1424 */
1425void
1426GDS_CLIENTS_done ()
1427{
1428 GNUNET_assert (client_head == NULL);
1429 GNUNET_assert (client_tail == NULL);
1430 if (NULL != retry_task)
1431 {
1432 GNUNET_SCHEDULER_cancel (retry_task);
1433 retry_task = NULL;
1434 }
1435 if (NULL != retry_heap)
1436 {
1437 GNUNET_assert (0 == GNUNET_CONTAINER_heap_get_size (retry_heap));
1438 GNUNET_CONTAINER_heap_destroy (retry_heap);
1439 retry_heap = NULL;
1440 }
1441 if (NULL != forward_map)
1442 {
1443 GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (forward_map));
1444 GNUNET_CONTAINER_multihashmap_destroy (forward_map);
1445 forward_map = NULL;
1446 }
1447}
1448
1449/* end of gnunet-service-dht_clients.c */
diff --git a/src/dht/gnunet-service-wdht_clients.h b/src/dht/gnunet-service-wdht_clients.h
new file mode 100644
index 000000000..f1781332c
--- /dev/null
+++ b/src/dht/gnunet-service-wdht_clients.h
@@ -0,0 +1,149 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file dht/gnunet-service-xdht_clients.h
23 * @brief GNUnet DHT service's client management code
24 * @author Christian Grothoff
25 * @author Nathan Evans
26 */
27#ifndef GNUNET_SERVICE_DHT_CLIENT_H
28#define GNUNET_SERVICE_DHT_CLIENT_H
29
30#include "gnunet_util_lib.h"
31#include "gnunet_block_lib.h"
32
33/**
34 * Handle a reply we've received from another peer. If the reply
35 * matches any of our pending queries, forward it to the respective
36 * client(s).
37 *
38 * @param expiration when will the reply expire
39 * @param key the query this reply is for
40 * @param get_path_length number of peers in @a get_path
41 * @param get_path path the reply took on get
42 * @param put_path_length number of peers in @a put_path
43 * @param put_path path the reply took on put
44 * @param type type of the reply
45 * @param data_size number of bytes in @a data
46 * @param data application payload data
47 */
48void
49GDS_CLIENTS_handle_reply (struct GNUNET_TIME_Absolute expiration,
50 const struct GNUNET_HashCode *key,
51 unsigned int get_path_length,
52 const struct GNUNET_PeerIdentity *get_path,
53 unsigned int put_path_length,
54 const struct GNUNET_PeerIdentity *put_path,
55 enum GNUNET_BLOCK_Type type, size_t data_size,
56 const void *data);
57
58
59/**
60 * Check if some client is monitoring GET messages and notify
61 * them in that case.
62 *
63 * @param options Options, for instance RecordRoute, DemultiplexEverywhere.
64 * @param type The type of data in the request.
65 * @param hop_count Hop count so far.
66 * @param path_length number of entries in path (or 0 if not recorded).
67 * @param path peers on the GET path (or NULL if not recorded).
68 * @param desired_replication_level Desired replication level.
69 * @param key Key of the requested data.
70 */
71void
72GDS_CLIENTS_process_get (uint32_t options,
73 enum GNUNET_BLOCK_Type type,
74 uint32_t hop_count,
75 uint32_t desired_replication_level,
76 unsigned int path_length,
77 const struct GNUNET_PeerIdentity *path,
78 const struct GNUNET_HashCode *key);
79
80
81/**
82 * Check if some client is monitoring GET RESP messages and notify
83 * them in that case.
84 *
85 * @param type The type of data in the result.
86 * @param get_path Peers on GET path (or NULL if not recorded).
87 * @param get_path_length number of entries in @a get_path.
88 * @param put_path peers on the PUT path (or NULL if not recorded).
89 * @param put_path_length number of entries in @a get_path.
90 * @param exp Expiration time of the data.
91 * @param key Key of the @a data.
92 * @param data Pointer to the result data.
93 * @param size Number of bytes in @a data.
94 */
95void
96GDS_CLIENTS_process_get_resp (enum GNUNET_BLOCK_Type type,
97 const struct GNUNET_PeerIdentity *get_path,
98 unsigned int get_path_length,
99 const struct GNUNET_PeerIdentity *put_path,
100 unsigned int put_path_length,
101 struct GNUNET_TIME_Absolute exp,
102 const struct GNUNET_HashCode * key,
103 const void *data,
104 size_t size);
105
106
107/**
108 * Check if some client is monitoring PUT messages and notify
109 * them in that case.
110 *
111 * @param options Options, for instance RecordRoute, DemultiplexEverywhere.
112 * @param type The type of data in the request.
113 * @param hop_count Hop count so far.
114 * @param path_length number of entries in path (or 0 if not recorded).
115 * @param path peers on the PUT path (or NULL if not recorded).
116 * @param desired_replication_level Desired replication level.
117 * @param exp Expiration time of the data.
118 * @param key Key under which data is to be stored.
119 * @param data Pointer to the data carried.
120 * @param size Number of bytes in data.
121 */
122void
123GDS_CLIENTS_process_put (uint32_t options,
124 enum GNUNET_BLOCK_Type type,
125 uint32_t hop_count,
126 uint32_t desired_replication_level,
127 unsigned int path_length,
128 const struct GNUNET_PeerIdentity *path,
129 struct GNUNET_TIME_Absolute exp,
130 const struct GNUNET_HashCode * key,
131 const void *data,
132 size_t size);
133
134/**
135 * Initialize client subsystem.
136 *
137 * @param server the initialized server
138 */
139void
140GDS_CLIENTS_init (struct GNUNET_SERVER_Handle *server);
141
142
143/**
144 * Shutdown client subsystem.
145 */
146void
147GDS_CLIENTS_done (void);
148
149#endif
diff --git a/src/dht/gnunet-service-wdht_datacache.c b/src/dht/gnunet-service-wdht_datacache.c
new file mode 100644
index 000000000..571342f36
--- /dev/null
+++ b/src/dht/gnunet-service-wdht_datacache.c
@@ -0,0 +1,381 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file dht/gnunet-service-dht_datacache.c
23 * @brief GNUnet DHT service's datacache integration
24 * @author Christian Grothoff
25 * @author Nathan Evans
26 */
27#include "platform.h"
28#include "gnunet_datacache_lib.h"
29#include "gnunet-service-wdht_clients.h"
30#include "gnunet-service-wdht_datacache.h"
31#include "gnunet-service-wdht_routing.h"
32#include "gnunet-service-wdht_neighbours.h"
33#include "gnunet-service-dht.h"
34
35#define LOG(kind,...) GNUNET_log_from (kind, "dht-dtcache",__VA_ARGS__)
36
37#define DEBUG(...) \
38 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
39
40/**
41 * Handle to the datacache service (for inserting/retrieving data)
42 */
43static struct GNUNET_DATACACHE_Handle *datacache;
44
45
46/**
47 * Handle a datum we've received from another peer. Cache if
48 * possible.
49 *
50 * @param expiration when will the reply expire
51 * @param key the query this reply is for
52 * @param put_path_length number of peers in 'put_path'
53 * @param put_path path the reply took on put
54 * @param type type of the reply
55 * @param data_size number of bytes in 'data'
56 * @param data application payload data
57 */
58void
59GDS_DATACACHE_handle_put (struct GNUNET_TIME_Absolute expiration,
60 const struct GNUNET_HashCode * key,
61 unsigned int put_path_length,
62 const struct GNUNET_PeerIdentity *put_path,
63 enum GNUNET_BLOCK_Type type, size_t data_size,
64 const void *data)
65{
66 int r;
67
68 if (NULL == datacache)
69 {
70 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
71 _("%s request received, but have no datacache!\n"), "PUT");
72 return;
73 }
74 if (data_size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
75 {
76 GNUNET_break (0);
77 return;
78 }
79
80 /* Put size is actual data size plus struct overhead plus path length (if any) */
81 GNUNET_STATISTICS_update (GDS_stats,
82 gettext_noop ("# ITEMS stored in datacache"), 1,
83 GNUNET_NO);
84
85 struct GNUNET_PeerIdentity peer = GDS_NEIGHBOURS_get_my_id();
86 DEBUG("DATACACHE_PUT KEY = %s, peer = %s\n",GNUNET_h2s(key),GNUNET_i2s(&peer));
87 r = GNUNET_DATACACHE_put (datacache, key, data_size, data, type, expiration,
88 put_path_length, put_path);
89 LOG (GNUNET_ERROR_TYPE_DEBUG,
90 "DATACACHE PUT for key %s [%u] completed (%d) after %u hops\n",
91 GNUNET_h2s (key), data_size, r, put_path_length);
92}
93
94/**
95 * List of peers in the get path.
96 */
97struct GetPath
98{
99 /**
100 * Pointer to next item in the list
101 */
102 struct GetPath *next;
103
104 /**
105 * Pointer to previous item in the list
106 */
107 struct GetPath *prev;
108
109 /**
110 * An element in the get path.
111 */
112 struct GNUNET_PeerIdentity peer;
113};
114
115
116/**
117 * Context containing information about a GET request.
118 */
119struct GetRequestContext
120{
121 /**
122 * extended query (see gnunet_block_lib.h).
123 */
124 const void *xquery;
125
126 /**
127 * Bloomfilter to filter out duplicate replies (updated)
128 */
129 struct GNUNET_CONTAINER_BloomFilter **reply_bf;
130
131 /**
132 * The key this request was about
133 */
134 struct GNUNET_HashCode key;
135
136 /**
137 * Number of bytes in xquery.
138 */
139 size_t xquery_size;
140
141 /**
142 * Mutator value for the reply_bf, see gnunet_block_lib.h
143 */
144 uint32_t reply_bf_mutator;
145
146 /**
147 * Total number of peers in get path.
148 */
149 unsigned int get_path_length;
150
151 /**
152 * Return value to give back.
153 */
154 enum GNUNET_BLOCK_EvaluationResult eval;
155
156 /**
157 * Peeer which has the data for the key.
158 */
159 struct GNUNET_PeerIdentity source_peer;
160
161 /**
162 * Next hop to forward the get result to.
163 */
164 struct GNUNET_PeerIdentity next_hop;
165
166 /**
167 * Head of get path.
168 */
169 struct GetPath *head;
170
171 /**
172 * Tail of get path.
173 */
174 struct GetPath *tail;
175
176 /* get_path */
177};
178
179
180/**
181 * Iterator for local get request results,
182 *
183 * @param cls closure for iterator, a `struct GetRequestContext`
184 * @param key the key this data is stored under
185 * @param size the size of the data identified by key
186 * @param data the actual data
187 * @param type the type of the data
188 * @param exp when does this value expire?
189 * @param put_path_length number of peers in @a put_path
190 * @param put_path path the reply took on put
191 * @return #GNUNET_OK to continue iteration, anything else
192 * to stop iteration.
193 */
194static int
195datacache_get_iterator (void *cls,
196 const struct GNUNET_HashCode *key,
197 size_t size,
198 const char *data,
199 enum GNUNET_BLOCK_Type type,
200 struct GNUNET_TIME_Absolute exp,
201 unsigned int put_path_length,
202 const struct GNUNET_PeerIdentity *put_path)
203{
204 struct GetRequestContext *ctx = cls;
205 enum GNUNET_BLOCK_EvaluationResult eval;
206
207 eval =
208 GNUNET_BLOCK_evaluate (GDS_block_context,
209 type,
210 GNUNET_BLOCK_EO_NONE,
211 key,
212 ctx->reply_bf,
213 ctx->reply_bf_mutator,
214 ctx->xquery,
215 ctx->xquery_size,
216 data,
217 size);
218 LOG (GNUNET_ERROR_TYPE_DEBUG,
219 "Found reply for query %s in datacache, evaluation result is %d\n",
220 GNUNET_h2s (key), (int) eval);
221 ctx->eval = eval;
222
223 switch (eval)
224 {
225 case GNUNET_BLOCK_EVALUATION_OK_MORE:
226 case GNUNET_BLOCK_EVALUATION_OK_LAST:
227 /* forward to local clients */
228 GNUNET_STATISTICS_update (GDS_stats,
229 gettext_noop
230 ("# Good RESULTS found in datacache"), 1,
231 GNUNET_NO);
232 struct GNUNET_PeerIdentity *get_path;
233 get_path = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) *
234 ctx->get_path_length);
235 struct GetPath *iterator;
236 iterator = ctx->head;
237 int i = 0;
238 while (i < ctx->get_path_length)
239 {
240 get_path[i] = iterator->peer;
241 i++;
242 iterator = iterator->next;
243 }
244 GDS_NEIGHBOURS_send_get_result (key,type, &(ctx->next_hop),&(ctx->source_peer),
245 put_path_length, put_path, ctx->get_path_length,
246 get_path, exp, data, size );
247 GNUNET_free_non_null (get_path);
248
249 break;
250 case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE:
251 GNUNET_STATISTICS_update (GDS_stats,
252 gettext_noop
253 ("# Duplicate RESULTS found in datacache"), 1,
254 GNUNET_NO);
255 break;
256 case GNUNET_BLOCK_EVALUATION_RESULT_INVALID:
257 GNUNET_STATISTICS_update (GDS_stats,
258 gettext_noop
259 ("# Invalid RESULTS found in datacache"), 1,
260 GNUNET_NO);
261 break;
262 case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT:
263 GNUNET_STATISTICS_update (GDS_stats,
264 gettext_noop
265 ("# Irrelevant RESULTS found in datacache"), 1,
266 GNUNET_NO);
267 break;
268 case GNUNET_BLOCK_EVALUATION_REQUEST_VALID:
269 GNUNET_break (0);
270 break;
271 case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID:
272 GNUNET_break_op (0);
273 return GNUNET_SYSERR;
274 case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED:
275 GNUNET_STATISTICS_update (GDS_stats,
276 gettext_noop
277 ("# Unsupported RESULTS found in datacache"), 1,
278 GNUNET_NO);
279 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
280 _("Unsupported block type (%u) in local response!\n"), type);
281 break;
282 }
283
284 return (eval == GNUNET_BLOCK_EVALUATION_OK_LAST) ? GNUNET_NO : GNUNET_OK;
285}
286
287
288/**
289 * Handle a GET request we've received from another peer.
290 *
291 * @param key the query
292 * @param type requested data type
293 * @param xquery extended query
294 * @param xquery_size number of bytes in xquery
295 * @param reply_bf where the reply bf is (to be) stored, possibly updated, can be NULL
296 * @param reply_bf_mutator mutation value for reply_bf
297 * @return evaluation result for the local replies
298 * @get_path_length Total number of peers in get path
299 * @get_path Peers in get path.
300 */
301enum GNUNET_BLOCK_EvaluationResult
302GDS_DATACACHE_handle_get (const struct GNUNET_HashCode * key,
303 enum GNUNET_BLOCK_Type type, const void *xquery,
304 size_t xquery_size,
305 struct GNUNET_CONTAINER_BloomFilter **reply_bf,
306 uint32_t reply_bf_mutator,
307 uint32_t get_path_length,
308 struct GNUNET_PeerIdentity *get_path,
309 struct GNUNET_PeerIdentity *next_hop,
310 struct GNUNET_PeerIdentity *source_peer)
311{
312 struct GetRequestContext ctx;
313 unsigned int r;
314
315 if (datacache == NULL)
316 return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
317 GNUNET_STATISTICS_update (GDS_stats,
318 gettext_noop ("# GET requests given to datacache"),
319 1, GNUNET_NO);
320 ctx.eval = GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
321 ctx.key = *key;
322 ctx.xquery = xquery;
323 ctx.xquery_size = xquery_size;
324 ctx.reply_bf = reply_bf;
325 ctx.reply_bf_mutator = reply_bf_mutator;
326 ctx.get_path_length = get_path_length;
327
328 if (next_hop != NULL)
329 {
330 memcpy (&(ctx.next_hop), next_hop, sizeof (struct GNUNET_PeerIdentity));
331 }
332 unsigned int i = 0;
333
334 ctx.head = NULL;
335 ctx.tail = NULL;
336 if (get_path != NULL)
337 {
338 while (i < get_path_length)
339 {
340 struct GetPath *element;
341 element = GNUNET_new (struct GetPath);
342 element->next = NULL;
343 element->prev = NULL;
344 element->peer = get_path[i];
345 GNUNET_CONTAINER_DLL_insert_tail (ctx.head, ctx.tail, element);
346 i++;
347 }
348 }
349
350 r = GNUNET_DATACACHE_get (datacache, key, type, &datacache_get_iterator,
351 &ctx);
352 DEBUG ("DATACACHE_GET for key %s completed (%d). %u results found.\n",GNUNET_h2s (key), ctx.eval, r);
353 return ctx.eval;
354}
355
356
357/**
358 * Initialize datacache subsystem.
359 */
360void
361GDS_DATACACHE_init ()
362{
363 datacache = GNUNET_DATACACHE_create (GDS_cfg, "dhtcache");
364}
365
366
367/**
368 * Shutdown datacache subsystem.
369 */
370void
371GDS_DATACACHE_done ()
372{
373 if (datacache != NULL)
374 {
375 GNUNET_DATACACHE_destroy (datacache);
376 datacache = NULL;
377 }
378}
379
380
381/* end of gnunet-service-dht_datacache.c */
diff --git a/src/dht/gnunet-service-wdht_datacache.h b/src/dht/gnunet-service-wdht_datacache.h
new file mode 100644
index 000000000..a8f37fa63
--- /dev/null
+++ b/src/dht/gnunet-service-wdht_datacache.h
@@ -0,0 +1,90 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file dht/gnunet-service-dht_datacache.h
23 * @brief GNUnet DHT service's datacache integration
24 * @author Christian Grothoff
25 * @author Nathan Evans
26 */
27#ifndef GNUNET_SERVICE_DHT_DATACACHE_H
28#define GNUNET_SERVICE_DHT_DATACACHE_H
29
30#include "gnunet_util_lib.h"
31#include "gnunet_block_lib.h"
32
33/**
34 * Handle a datum we've received from another peer. Cache if
35 * possible.
36 *
37 * @param expiration when will the reply expire
38 * @param key the query this reply is for
39 * @param put_path_length number of peers in 'put_path'
40 * @param put_path path the reply took on put
41 * @param type type of the reply
42 * @param data_size number of bytes in 'data'
43 * @param data application payload data
44 */
45void
46GDS_DATACACHE_handle_put (struct GNUNET_TIME_Absolute expiration,
47 const struct GNUNET_HashCode * key,
48 unsigned int put_path_length,
49 const struct GNUNET_PeerIdentity *put_path,
50 enum GNUNET_BLOCK_Type type, size_t data_size,
51 const void *data);
52
53
54/**
55 * Handle a GET request we've received from another peer.
56 *
57 * @param key the query
58 * @param type requested data type
59 * @param xquery extended query
60 * @param xquery_size number of bytes in xquery
61 * @param reply_bf where the reply bf is (to be) stored, possibly updated!, can be NULL
62 * @param reply_bf_mutator mutation value for reply_bf
63 * @return evaluation result for the local replies
64 */
65enum GNUNET_BLOCK_EvaluationResult
66GDS_DATACACHE_handle_get (const struct GNUNET_HashCode * key,
67 enum GNUNET_BLOCK_Type type, const void *xquery,
68 size_t xquery_size,
69 struct GNUNET_CONTAINER_BloomFilter **reply_bf,
70 uint32_t reply_bf_mutator,
71 uint32_t get_path_length,
72 struct GNUNET_PeerIdentity *get_path,
73 struct GNUNET_PeerIdentity *next_hop,
74 struct GNUNET_PeerIdentity *source_peer);
75
76
77/**
78 * Initialize datacache subsystem.
79 */
80void
81GDS_DATACACHE_init (void);
82
83
84/**
85 * Shutdown datacache subsystem.
86 */
87void
88GDS_DATACACHE_done (void);
89
90#endif
diff --git a/src/dht/gnunet-service-wdht_hello.c b/src/dht/gnunet-service-wdht_hello.c
new file mode 100644
index 000000000..c5e6c7999
--- /dev/null
+++ b/src/dht/gnunet-service-wdht_hello.c
@@ -0,0 +1,137 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file dht/gnunet-service-xdht_hello.c
23 * @brief GNUnet DHT integration with peerinfo
24 * @author Christian Grothoff
25 *
26 * TODO:
27 * - consider adding mechanism to remove expired HELLOs
28 */
29#include "platform.h"
30#include "gnunet-service-wdht.h"
31#include "gnunet-service-wdht_hello.h"
32#include "gnunet_peerinfo_service.h"
33
34
35/**
36 * Handle for peerinfo notifications.
37 */
38static struct GNUNET_PEERINFO_NotifyContext *pnc;
39
40/**
41 * Hash map of peers to HELLOs.
42 */
43static struct GNUNET_CONTAINER_MultiPeerMap *peer_to_hello;
44
45
46/**
47 * Obtain a peer's HELLO if available
48 *
49 * @param peer peer to look for a HELLO from
50 * @return HELLO for the given peer
51 */
52const struct GNUNET_HELLO_Message *
53GDS_HELLO_get (const struct GNUNET_PeerIdentity *peer)
54{
55 if (NULL == peer_to_hello)
56 return NULL;
57 return GNUNET_CONTAINER_multipeermap_get (peer_to_hello, peer);
58}
59
60
61/**
62 * Function called for each HELLO known to PEERINFO.
63 *
64 * @param cls closure
65 * @param peer id of the peer, NULL for last call
66 * @param hello hello message for the peer (can be NULL)
67 * @param err_msg error message (not used)
68 */
69static void
70process_hello (void *cls, const struct GNUNET_PeerIdentity *peer,
71 const struct GNUNET_HELLO_Message *hello, const char *err_msg)
72{
73 struct GNUNET_TIME_Absolute ex;
74 struct GNUNET_HELLO_Message *hm;
75
76 if (hello == NULL)
77 return;
78 ex = GNUNET_HELLO_get_last_expiration (hello);
79 if (0 == GNUNET_TIME_absolute_get_remaining (ex).rel_value_us)
80 return;
81 GNUNET_STATISTICS_update (GDS_stats,
82 gettext_noop ("# HELLOs obtained from peerinfo"), 1,
83 GNUNET_NO);
84 hm = GNUNET_CONTAINER_multipeermap_get (peer_to_hello, peer);
85 GNUNET_free_non_null (hm);
86 hm = GNUNET_malloc (GNUNET_HELLO_size (hello));
87 memcpy (hm, hello, GNUNET_HELLO_size (hello));
88 GNUNET_assert (GNUNET_SYSERR !=
89 GNUNET_CONTAINER_multipeermap_put (peer_to_hello,
90 peer, hm,
91 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE));
92}
93
94
95/**
96 * Initialize HELLO subsystem.
97 */
98void
99GDS_HELLO_init ()
100{
101 pnc = GNUNET_PEERINFO_notify (GDS_cfg, GNUNET_NO, &process_hello, NULL);
102 peer_to_hello = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
103}
104
105
106/**
107 * Free memory occopied by the HELLO.
108 */
109static int
110free_hello (void *cls,
111 const struct GNUNET_PeerIdentity *key,
112 void *hello)
113{
114 GNUNET_free (hello);
115 return GNUNET_OK;
116}
117
118
119/**
120 * Shutdown HELLO subsystem.
121 */
122void
123GDS_HELLO_done ()
124{
125 if (NULL != pnc)
126 {
127 GNUNET_PEERINFO_notify_cancel (pnc);
128 pnc = NULL;
129 }
130 if (NULL != peer_to_hello)
131 {
132 GNUNET_CONTAINER_multipeermap_iterate (peer_to_hello, &free_hello, NULL);
133 GNUNET_CONTAINER_multipeermap_destroy (peer_to_hello);
134 }
135}
136
137/* end of gnunet-service-dht_hello.c */
diff --git a/src/dht/gnunet-service-wdht_hello.h b/src/dht/gnunet-service-wdht_hello.h
new file mode 100644
index 000000000..e7376e7b0
--- /dev/null
+++ b/src/dht/gnunet-service-wdht_hello.h
@@ -0,0 +1,55 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file dht/gnunet-service-xdht_hello.h
23 * @brief GNUnet DHT integration with peerinfo
24 * @author Christian Grothoff
25 */
26#ifndef GNUNET_SERVICE_XDHT_HELLO_H
27#define GNUNET_SERVICE_XDHT_HELLO_H
28
29#include "gnunet_util_lib.h"
30#include "gnunet_hello_lib.h"
31
32/**
33 * Obtain a peer's HELLO if available
34 *
35 * @param peer peer to look for a HELLO from
36 * @return HELLO for the given peer
37 */
38const struct GNUNET_HELLO_Message *
39GDS_HELLO_get (const struct GNUNET_PeerIdentity *peer);
40
41
42/**
43 * Initialize HELLO subsystem.
44 */
45void
46GDS_HELLO_init (void);
47
48
49/**
50 * Shutdown HELLO subsystem.
51 */
52void
53GDS_HELLO_done (void);
54
55#endif
diff --git a/src/dht/gnunet-service-wdht_neighbours.c b/src/dht/gnunet-service-wdht_neighbours.c
new file mode 100644
index 000000000..c91b78a69
--- /dev/null
+++ b/src/dht/gnunet-service-wdht_neighbours.c
@@ -0,0 +1,6290 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2014 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file dht/gnunet-service-xdht_neighbours.c
23 * @brief GNUnet DHT service's finger and friend table management code
24 * @author Supriti Singh
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_block_lib.h"
30#include "gnunet_hello_lib.h"
31#include "gnunet_constants.h"
32#include "gnunet_protocols.h"
33#include "gnunet_ats_service.h"
34#include "gnunet_core_service.h"
35#include "gnunet_datacache_lib.h"
36#include "gnunet_transport_service.h"
37#include "gnunet_dht_service.h"
38#include "gnunet_statistics_service.h"
39#include "gnunet-service-xdht.h"
40#include "gnunet-service-wdht_clients.h"
41#include "gnunet-service-wdht_datacache.h"
42#include "gnunet-service-wdht_neighbours.h"
43#include "gnunet-service-wdht_routing.h"
44#include <fenv.h>
45#include "dht.h"
46
47/**
48 * TODO:
49 * 1. In X-Vine paper, there is no policy defined for replicating the data to
50 * recover in case of peer failure. We can do it in Chord way. In R5N, the key
51 * is hashed and then data is stored according to the key value generated after
52 * hashing.
53 */
54
55#define DEBUG(...) \
56 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
57
58/**
59 * Maximum possible fingers (including predecessor) of a peer
60 */
61#define MAX_FINGERS 65
62
63/**
64 * Maximum allowed number of pending messages per friend peer.
65 */
66#define MAXIMUM_PENDING_PER_FRIEND 64
67
68/**
69 * How long to wait before sending another find finger trail request
70 */
71#define DHT_FIND_FINGER_TRAIL_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2)
72
73/**
74 * How long to wait before sending another verify successor message.
75 */
76#define DHT_SEND_VERIFY_SUCCESSOR_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2)
77
78/**
79 * How long to wait before sending another verify successor message.
80 */
81#define DHT_SEND_VERIFY_SUCCESSOR_RETRY_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
82
83/**
84 * How long to wait before retrying notify successor.
85 */
86#define DHT_SEND_NOTIFY_SUCCESSOR_RETRY_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
87
88/**
89 * How long at most to wait for transmission of a request to a friend ?
90 */
91#define PENDING_MESSAGE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
92
93/**
94 * Duration for which I may remain congested.
95 * Note: Its a static value. In future, a peer may do some analysis and calculate
96 * congestion_timeout based on 'some' parameters.
97 */
98#define CONGESTION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
99
100/**
101 * In case we don't hear back from the current successor, then we can start
102 * verify successor.
103 */
104#define WAIT_NOTIFY_CONFIRMATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 200)
105
106/**
107 * Maximum number of trails allowed to go through a friend.
108 */
109#define TRAILS_THROUGH_FRIEND_THRESHOLD 64
110
111/**
112 * Maximum number of trails stored per finger.
113 */
114#define MAXIMUM_TRAILS_PER_FINGER 4
115
116/**
117 * Finger map index for predecessor entry in finger table.
118 */
119#define PREDECESSOR_FINGER_ID 64
120
121/**
122 * FIXME: Its use only at 3 places check if you can remove it.
123 * To check if a finger is predecessor or not.
124 */
125enum GDS_NEIGHBOURS_finger_type
126{
127 GDS_FINGER_TYPE_PREDECESSOR = 1,
128 GDS_FINGER_TYPE_NON_PREDECESSOR = 0
129};
130
131GNUNET_NETWORK_STRUCT_BEGIN
132
133/**
134 * P2P PUT message
135 */
136struct PeerPutMessage
137{
138 /**
139 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_PUT
140 */
141 struct GNUNET_MessageHeader header;
142
143 /**
144 * Processing options
145 */
146 uint32_t options GNUNET_PACKED;
147
148 /**
149 * Content type.
150 */
151 uint32_t block_type GNUNET_PACKED;
152
153 /**
154 * Hop count
155 */
156 uint32_t hop_count GNUNET_PACKED;
157
158 /**
159 * Replication level for this message
160 * In the current implementation, this value is not used.
161 */
162 uint32_t desired_replication_level GNUNET_PACKED;
163
164 /**
165 * Length of the PUT path that follows (if tracked).
166 */
167 uint32_t put_path_length GNUNET_PACKED;
168
169 /**
170 * Best known destination (could be my friend or finger) which should
171 * get this message next.
172 */
173 struct GNUNET_PeerIdentity best_known_destination;
174
175 /**
176 * In case best_known_destination is a finger, then trail to reach
177 * to that finger. Else its default value is 0.
178 */
179 struct GNUNET_HashCode intermediate_trail_id;
180
181 /**
182 * When does the content expire?
183 */
184 struct GNUNET_TIME_AbsoluteNBO expiration_time;
185
186 /**
187 * The key to store the value under.
188 */
189 struct GNUNET_HashCode key GNUNET_PACKED;
190
191 /* put path (if tracked) */
192
193 /* Payload */
194
195};
196
197/**
198 * P2P GET message
199 */
200struct PeerGetMessage
201{
202 /**
203 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_GET
204 */
205 struct GNUNET_MessageHeader header;
206
207 /**
208 * Processing options
209 */
210 uint32_t options GNUNET_PACKED;
211
212 /**
213 * Desired content type.
214 */
215 uint32_t block_type GNUNET_PACKED;
216
217 /**
218 * Hop count
219 */
220 uint32_t hop_count GNUNET_PACKED;
221
222 /**
223 * Desired replication level for this request.
224 * In the current implementation, this value is not used.
225 */
226 uint32_t desired_replication_level GNUNET_PACKED;
227
228 /**
229 * Total number of peers in get path.
230 */
231 unsigned int get_path_length;
232
233 /**
234 * Best known destination (could be my friend or finger) which should
235 * get this message next.
236 */
237 struct GNUNET_PeerIdentity best_known_destination;
238
239 /**
240 * In case best_known_destination is a finger, then trail to reach
241 * to that finger. Else its default value is 0.
242 */
243 struct GNUNET_HashCode intermediate_trail_id;
244
245 /**
246 * The key we are looking for.
247 */
248 struct GNUNET_HashCode key;
249
250 /* Get path. */
251 /* struct GNUNET_PeerIdentity[]*/
252};
253
254/**
255 * P2P Result message
256 */
257struct PeerGetResultMessage
258{
259 /**
260 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_GET_RESULT
261 */
262 struct GNUNET_MessageHeader header;
263
264 /**
265 * The type for the data.
266 */
267 uint32_t type GNUNET_PACKED;
268
269 /**
270 * Number of peers recorded in the outgoing path from source to the
271 * stored location of this message.
272 */
273 uint32_t put_path_length GNUNET_PACKED;
274
275 /**
276 * Length of the GET path that follows (if tracked).
277 */
278 uint32_t get_path_length GNUNET_PACKED;
279
280 /**
281 * Peer which queried for get and should get the result.
282 */
283 struct GNUNET_PeerIdentity querying_peer;
284
285 /**
286 * When does the content expire?
287 */
288 struct GNUNET_TIME_Absolute expiration_time;
289
290 /**
291 * The key of the corresponding GET request.
292 */
293 struct GNUNET_HashCode key;
294
295 /* put path (if tracked) */
296
297 /* get path (if tracked) */
298
299 /* Payload */
300
301};
302
303/**
304 * P2P Trail setup message
305 */
306struct PeerTrailSetupMessage
307{
308 /**
309 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP
310 */
311 struct GNUNET_MessageHeader header;
312
313 /**
314 * Is source_peer trying to setup the trail to a predecessor or any finger.
315 */
316 uint32_t is_predecessor;
317
318 /**
319 * Peer closest to this value will be our finger.
320 */
321 uint64_t final_destination_finger_value;
322
323 /**
324 * Source peer which wants to setup the trail to one of its finger.
325 */
326 struct GNUNET_PeerIdentity source_peer;
327
328 /**
329 * Best known destination (could be my friend or finger) which should
330 * get this message next.
331 *
332 * FIXME: this could be removed if we include trail_source / trail_dest
333 * in the routing table. This way we save 32 bytes of bandwidth by using
334 * extra 8 bytes of memory (2 * sizeof (GNUNET_PEER_ID))
335 */
336 struct GNUNET_PeerIdentity best_known_destination;
337
338 /**
339 * In case best_known_destination is a finger, then trail id of trail to
340 * reach to this finger.
341 */
342 struct GNUNET_HashCode intermediate_trail_id;
343
344 /**
345 * Trail id for trail which we are trying to setup.
346 */
347 struct GNUNET_HashCode trail_id;
348
349 /* List of peers which are part of trail setup so far.
350 * Trail does NOT include source_peer and peer which will be closest to
351 * ultimate_destination_finger_value.
352 * struct GNUNET_PeerIdentity trail[]
353 */
354};
355
356/**
357 * P2P Trail Setup Result message
358 */
359struct PeerTrailSetupResultMessage
360{
361
362 /**
363 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP_RESULT
364 */
365 struct GNUNET_MessageHeader header;
366
367 /**
368 * Finger to which we have found the path.
369 */
370 struct GNUNET_PeerIdentity finger_identity;
371
372 /**
373 * Peer which started trail_setup to find trail to finger_identity
374 */
375 struct GNUNET_PeerIdentity querying_peer;
376
377 /**
378 * Is the trail setup to querying_peer's predecessor or finger?
379 */
380 uint32_t is_predecessor;
381
382 /**
383 * Value to which finger_identity is the closest peer.
384 */
385 uint64_t ulitmate_destination_finger_value;
386
387 /**
388 * Identifier of the trail from querying peer to finger_identity, NOT
389 * including both endpoints.
390 */
391 struct GNUNET_HashCode trail_id;
392
393 /* List of peers which are part of the trail from querying peer to
394 * finger_identity, NOT including both endpoints.
395 * struct GNUNET_PeerIdentity trail[]
396 */
397};
398
399/**
400 * P2P Verify Successor Message.
401 */
402struct PeerVerifySuccessorMessage
403{
404 /**
405 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_VERIFY_SUCCESSOR
406 */
407 struct GNUNET_MessageHeader header;
408
409 /**
410 * Peer which wants to verify its successor.
411 */
412 struct GNUNET_PeerIdentity source_peer;
413
414 /**
415 * Source Peer's current successor.
416 */
417 struct GNUNET_PeerIdentity successor;
418
419 /**
420 * Identifier of trail to reach from source_peer to successor.
421 */
422 struct GNUNET_HashCode trail_id;
423
424 /* List of the peers which are part of trail to reach from source_peer
425 * to successor, NOT including them
426 * struct GNUNET_PeerIdentity trail[]
427 */
428};
429
430/**
431 * P2P Verify Successor Result Message
432 */
433struct PeerVerifySuccessorResultMessage
434{
435 /**
436 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_VERIFY_SUCCESSOR_RESULT
437 */
438 struct GNUNET_MessageHeader header;
439
440 /**
441 * Peer which sent the request to verify its successor.
442 */
443 struct GNUNET_PeerIdentity querying_peer;
444
445 /**
446 * Successor to which PeerVerifySuccessorMessage was sent.
447 */
448 struct GNUNET_PeerIdentity current_successor;
449
450 /**
451 * Current Predecessor of source_successor. It can be same as querying peer
452 * or different. In case it is different then it can be querying_peer's
453 * probable successor.
454 */
455 struct GNUNET_PeerIdentity probable_successor;
456
457 /**
458 * Trail identifier of trail from querying_peer to current_successor.
459 */
460 struct GNUNET_HashCode trail_id;
461
462 /**
463 * Direction in which we are looking at the trail.
464 */
465 uint32_t trail_direction;
466
467 /* In case probable_successor != querying_peer, then trail to reach from
468 * querying_peer to probable_successor, NOT including end points.
469 * struct GNUNET_PeerIdentity trail[]
470 */
471};
472
473/**
474 * P2P Notify New Successor Message.
475 */
476struct PeerNotifyNewSuccessorMessage
477{
478 /**
479 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_NOTIFY_NEW_SUCCESSOR
480 */
481 struct GNUNET_MessageHeader header;
482
483 /**
484 * Peer which wants to notify its new successor.
485 */
486 struct GNUNET_PeerIdentity source_peer;
487
488 /**
489 * New successor of source_peer.
490 */
491 struct GNUNET_PeerIdentity new_successor;
492
493 /**
494 * Unique identifier of the trail from source_peer to new_successor,
495 * NOT including the endpoints.
496 */
497 struct GNUNET_HashCode trail_id;
498
499 /* List of peers in trail from source_peer to new_successor,
500 * NOT including the endpoints.
501 * struct GNUNET_PeerIdentity trail[]
502 */
503};
504
505/**
506 * P2P Notify Successor Confirmation message.
507 */
508struct PeerNotifyConfirmationMessage
509{
510 /**
511 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_TEARDOWN
512 */
513 struct GNUNET_MessageHeader header;
514
515 /**
516 * Unique identifier of the trail.
517 */
518 struct GNUNET_HashCode trail_id;
519
520 /**
521 * Direction of trail.
522 */
523 uint32_t trail_direction;
524};
525
526
527/**
528 * P2P Trail Tear Down message.
529 */
530struct PeerTrailTearDownMessage
531{
532 /**
533 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_TEARDOWN
534 */
535 struct GNUNET_MessageHeader header;
536
537 /**
538 * Unique identifier of the trail.
539 */
540 struct GNUNET_HashCode trail_id;
541
542 /**
543 * Direction of trail.
544 */
545 uint32_t trail_direction;
546};
547
548
549/**
550 * P2P Trail Rejection Message.
551 */
552struct PeerTrailRejectionMessage
553{
554 /**
555 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP_REJECTION
556 */
557 struct GNUNET_MessageHeader header;
558
559 /**
560 * Peer which wants to set up the trail.
561 */
562 struct GNUNET_PeerIdentity source_peer;
563
564 /**
565 * Peer which sent trail rejection message as it it congested.
566 */
567 struct GNUNET_PeerIdentity congested_peer;
568
569 /**
570 * Peer identity closest to this value will be finger of
571 * source_peer.
572 */
573 uint64_t ultimate_destination_finger_value;
574
575 /**
576 * Is source_peer trying to setup the trail to its predecessor or finger.
577 */
578 uint32_t is_predecessor;
579
580 /**
581 * Identifier for the trail that source peer is trying to setup.
582 */
583 struct GNUNET_HashCode trail_id;
584
585 /**
586 * Relative time for which congested_peer will remain congested.
587 */
588 struct GNUNET_TIME_Relative congestion_time;
589
590 /* Trail_list from source_peer to peer which sent the message for trail setup
591 * to congested peer. This trail does NOT include source_peer.
592 struct GNUNET_PeerIdnetity trail[]*/
593};
594
595/**
596 * P2P Add Trail Message.
597 */
598struct PeerAddTrailMessage
599{
600 /**
601 * Type: #GNUNET_MESSAGE_TYPE_XDHT_P2P_ADD_TRAIL
602 */
603 struct GNUNET_MessageHeader header;
604
605 /**
606 * Source of the routing trail.
607 */
608 struct GNUNET_PeerIdentity source_peer;
609
610 /**
611 * Destination of the routing trail.
612 */
613 struct GNUNET_PeerIdentity destination_peer;
614
615 /**
616 * Unique identifier of the trail from source_peer to destination_peer,
617 * NOT including the endpoints.
618 */
619 struct GNUNET_HashCode trail_id;
620
621 /* Trail from source peer to destination peer, NOT including them.
622 * struct GNUNET_PeerIdentity trail[]
623 */
624};
625
626
627GNUNET_NETWORK_STRUCT_END
628
629/**
630 * Linked list of messages to send to a particular other peer.
631 */
632struct P2PPendingMessage
633{
634 /**
635 * Pointer to next item in the list
636 */
637 struct P2PPendingMessage *next;
638
639 /**
640 * Pointer to previous item in the list
641 */
642 struct P2PPendingMessage *prev;
643
644 /**
645 * Message importance level. FIXME: used? useful?
646 */
647 unsigned int importance;
648
649 /**
650 * When does this message time out?
651 */
652 struct GNUNET_TIME_Absolute timeout;
653
654 /**
655 * Actual message to be sent, allocated at the end of the struct:
656 * // msg = (cast) &pm[1];
657 * // memcpy (&pm[1], data, len);
658 */
659 const struct GNUNET_MessageHeader *msg;
660
661};
662
663/**
664 * Entry in friend_peermap.
665 */
666struct FriendInfo
667{
668 /**
669 * Friend Identity
670 */
671 struct GNUNET_PeerIdentity id;
672
673 /**
674 * Number of trails for which this friend is the first hop or if the friend
675 * is finger.
676 */
677 unsigned int trails_count;
678
679 /**
680 * Count of outstanding messages for this friend.
681 */
682 unsigned int pending_count;
683
684 /**
685 * In case not 0, then amount of time for which this friend is congested.
686 */
687 struct GNUNET_TIME_Absolute congestion_timestamp;
688
689
690 // TODO : Change name of head and tail to pending_messages_list_head and so.
691 /**
692 * Head of pending messages to be sent to this friend.
693 */
694 struct P2PPendingMessage *head;
695
696 /**
697 * Tail of pending messages to be sent to this friend.
698 */
699 struct P2PPendingMessage *tail;
700
701 /**
702 * Core handle for sending messages to this friend.
703 */
704 struct GNUNET_CORE_TransmitHandle *th;
705
706};
707
708/**
709 * An individual element of the trail to reach to a finger.
710 */
711struct Trail_Element
712{
713 /**
714 * Pointer to next item in the list
715 */
716 struct Trail_Element *next;
717
718 /**
719 * Pointer to prev item in the list
720 */
721 struct Trail_Element *prev;
722
723 /**
724 * An element in this trail.
725 */
726 struct GNUNET_PeerIdentity peer;
727};
728
729/**
730 * Information about an individual trail.
731 */
732struct Trail
733{
734 /**
735 * Head of trail.
736 */
737 struct Trail_Element *trail_head;
738
739 /**
740 * Tail of trail.
741 */
742 struct Trail_Element *trail_tail;
743
744 /**
745 * Unique identifier of this trail.
746 */
747 struct GNUNET_HashCode trail_id;
748
749 /**
750 * Length of trail pointed
751 */
752 unsigned int trail_length;
753
754 /**
755 * Is there a valid trail entry.
756 */
757 unsigned int is_present;
758};
759
760/**
761 * An entry in finger_table
762 */
763struct FingerInfo
764{
765 /**
766 * Finger identity.
767 */
768 struct GNUNET_PeerIdentity finger_identity;
769
770 /**
771 * In case not 0, this amount is time to wait for notify successor message.
772 * Used ONLY for successor. NOT for any other finger.
773 */
774 struct GNUNET_TIME_Absolute wait_notify_confirmation;
775
776 /**
777 * Is any finger stored at this finger index.
778 */
779 unsigned int is_present;
780
781 /**
782 * Index in finger peer map
783 */
784 uint32_t finger_table_index;
785
786 /**
787 * Number of trails setup so far for this finger.
788 * Should not cross MAXIMUM_TRAILS_PER_FINGER.
789 */
790 uint32_t trails_count;
791
792 /**
793 * Array of trails to reach to this finger.
794 */
795 struct Trail trail_list[MAXIMUM_TRAILS_PER_FINGER];
796};
797
798
799/**
800 * Stores information about the peer which is closest to destination_finger_value.
801 * 'closest' can be either successor or predecessor depending on is_predecessor
802 * flag.
803 */
804struct Closest_Peer
805{
806 /**
807 * Destination finger value.
808 */
809 uint64_t destination_finger_value;
810
811 /**
812 * Is finger_value a predecessor or any other finger.
813 */
814 unsigned int is_predecessor;
815
816 /**
817 * Trail id to reach to peer.
818 * In case peer is my identity or friend, it is set to 0.
819 */
820 struct GNUNET_HashCode trail_id;
821
822 /**
823 * Next destination. In case of friend and my_identity , it is same as next_hop
824 * In case of finger it is finger identity.
825 */
826 struct GNUNET_PeerIdentity best_known_destination;
827
828 /**
829 * In case best_known_destination is a finger, then first friend in the trail
830 * to reach to it. In other case, same as best_known_destination.
831 */
832 struct GNUNET_PeerIdentity next_hop;
833
834 /**
835 * In case finger is the next hop, it contains a valid finger table index
836 * at which the finger is stored. Else, It contains 65, which is out of range
837 * of finger table index.
838 */
839 unsigned int finger_table_index;
840};
841
842/**
843 * Context for send_verify_successor_task.
844 */
845struct VerifySuccessorContext
846{
847 /**
848 * Number of times this has been scheduled.
849 */
850 unsigned int num_retries_scheduled;
851};
852
853/**
854 * Task that sends FIND FINGER TRAIL requests. This task is started when we have
855 * get our first friend.
856 */
857static struct GNUNET_SCHEDULER_Task * find_finger_trail_task;
858
859/**
860 * Task that sends verify successor message. This task is started when we get
861 * our successor for the first time.
862 */
863static struct GNUNET_SCHEDULER_Task * send_verify_successor_task;
864
865/**
866 * Task that sends verify successor message. This task is started when we get
867 * our successor for the first time.
868 */
869static struct GNUNET_SCHEDULER_Task * send_verify_successor_retry_task;
870
871/**
872 * Task that sends verify successor message. This task is started when we get
873 * our successor for the first time.
874 */
875static struct GNUNET_SCHEDULER_Task * send_notify_new_successor_retry_task;
876
877/**
878 * Identity of this peer.
879 */
880static struct GNUNET_PeerIdentity my_identity;
881
882/**
883 * Peer map of all the friends of a peer
884 */
885static struct GNUNET_CONTAINER_MultiPeerMap *friend_peermap;
886
887/**
888 * Array of all the fingers.
889 */
890static struct FingerInfo finger_table [MAX_FINGERS];
891
892/**
893 * Handle to CORE.
894 */
895static struct GNUNET_CORE_Handle *core_api;
896
897/**
898 * Handle for the statistics service.
899 */
900//extern struct GNUNET_STATISTICS_Handle *GDS_stats;
901
902/**
903 * The current finger index that we have want to find trail to. We start the
904 * search with value = 0, i.e. successor and then go to PREDCESSOR_FINGER_ID
905 * and decrement it. For any index 63 <= index < 0, if finger is same as successor,
906 * we reset this index to 0.
907 */
908static unsigned int current_search_finger_index;
909
910/**
911 * Time duration to schedule find finger trail task.
912 */
913static struct GNUNET_TIME_Relative find_finger_trail_task_next_send_time;
914
915/**
916 * Time duration to schedule verify successor task.
917 */
918static struct GNUNET_TIME_Relative verify_successor_next_send_time;
919
920/**
921 * Time duration to send verify successor again, if result was not received in time.
922 */
923static struct GNUNET_TIME_Relative verify_successor_retry_time;
924
925/**
926 * Time duration to retry send_notify_successor.
927 */
928static struct GNUNET_TIME_Relative notify_successor_retry_time;
929
930/**
931 * Are we waiting for confirmation from our new successor that it got the
932 * message
933 */
934//static unsigned int waiting_for_notify_confirmation;
935
936/* Below variables are used only for testing, and statistics collection. */
937/**
938 * Should we store our topology predecessor and successor IDs into statistics?
939 */
940unsigned int track_topology;
941
942/**
943 * Should I be a malicious peer and drop the PUT/GET packets?
944 * if 0 then NOT malicious.
945 */
946unsigned int act_malicious;
947
948/**
949 * Count of fingers found. Ideally we should have O(logn) fingers for a
950 * stable network.
951 */
952static unsigned int total_fingers_found;
953
954/**
955 * Number of times we found the same successor.
956 */
957static unsigned int successor_times;
958
959/**
960 * Number of rounds for which we should search for finger.
961 */
962static unsigned int fingers_round_count;
963/**
964 * Called when core is ready to send a message we asked for
965 * out to the destination.
966 *
967 * @param cls the 'struct FriendInfo' of the target friend
968 * @param size number of bytes available in buf
969 * @param buf where the callee should write the message
970 * @return number of bytes written to buf
971 */
972static size_t
973core_transmit_notify (void *cls, size_t size, void *buf)
974{
975 struct FriendInfo *peer = cls;
976 char *cbuf = buf;
977 struct P2PPendingMessage *pending;
978 size_t off;
979 size_t msize;
980
981 peer->th = NULL;
982 while ( (NULL != (pending = peer->head)) &&
983 (0 == GNUNET_TIME_absolute_get_remaining (pending->timeout).rel_value_us) )
984 {
985 GNUNET_STATISTICS_update (GDS_stats,
986 gettext_noop
987 ("# Messages dropped (CORE timeout)"),
988 1,
989 GNUNET_NO);
990 peer->pending_count--;
991 GNUNET_CONTAINER_DLL_remove (peer->head,
992 peer->tail,
993 pending);
994 GNUNET_free (pending);
995 }
996 if (NULL == pending)
997 {
998 /* no messages pending */
999 return 0;
1000 }
1001 if (NULL == buf)
1002 {
1003 peer->th =
1004 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
1005 GNUNET_CORE_PRIO_BEST_EFFORT,
1006 GNUNET_TIME_absolute_get_remaining
1007 (pending->timeout), &peer->id,
1008 ntohs (pending->msg->size),
1009 &core_transmit_notify, peer);
1010 GNUNET_break (NULL != peer->th);
1011 return 0;
1012 }
1013 off = 0;
1014 while ((NULL != (pending = peer->head)) &&
1015 (size - off >= (msize = ntohs (pending->msg->size))))
1016 {
1017 GNUNET_STATISTICS_update (GDS_stats,
1018 gettext_noop
1019 ("# Bytes transmitted to other peers"),
1020 msize,
1021 GNUNET_NO);
1022 memcpy (&cbuf[off], pending->msg, msize);
1023 off += msize;
1024 peer->pending_count--;
1025 GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending);
1026 GNUNET_free (pending);
1027 }
1028 if (peer->head != NULL)
1029 {
1030 peer->th =
1031 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
1032 GNUNET_CORE_PRIO_BEST_EFFORT,
1033 GNUNET_TIME_absolute_get_remaining
1034 (pending->timeout), &peer->id, msize,
1035 &core_transmit_notify, peer);
1036 GNUNET_break (NULL != peer->th);
1037 }
1038 return off;
1039}
1040
1041
1042/**
1043 * Transmit all messages in the friend's message queue.
1044 *
1045 * @param peer message queue to process
1046 */
1047static void
1048process_friend_queue (struct FriendInfo *peer)
1049{
1050 struct P2PPendingMessage *pending;
1051
1052 if (NULL == (pending = peer->head))
1053 {
1054 return;
1055 }
1056 if (NULL != peer->th)
1057 {
1058 return;
1059 }
1060
1061 peer->th =
1062 GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO,
1063 pending->importance,
1064 GNUNET_TIME_absolute_get_remaining
1065 (pending->timeout), &peer->id,
1066 ntohs (pending->msg->size),
1067 &core_transmit_notify, peer);
1068 GNUNET_break (NULL != peer->th);
1069}
1070
1071
1072#if ENABLE_MALICIOUS
1073/**
1074 * Set the ENABLE_MALICIOUS value to malicious.
1075 * @param malicious
1076 */
1077int
1078GDS_NEIGHBOURS_act_malicious (unsigned int malicious)
1079{
1080 act_malicious = malicious;
1081 return GNUNET_OK;
1082}
1083#endif
1084
1085/**
1086 * Construct a trail setup message and forward it to target_friend
1087 * @param source_peer Peer which wants to setup the trail
1088 * @param ultimate_destination_finger_value Peer identity closest to this value
1089 * will be finger to @a source_peer
1090 * @param best_known_destination Best known destination (could be finger or friend)
1091 * which should get this message. In case it is
1092 * friend, then it is same as target_friend
1093 * @param target_friend Friend to which message is forwarded now.
1094 * @param trail_length Total number of peers in trail setup so far.
1095 * @param trail_peer_list Trail setup so far
1096 * @param is_predecessor Is @a source_peer looking for trail to a predecessor or not.
1097 * @param trail_id Unique identifier for the trail we are trying to setup.
1098 * @param intermediate_trail_id Trail id of intermediate trail to reach to
1099 * best_known_destination when its a finger. If not
1100 * used then set to 0.
1101 */
1102void
1103GDS_NEIGHBOURS_send_trail_setup (struct GNUNET_PeerIdentity source_peer,
1104 uint64_t ultimate_destination_finger_value,
1105 struct GNUNET_PeerIdentity best_known_destination,
1106 struct FriendInfo *target_friend,
1107 unsigned int trail_length,
1108 const struct GNUNET_PeerIdentity *trail_peer_list,
1109 unsigned int is_predecessor,
1110 struct GNUNET_HashCode trail_id,
1111 struct GNUNET_HashCode intermediate_trail_id)
1112{
1113 struct P2PPendingMessage *pending;
1114 struct PeerTrailSetupMessage *tsm;
1115 struct GNUNET_PeerIdentity *peer_list;
1116 size_t msize;
1117
1118 msize = sizeof (struct PeerTrailSetupMessage) +
1119 (trail_length * sizeof (struct GNUNET_PeerIdentity));
1120
1121 if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
1122 {
1123 GNUNET_break (0);
1124 return;
1125 }
1126
1127 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1128 {
1129 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1130 1, GNUNET_NO);
1131 }
1132 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1133 pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT);
1134 tsm = (struct PeerTrailSetupMessage *) &pending[1];
1135 pending->msg = &(tsm->header);
1136 tsm->header.size = htons (msize);
1137 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP);
1138 tsm->final_destination_finger_value = GNUNET_htonll (ultimate_destination_finger_value);
1139 tsm->source_peer = source_peer;
1140 tsm->best_known_destination = best_known_destination;
1141 tsm->is_predecessor = htonl (is_predecessor);
1142 tsm->trail_id = trail_id;
1143 tsm->intermediate_trail_id = intermediate_trail_id;
1144
1145 if (trail_length > 0)
1146 {
1147 peer_list = (struct GNUNET_PeerIdentity *) &tsm[1];
1148 memcpy (peer_list, trail_peer_list, trail_length * sizeof(struct GNUNET_PeerIdentity));
1149 }
1150
1151 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1152 target_friend->pending_count++;
1153 process_friend_queue (target_friend);
1154}
1155
1156
1157/**
1158 * Construct a trail setup result message and forward it to target friend.
1159 * @param querying_peer Peer which sent the trail setup request and should get
1160 * the result back.
1161 * @param Finger Peer to which the trail has been setup to.
1162 * @param target_friend Friend to which this message should be forwarded.
1163 * @param trail_length Numbers of peers in the trail.
1164 * @param trail_peer_list Peers which are part of the trail from
1165 * querying_peer to Finger, NOT including them.
1166 * @param is_predecessor Is @a Finger predecessor to @a querying_peer ?
1167 * @param ultimate_destination_finger_value Value to which @a finger is the closest
1168 * peer.
1169 * @param trail_id Unique identifier of the trail.
1170 */
1171void
1172GDS_NEIGHBOURS_send_trail_setup_result (struct GNUNET_PeerIdentity querying_peer,
1173 struct GNUNET_PeerIdentity finger,
1174 struct FriendInfo *target_friend,
1175 unsigned int trail_length,
1176 const struct GNUNET_PeerIdentity *trail_peer_list,
1177 unsigned int is_predecessor,
1178 uint64_t ultimate_destination_finger_value,
1179 struct GNUNET_HashCode trail_id)
1180{
1181 struct P2PPendingMessage *pending;
1182 struct PeerTrailSetupResultMessage *tsrm;
1183 struct GNUNET_PeerIdentity *peer_list;
1184 size_t msize;
1185
1186 msize = sizeof (struct PeerTrailSetupResultMessage) +
1187 (trail_length * sizeof (struct GNUNET_PeerIdentity));
1188
1189 if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
1190 {
1191 GNUNET_break (0);
1192 return;
1193 }
1194
1195 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1196 {
1197 GNUNET_STATISTICS_update (GDS_stats,
1198 gettext_noop ("# P2P messages dropped due to full queue"),
1199 1, GNUNET_NO);
1200 }
1201
1202 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1203 pending->importance = 0;
1204 pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT);
1205 tsrm = (struct PeerTrailSetupResultMessage *) &pending[1];
1206 pending->msg = &tsrm->header;
1207 tsrm->header.size = htons (msize);
1208 tsrm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP_RESULT);
1209 tsrm->querying_peer = querying_peer;
1210 tsrm->finger_identity = finger;
1211 tsrm->is_predecessor = htonl (is_predecessor);
1212 tsrm->trail_id = trail_id;
1213 tsrm->ulitmate_destination_finger_value =
1214 GNUNET_htonll (ultimate_destination_finger_value);
1215 peer_list = (struct GNUNET_PeerIdentity *) &tsrm[1];
1216 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
1217
1218 /* Send the message to chosen friend. */
1219 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1220 target_friend->pending_count++;
1221 process_friend_queue (target_friend);
1222}
1223
1224/**
1225 * Send notify successor confirmation message.
1226 * @param trail_id Unique Identifier of the trail.
1227 * @param trail_direction Destination to Source.
1228 * @param target_friend Friend to get this message next.
1229 */
1230void
1231GDS_NEIGHBOURS_send_notify_succcessor_confirmation (struct GNUNET_HashCode trail_id,
1232 unsigned int trail_direction,
1233 struct FriendInfo *target_friend)
1234{
1235 struct PeerNotifyConfirmationMessage *ncm;
1236 struct P2PPendingMessage *pending;
1237 size_t msize;
1238
1239 msize = sizeof (struct PeerNotifyConfirmationMessage);
1240 if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
1241 {
1242 GNUNET_break (0);
1243 return;
1244 }
1245
1246 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1247 {
1248 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1249 1, GNUNET_NO);
1250 }
1251
1252 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1253 pending->importance = 0; /* FIXME */
1254 pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT);
1255 ncm = (struct PeerNotifyConfirmationMessage *) &pending[1];
1256 pending->msg = &ncm->header;
1257 ncm->header.size = htons (msize);
1258 ncm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_NOTIFY_SUCCESSOR_CONFIRMATION);
1259 ncm->trail_id = trail_id;
1260 ncm->trail_direction = htonl (trail_direction);
1261
1262 /* Send the message to chosen friend. */
1263 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1264 target_friend->pending_count++;
1265 process_friend_queue (target_friend);
1266}
1267
1268
1269/**
1270 * Send trail rejection message to target friend
1271 * @param source_peer Peer which is trying to setup the trail.
1272 * @param ultimate_destination_finger_value Peer closest to this value will be
1273 * @a source_peer's finger
1274 * @param congested_peer Peer which sent this message as it is congested.
1275 * @param is_predecessor Is source_peer looking for trail to a predecessor or not.
1276 * @param trail_peer_list Trails seen so far in trail setup before getting rejected
1277 * by congested_peer. This does NOT include @a source_peer
1278 * and congested_peer.
1279 * @param trail_length Total number of peers in trail_peer_list, NOT including
1280 * @a source_peer and @a congested_peer
1281 * @param trail_id Unique identifier of this trail.
1282 * @param congestion_timeout Duration given by congested peer as an estimate of
1283 * how long it may remain congested.
1284 */
1285void
1286GDS_NEIGHBOURS_send_trail_rejection (struct GNUNET_PeerIdentity source_peer,
1287 uint64_t ultimate_destination_finger_value,
1288 struct GNUNET_PeerIdentity congested_peer,
1289 unsigned int is_predecessor,
1290 const struct GNUNET_PeerIdentity *trail_peer_list,
1291 unsigned int trail_length,
1292 struct GNUNET_HashCode trail_id,
1293 struct FriendInfo *target_friend,
1294 const struct GNUNET_TIME_Relative congestion_timeout)
1295{
1296 struct PeerTrailRejectionMessage *trm;
1297 struct P2PPendingMessage *pending;
1298 struct GNUNET_PeerIdentity *peer_list;
1299 size_t msize;
1300
1301 msize = sizeof (struct PeerTrailRejectionMessage) +
1302 (trail_length * sizeof (struct GNUNET_PeerIdentity));
1303
1304 if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
1305 {
1306 GNUNET_break (0);
1307 return;
1308 }
1309
1310 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1311 {
1312 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1313 1, GNUNET_NO);
1314 }
1315
1316 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1317 pending->importance = 0;
1318 pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT);
1319 trm = (struct PeerTrailRejectionMessage *)&pending[1];
1320 pending->msg = &trm->header;
1321 trm->header.size = htons (msize);
1322 trm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP_REJECTION);
1323 trm->source_peer = source_peer;
1324 trm->congested_peer = congested_peer;
1325 trm->congestion_time = congestion_timeout;
1326 trm->is_predecessor = htonl (is_predecessor);
1327 trm->trail_id = trail_id;
1328 trm->ultimate_destination_finger_value =
1329 GNUNET_htonll (ultimate_destination_finger_value);
1330
1331 peer_list = (struct GNUNET_PeerIdentity *) &trm[1];
1332 if (trail_length > 0)
1333 {
1334 memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity));
1335 }
1336
1337 /* Send the message to chosen friend. */
1338 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1339 target_friend->pending_count++;
1340 process_friend_queue (target_friend);
1341}
1342
1343
1344/**
1345 * Construct a verify successor message and forward it to target_friend.
1346 * @param source_peer Peer which wants to verify its successor.
1347 * @param successor Peer which is @a source_peer's current successor.
1348 * @param trail_id Unique Identifier of trail from @a source_peer to @a successor,
1349 * NOT including them.
1350 * @param trail List of peers which are part of trail to reach from @a source_peer
1351 * to @a successor, NOT including them.
1352 * @param trail_length Total number of peers in @a trail.
1353 * @param target_friend Next friend to get this message.
1354 */
1355void
1356GDS_NEIGHBOURS_send_verify_successor_message (struct GNUNET_PeerIdentity source_peer,
1357 struct GNUNET_PeerIdentity successor,
1358 struct GNUNET_HashCode trail_id,
1359 struct GNUNET_PeerIdentity *trail,
1360 unsigned int trail_length,
1361 struct FriendInfo *target_friend)
1362{
1363 struct PeerVerifySuccessorMessage *vsm;
1364 struct P2PPendingMessage *pending;
1365 struct GNUNET_PeerIdentity *peer_list;
1366 size_t msize;
1367
1368 msize = sizeof (struct PeerVerifySuccessorMessage) +
1369 (trail_length * sizeof (struct GNUNET_PeerIdentity));
1370
1371 if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
1372 {
1373 GNUNET_break (0);
1374 return;
1375 }
1376
1377 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1378 {
1379 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1380 1, GNUNET_NO);
1381 }
1382
1383 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1384 pending->importance = 0; /* FIXME */
1385 pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT);
1386 vsm = (struct PeerVerifySuccessorMessage *) &pending[1];
1387 pending->msg = &vsm->header;
1388 vsm->header.size = htons (msize);
1389 vsm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_VERIFY_SUCCESSOR);
1390 vsm->source_peer = source_peer;
1391 vsm->successor = successor;
1392 vsm->trail_id = trail_id;
1393 peer_list = (struct GNUNET_PeerIdentity *) &vsm[1];
1394 memcpy (peer_list, trail, trail_length * sizeof (struct GNUNET_PeerIdentity));
1395
1396 /* Send the message to chosen friend. */
1397 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1398 target_friend->pending_count++;
1399 process_friend_queue (target_friend);
1400}
1401
1402
1403/**
1404 * FIXME: In every function we pass target friend except for this one.
1405 * so, either change everything or this one. also, should se just store
1406 * the pointer to friend in routing table rather than gnunet_peeridentity.
1407 * if yes then we should keep friend info in.h andmake lot of changes.
1408 * Construct a trail teardown message and forward it to target friend.
1409 *
1410 * @param trail_id Unique identifier of the trail.
1411 * @param trail_direction Direction of trail.
1412 * @param target_friend Friend to get this message.
1413 */
1414void
1415GDS_NEIGHBOURS_send_trail_teardown (const struct GNUNET_HashCode *trail_id,
1416 unsigned int trail_direction,
1417 const struct GNUNET_PeerIdentity *peer)
1418{
1419 struct PeerTrailTearDownMessage *ttdm;
1420 struct P2PPendingMessage *pending;
1421 struct FriendInfo *target_friend;
1422 size_t msize;
1423
1424 msize = sizeof (struct PeerTrailTearDownMessage);
1425 if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
1426 {
1427 GNUNET_break (0);
1428 return;
1429 }
1430
1431 if (NULL == (target_friend =
1432 GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer)))
1433 {
1434 /* FIXME: In what case friend can be null. ?*/
1435 GNUNET_break (0);
1436 return;
1437 }
1438
1439 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1440 {
1441 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1442 1, GNUNET_NO);
1443 }
1444
1445 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1446 pending->importance = 0; /* FIXME */
1447 pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT);
1448 ttdm = (struct PeerTrailTearDownMessage *) &pending[1];
1449 pending->msg = &ttdm->header;
1450 ttdm->header.size = htons (msize);
1451 ttdm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_TEARDOWN);
1452 ttdm->trail_id = *trail_id;
1453 ttdm->trail_direction = htonl (trail_direction);
1454
1455 /* Send the message to chosen friend. */
1456 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1457 target_friend->pending_count++;
1458 process_friend_queue (target_friend);
1459}
1460
1461
1462/**
1463 * Construct a verify successor result message and send it to target_friend
1464 * @param querying_peer Peer which sent the verify successor message.
1465 * @param source_successor Current_successor of @a querying_peer.
1466 * @param current_predecessor Current predecessor of @a successor. Could be same
1467 * or different from @a querying_peer.
1468 * @param trail_id Unique identifier of the trail from @a querying_peer to
1469 * @a successor, NOT including them.
1470 * @param trail List of peers which are part of trail from @a querying_peer to
1471 * @a successor, NOT including them.
1472 * @param trail_length Total number of peers in @a trail
1473 * @param trail_direction Direction in which we are sending the message. In this
1474 * case we are sending result from @a successor to @a querying_peer.
1475 * @param target_friend Next friend to get this message.
1476 */
1477void
1478GDS_NEIGHBOURS_send_verify_successor_result (struct GNUNET_PeerIdentity querying_peer,
1479 struct GNUNET_PeerIdentity current_successor,
1480 struct GNUNET_PeerIdentity probable_successor,
1481 struct GNUNET_HashCode trail_id,
1482 const struct GNUNET_PeerIdentity *trail,
1483 unsigned int trail_length,
1484 enum GDS_ROUTING_trail_direction trail_direction,
1485 struct FriendInfo *target_friend)
1486{
1487 struct PeerVerifySuccessorResultMessage *vsmr;
1488 struct P2PPendingMessage *pending;
1489 struct GNUNET_PeerIdentity *peer_list;
1490 size_t msize;
1491
1492 msize = sizeof (struct PeerVerifySuccessorResultMessage) +
1493 (trail_length * sizeof(struct GNUNET_PeerIdentity));
1494
1495 if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
1496 {
1497 GNUNET_break (0);
1498 return;
1499 }
1500
1501 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1502 {
1503 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1504 1, GNUNET_NO);
1505 }
1506
1507 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1508 pending->importance = 0; /* FIXME */
1509 pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT);
1510 vsmr = (struct PeerVerifySuccessorResultMessage *) &pending[1];
1511 pending->msg = &vsmr->header;
1512 vsmr->header.size = htons (msize);
1513 vsmr->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_VERIFY_SUCCESSOR_RESULT);
1514 vsmr->querying_peer = querying_peer;
1515 vsmr->current_successor = current_successor;
1516 vsmr->probable_successor = probable_successor;
1517 vsmr->trail_direction = htonl (trail_direction);
1518 vsmr->trail_id = trail_id;
1519 peer_list = (struct GNUNET_PeerIdentity *) &vsmr[1];
1520 memcpy (peer_list, trail, trail_length * sizeof (struct GNUNET_PeerIdentity));
1521
1522 /* Send the message to chosen friend. */
1523 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1524 target_friend->pending_count++;
1525 process_friend_queue (target_friend);
1526}
1527
1528
1529/**
1530 * Construct a notify new successor message and send it to target_friend
1531 * @param source_peer Peer which wants to notify to its new successor that it
1532 * could be its predecessor.
1533 * @param successor New successor of @a source_peer
1534 * @param successor_trail List of peers in Trail to reach from
1535 * @a source_peer to @a new_successor, NOT including
1536 * the endpoints.
1537 * @param successor_trail_length Total number of peers in @a new_successor_trail.
1538 * @param successor_trail_id Unique identifier of @a new_successor_trail.
1539 * @param target_friend Next friend to get this message.
1540 */
1541void
1542GDS_NEIGHBOURS_send_notify_new_successor (struct GNUNET_PeerIdentity source_peer,
1543 struct GNUNET_PeerIdentity successor,
1544 const struct GNUNET_PeerIdentity *successor_trail,
1545 unsigned int successor_trail_length,
1546 struct GNUNET_HashCode succesor_trail_id,
1547 struct FriendInfo *target_friend)
1548{
1549 struct PeerNotifyNewSuccessorMessage *nsm;
1550 struct P2PPendingMessage *pending;
1551 struct GNUNET_PeerIdentity *peer_list;
1552 size_t msize;
1553
1554 msize = sizeof (struct PeerNotifyNewSuccessorMessage) +
1555 (successor_trail_length * sizeof(struct GNUNET_PeerIdentity));
1556
1557 if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
1558 {
1559 GNUNET_break (0);
1560 return;
1561 }
1562
1563 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1564 {
1565 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1566 1, GNUNET_NO);
1567 }
1568
1569 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1570 pending->importance = 0; /* FIXME */
1571 pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT);
1572 nsm = (struct PeerNotifyNewSuccessorMessage *) &pending[1];
1573 pending->msg = &nsm->header;
1574 nsm->header.size = htons (msize);
1575 nsm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_NOTIFY_NEW_SUCCESSOR);
1576 nsm->new_successor = successor;
1577 nsm->source_peer = source_peer;
1578 nsm->trail_id = succesor_trail_id;
1579 peer_list = (struct GNUNET_PeerIdentity *) &nsm[1];
1580 memcpy (peer_list, successor_trail,
1581 successor_trail_length * sizeof (struct GNUNET_PeerIdentity));
1582
1583 /* Send the message to chosen friend. */
1584 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1585 target_friend->pending_count++;
1586 process_friend_queue (target_friend);
1587}
1588
1589
1590/**
1591 * Construct an add_trail message and send it to target_friend
1592 * @param source_peer Source of the trail.
1593 * @param destination_peer Destination of the trail.
1594 * @param trail_id Unique identifier of the trail from
1595 * @a source_peer to @a destination_peer, NOT including the endpoints.
1596 * @param trail List of peers in Trail from @a source_peer to @a destination_peer,
1597 * NOT including the endpoints.
1598 * @param trail_length Total number of peers in @a trail.
1599 * @param target_friend Next friend to get this message.
1600 */
1601void
1602GDS_NEIGHBOURS_send_add_trail (struct GNUNET_PeerIdentity source_peer,
1603 struct GNUNET_PeerIdentity destination_peer,
1604 struct GNUNET_HashCode trail_id,
1605 const struct GNUNET_PeerIdentity *trail,
1606 unsigned int trail_length,
1607 struct FriendInfo *target_friend)
1608{
1609 struct PeerAddTrailMessage *adm;
1610 struct GNUNET_PeerIdentity *peer_list;
1611 struct P2PPendingMessage *pending;
1612 size_t msize;
1613
1614 msize = sizeof (struct PeerAddTrailMessage) +
1615 (trail_length * sizeof(struct GNUNET_PeerIdentity));
1616
1617 if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
1618 {
1619 GNUNET_break (0);
1620 return;
1621 }
1622
1623 if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND)
1624 {
1625 GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"),
1626 1, GNUNET_NO);
1627 }
1628
1629 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
1630 pending->importance = 0; /* FIXME */
1631 pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT);
1632 adm = (struct PeerAddTrailMessage *) &pending[1];
1633 pending->msg = &adm->header;
1634 adm->header.size = htons (msize);
1635 adm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_ADD_TRAIL);
1636 adm->source_peer = source_peer;
1637 adm->destination_peer = destination_peer;
1638 adm->trail_id = trail_id;
1639 peer_list = (struct GNUNET_PeerIdentity *)&adm[1];
1640 memcpy (peer_list, trail, sizeof (struct GNUNET_PeerIdentity) * trail_length);
1641
1642 /* Send the message to chosen friend. */
1643 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
1644 target_friend->pending_count++;
1645 process_friend_queue (target_friend);
1646
1647}
1648
1649
1650/**
1651 * Search my location in trail. In case I am present more than once in the
1652 * trail (can happen during trail setup), then return my lowest index.
1653 * @param trail List of peers
1654 * @return my_index if found
1655 * trail_length + 1 if an entry is present twice, It is an error.
1656 * -1 if no entry found.
1657 */
1658static int
1659search_my_index (const struct GNUNET_PeerIdentity *trail,
1660 int trail_length)
1661{
1662 int i;
1663 int index_seen = trail_length + 1;
1664 int flag = 0;
1665
1666 for (i = 0; i < trail_length; i++)
1667 {
1668 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &trail[i]))
1669 {
1670 flag = 1;
1671 if(index_seen == (trail_length + 1))
1672 index_seen = i;
1673 else
1674 {
1675 DEBUG("Entry is present twice in trail. Its not allowed\n");
1676 }
1677 break;
1678 }
1679 }
1680
1681 if (1 == flag)
1682 return index_seen;
1683 else
1684 return -1;
1685}
1686
1687
1688/**
1689 * Check if the friend is congested or have reached maximum number of trails
1690 * it can be part of of.
1691 * @param friend Friend to be checked.
1692 * @return #GNUNET_NO if friend is not congested or have not crossed threshold.
1693 * #GNUNET_YES if friend is either congested or have crossed threshold
1694 */
1695static int
1696is_friend_congested (struct FriendInfo *friend)
1697{
1698 if (( friend->trails_count < TRAILS_THROUGH_FRIEND_THRESHOLD) &&
1699 ((0 == GNUNET_TIME_absolute_get_remaining
1700 (friend->congestion_timestamp).rel_value_us)))
1701 return GNUNET_NO;
1702 else
1703 return GNUNET_YES;
1704}
1705
1706
1707/**
1708 * Select closest finger to value.
1709 * @param peer1 First peer
1710 * @param peer2 Second peer
1711 * @param value Value to be compare
1712 * @return Closest peer
1713 */
1714static struct GNUNET_PeerIdentity
1715select_closest_finger (const struct GNUNET_PeerIdentity *peer1,
1716 const struct GNUNET_PeerIdentity *peer2,
1717 uint64_t value)
1718{
1719 uint64_t peer1_value;
1720 uint64_t peer2_value;
1721
1722 memcpy (&peer1_value, peer1, sizeof (uint64_t));
1723 memcpy (&peer2_value, peer2, sizeof (uint64_t));
1724 peer1_value = GNUNET_ntohll (peer1_value);
1725 peer2_value = GNUNET_ntohll (peer2_value);
1726
1727 if (peer1_value == value)
1728 {
1729 return *peer1;
1730 }
1731
1732 if (peer2_value == value)
1733 {
1734 return *peer2;
1735 }
1736
1737 if (value < peer1_value && peer1_value < peer2_value)
1738 {
1739 return *peer1;
1740 }
1741 else if (value < peer2_value && peer2_value < peer1_value)
1742 {
1743 return *peer2;
1744 }
1745 else if (peer1_value < value && value < peer2_value)
1746 {
1747 return *peer2;
1748 }
1749 else if (peer2_value < value && value < peer1_value)
1750 {
1751 return *peer1;
1752 }
1753 else if (peer1_value < peer2_value && peer2_value < value)
1754 {
1755 return *peer1;
1756 }
1757 else // if (peer2_value < peer1_value && peer1_value < value)
1758 {
1759 return *peer2;
1760 }
1761}
1762
1763
1764/**
1765 * Select closest predecessor to value.
1766 * @param peer1 First peer
1767 * @param peer2 Second peer
1768 * @param value Value to be compare
1769 * @return Peer which precedes value in the network.
1770 */
1771static struct GNUNET_PeerIdentity
1772select_closest_predecessor (const struct GNUNET_PeerIdentity *peer1,
1773 const struct GNUNET_PeerIdentity *peer2,
1774 uint64_t value)
1775{
1776 uint64_t peer1_value;
1777 uint64_t peer2_value;
1778
1779 memcpy (&peer1_value, peer1, sizeof (uint64_t));
1780 memcpy (&peer2_value, peer2, sizeof (uint64_t));
1781 peer1_value = GNUNET_ntohll (peer1_value);
1782 peer2_value = GNUNET_ntohll (peer2_value);
1783
1784 if (peer1_value == value)
1785 {
1786 return *peer1;
1787 }
1788
1789 if (peer2_value == value)
1790 {
1791 return *peer2;
1792 }
1793
1794 if (value < peer1_value && peer1_value < peer2_value)
1795 {
1796 return *peer2;
1797 }
1798 else if (value < peer2_value && peer2_value < peer1_value)
1799 {
1800 return *peer1;
1801 }
1802 else if (peer1_value < value && value < peer2_value)
1803 {
1804 return *peer1;
1805 }
1806 else if (peer2_value < value && value < peer1_value)
1807 {
1808 return *peer2;
1809 }
1810 else if (peer1_value < peer2_value && peer2_value < value)
1811 {
1812 return *peer2;
1813 }
1814 else // if (peer2_value < peer1_value && peer1_value < value)
1815 {
1816 return *peer1;
1817 }
1818}
1819
1820#if 0
1821/**
1822 *
1823 *
1824 */
1825void
1826test_print_trail (struct GNUNET_PeerIdentity *trail,
1827 unsigned int trail_length)
1828{
1829 struct GNUNET_PeerIdentity print_peer;
1830 int i;
1831
1832 FPRINTF (stderr,_("\nSUPU %s, %s, %d,trail_length = %d"),
1833 __FILE__, __func__,__LINE__,trail_length);
1834 for (i =0 ; i< trail_length; i++)
1835 {
1836 print_peer = trail[i];
1837 FPRINTF (stderr,_("\nSUPU %s, %s, %d,trail[%d]=%s"),
1838 __FILE__, __func__,__LINE__,i,GNUNET_i2s(&print_peer));
1839 }
1840}
1841#endif
1842
1843#if 0
1844/**
1845 * This is a test function to print all the entries of friend table.
1846 */
1847static void
1848test_friend_peermap_print ()
1849{
1850 struct FriendInfo *friend;
1851 struct GNUNET_CONTAINER_MultiPeerMapIterator *friend_iter;
1852 struct GNUNET_PeerIdentity print_peer;
1853 struct GNUNET_PeerIdentity key_ret;
1854 int i;
1855
1856 print_peer = my_identity;
1857 FPRINTF (stderr,_("\nSUPU************ FRIEND_PEERMAP of %s"),GNUNET_i2s(&print_peer));
1858 friend_iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap);
1859
1860 for (i = 0; i < GNUNET_CONTAINER_multipeermap_size (friend_peermap); i++)
1861 {
1862 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (friend_iter,
1863 &key_ret,
1864 (const void **)&friend))
1865 {
1866 memcpy (&print_peer, &key_ret, sizeof (struct GNUNET_PeerIdentity));
1867 FPRINTF (stderr,_("\nSUPU %s, %s, %d, friend = %s, friend->trails_count = %d"),
1868 __FILE__, __func__,__LINE__, GNUNET_i2s(&print_peer), friend->trails_count);
1869 }
1870 }
1871}
1872#endif
1873
1874#if 0
1875/**
1876 * This is a test function, to print all the entries of finger table.
1877 */
1878static void
1879test_finger_table_print()
1880{
1881 struct FingerInfo *finger;
1882 struct GNUNET_PeerIdentity print_peer;
1883 //struct Trail *trail;
1884 int i;
1885 //int j;
1886 //int k;
1887 print_peer = my_identity;
1888 FPRINTF (stderr,_("\nSUPU************ FINGER_TABLE of %s"),GNUNET_i2s(&print_peer));
1889 for (i = 0; i < MAX_FINGERS; i++)
1890 {
1891 finger = &finger_table[i];
1892
1893 if (GNUNET_NO == finger->is_present)
1894 continue;
1895
1896 print_peer = finger->finger_identity;
1897 FPRINTF (stderr,_("\nSUPU %s, %s, %d, finger_table[%d] = %s, trails_count = %d"),
1898 __FILE__, __func__,__LINE__,i,GNUNET_i2s (&print_peer), finger->trails_count);
1899
1900#if 0
1901 for (j = 0; j < finger->trails_count; j++)
1902 {
1903 trail = &finger->trail_list[j];
1904 FPRINTF (stderr,_("\nSUPU %s, %s, %d, trail_id[%d]=%s"),__FILE__, __func__,__LINE__,j, GNUNET_h2s(&trail->trail_id));
1905 struct Trail_Element *element;
1906 element = trail->trail_head;
1907 for (k = 0; k < trail->trail_length; k++)
1908 {
1909 print_peer = element->peer;
1910 FPRINTF (stderr,_("\nSUPU %s, %s, %d,trail[%d] = %s "),__FILE__, __func__,__LINE__,k, GNUNET_i2s(&print_peer));
1911 element = element->next;
1912 }
1913 }
1914 #endif
1915 }
1916}
1917#endif
1918
1919/**
1920 * Select the closest peer among two peers (which should not be same)
1921 * with respect to value and finger_table_index
1922 * NOTE: peer1 != peer2
1923 * @param peer1 First peer
1924 * @param peer2 Second peer
1925 * @param value Value relative to which we find the closest
1926 * @param is_predecessor Is value a predecessor or any other finger.
1927 * @return Closest peer among two peers.
1928 */
1929static struct GNUNET_PeerIdentity
1930select_closest_peer (const struct GNUNET_PeerIdentity *peer1,
1931 const struct GNUNET_PeerIdentity *peer2,
1932 uint64_t value,
1933 unsigned int is_predecessor)
1934{
1935 /* This check is here to ensure that calling function never sends
1936 same peer value in peer1 and peer2. Remove it later. */
1937 GNUNET_assert(0 != GNUNET_CRYPTO_cmp_peer_identity (peer1, peer2));
1938 if (1 == is_predecessor)
1939 return select_closest_predecessor (peer1, peer2, value);
1940
1941 // TODO: Change name to something like select_closest_successor!!
1942 return select_closest_finger (peer1, peer2, value);
1943}
1944
1945
1946/**
1947 * Iterate over the list of all the trails of a finger. In case the first
1948 * friend to reach the finger has reached trail threshold or is congested,
1949 * then don't select it. In case there multiple available good trails to reach
1950 * to Finger, choose the one with shortest trail length.
1951 * Note: We use length as parameter. But we can use any other suitable parameter
1952 * also.
1953 * @param finger Finger Finger whose trail we have to select.
1954 * @return Trail Selected Trail.
1955 */
1956static struct Trail *
1957select_finger_trail (struct FingerInfo *finger)
1958{
1959 struct FriendInfo *friend;
1960 struct Trail *current_finger_trail;
1961 struct Trail *best_trail = NULL;
1962 unsigned int i;
1963
1964 GNUNET_assert (finger->trails_count > 0);
1965 for (i = 0; i < finger->trails_count; i++)
1966 {
1967 current_finger_trail = &finger->trail_list[i];
1968
1969 /* No trail stored at this index. */
1970 if (GNUNET_NO == current_finger_trail->is_present)
1971 continue;
1972
1973 GNUNET_assert (NULL !=
1974 (friend =
1975 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
1976 &current_finger_trail->trail_head->peer)));
1977
1978 /* First friend to reach trail is not free. */
1979 if (GNUNET_YES == is_friend_congested (friend))
1980 continue;
1981
1982 if (NULL == best_trail ||
1983 best_trail->trail_length > current_finger_trail->trail_length)
1984 {
1985 best_trail = current_finger_trail;
1986 }
1987 }
1988
1989 return best_trail;
1990}
1991
1992
1993/**
1994 * Compare FINGER entry with current successor. If finger's first friend of all
1995 * its trail is not congested and has not crossed trail threshold, then check
1996 * if finger peer identity is closer to final_destination_finger_value than
1997 * current_successor. If yes then update current_successor.
1998 * @param current_successor[in/out]
1999 * @return
2000 */
2001static void
2002compare_finger_and_current_closest_peer (struct Closest_Peer *current_closest_peer)
2003{
2004 struct FingerInfo *finger;
2005 struct GNUNET_PeerIdentity closest_peer;
2006 struct Trail *finger_trail;
2007 int i;
2008
2009 /* Iterate over finger table. */
2010 for (i = 0; i < MAX_FINGERS; i++)
2011 {
2012 finger = &finger_table[i];
2013
2014 if (GNUNET_NO == finger->is_present)
2015 continue;
2016
2017 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger->finger_identity,
2018 &current_closest_peer->best_known_destination))
2019 continue;
2020
2021 /* If I am my own finger, then ignore this finger. */
2022 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger->finger_identity,
2023 &my_identity))
2024 continue;
2025
2026 /* If finger is a friend, we have already checked it in previous function. */
2027 if (NULL != (GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2028 &finger->finger_identity)))
2029 {
2030 continue;
2031 }
2032
2033 closest_peer = select_closest_peer (&finger->finger_identity,
2034 &current_closest_peer->best_known_destination,
2035 current_closest_peer->destination_finger_value,
2036 current_closest_peer->is_predecessor);
2037
2038 if (0 == GNUNET_CRYPTO_cmp_peer_identity(&finger->finger_identity, &closest_peer))
2039 {
2040 /* Choose one of the trail to reach to finger. */
2041 finger_trail = select_finger_trail (finger);
2042
2043 /* In case no trail found, ignore this finger. */
2044 if (NULL == finger_trail)
2045 continue;
2046
2047 current_closest_peer->best_known_destination = closest_peer;
2048 current_closest_peer->next_hop = finger_trail->trail_head->peer;
2049 current_closest_peer->trail_id = finger_trail->trail_id;
2050 current_closest_peer->finger_table_index = i;
2051 }
2052 continue;
2053 }
2054}
2055
2056
2057/**
2058 * Compare friend entry with current successor.
2059 * If friend identity and current_successor is same, then do nothing.
2060 * If friend is not congested and has not crossed trail threshold, then check
2061 * if friend peer identity is closer to final_destination_finger_value than
2062 * current_successor. If yes then update current_successor.
2063 * @param cls closure
2064 * @param key current public key
2065 * @param value struct Closest_Peer
2066 * @return #GNUNET_YES if we should continue to iterate,
2067 * #GNUNET_NO if not.
2068 */
2069static int
2070compare_friend_and_current_closest_peer (void *cls,
2071 const struct GNUNET_PeerIdentity *key,
2072 void *value)
2073{
2074 struct FriendInfo *friend = value;
2075 struct Closest_Peer *current_closest_peer = cls;
2076 struct GNUNET_PeerIdentity closest_peer;
2077
2078 /* Friend is either congested or has crossed threshold. */
2079 if (GNUNET_YES == is_friend_congested (friend))
2080 return GNUNET_YES;
2081
2082 /* If current_closest_peer and friend identity are same, then do nothing.*/
2083 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&friend->id,
2084 &current_closest_peer->best_known_destination))
2085 {
2086 GNUNET_break (0);
2087 return GNUNET_YES;
2088 }
2089
2090 closest_peer = select_closest_peer (&friend->id,
2091 &current_closest_peer->best_known_destination,
2092 current_closest_peer->destination_finger_value,
2093 current_closest_peer->is_predecessor);
2094
2095 /* Is friend the closest successor? */
2096 if (0 == GNUNET_CRYPTO_cmp_peer_identity(&friend->id, &closest_peer))
2097 {
2098 current_closest_peer->best_known_destination = friend->id;
2099 current_closest_peer->next_hop = friend->id;
2100 }
2101
2102 return GNUNET_YES;
2103}
2104
2105
2106/**
2107 * Initialize current_successor to my_identity.
2108 * @param my_identity My peer identity
2109 * @return Updated closest_peer
2110 */
2111static struct Closest_Peer
2112init_closest_peer (struct GNUNET_PeerIdentity my_identity,
2113 uint64_t destination_finger_value,
2114 unsigned int is_predecessor)
2115{
2116 struct Closest_Peer current_closest_peer;
2117
2118 memset (&current_closest_peer.trail_id, 0, sizeof(struct GNUNET_HashCode));
2119 current_closest_peer.destination_finger_value = destination_finger_value;
2120 current_closest_peer.is_predecessor = is_predecessor;
2121 current_closest_peer.next_hop = my_identity;
2122 current_closest_peer.best_known_destination = my_identity;
2123 current_closest_peer.finger_table_index = 65; //65 is a for non valid finger table index.
2124 return current_closest_peer;
2125}
2126
2127
2128/**
2129 * Find locally best known peer, among your own identity, friend and finger list,
2130 * which is closest to given destination_finger_value.
2131 *
2132 * NOTE: In case a friend is also a finger, then it is always chosen as friend
2133 * not a finger.
2134 * @param destination_finger_value Peer closest to this value will be the next destination.
2135 * @param is_predecessor Are we looking for predecessor or finger?
2136 * @return Closest_Peer that contains all the relevant field to reach to
2137 * @a destination_finger_value
2138 */
2139static struct Closest_Peer
2140find_local_best_known_next_hop (uint64_t destination_finger_value,
2141 unsigned int is_predecessor)
2142{
2143 struct Closest_Peer current_closest_peer;
2144
2145 /* Initialize current_successor to my_identity. */
2146 current_closest_peer = init_closest_peer (my_identity,
2147 destination_finger_value,
2148 is_predecessor);
2149
2150 /* Compare each friend entry with current_successor and update current_successor
2151 * with friend if its closest. */
2152 GNUNET_assert
2153 (GNUNET_SYSERR !=
2154 GNUNET_CONTAINER_multipeermap_iterate (friend_peermap,
2155 &compare_friend_and_current_closest_peer,
2156 &current_closest_peer));
2157
2158 /* Compare each finger entry with current_successor and update current_successor
2159 * with finger if its closest. */
2160 compare_finger_and_current_closest_peer (&current_closest_peer);
2161 return current_closest_peer;
2162}
2163
2164
2165/**
2166 * Construct a Put message and send it to target_peer.
2167 * @param key Key for the content
2168 * @param block_type Type of the block
2169 * @param options Routing options
2170 * @param desired_replication_level Desired replication count
2171 * @param best_known_dest Peer to which this message should reach eventually,
2172 * as it is best known destination to me.
2173 * @param intermediate_trail_id Trail id in case
2174 * @param target_peer Peer to which this message will be forwarded.
2175 * @param hop_count Number of hops traversed so far.
2176 * @param put_path_length Total number of peers in @a put_path
2177 * @param put_path Number of peers traversed so far
2178 * @param expiration_time When does the content expire
2179 * @param data Content to store
2180 * @param data_size Size of content @a data in bytes
2181 */
2182void
2183GDS_NEIGHBOURS_send_put (const struct GNUNET_HashCode *key,
2184 enum GNUNET_BLOCK_Type block_type,
2185 enum GNUNET_DHT_RouteOption options,
2186 uint32_t desired_replication_level,
2187 struct GNUNET_PeerIdentity best_known_dest,
2188 struct GNUNET_HashCode intermediate_trail_id,
2189 struct GNUNET_PeerIdentity *target_peer,
2190 uint32_t hop_count,
2191 uint32_t put_path_length,
2192 struct GNUNET_PeerIdentity *put_path,
2193 struct GNUNET_TIME_Absolute expiration_time,
2194 const void *data, size_t data_size)
2195{
2196 struct PeerPutMessage *ppm;
2197 struct P2PPendingMessage *pending;
2198 struct FriendInfo *target_friend;
2199 struct GNUNET_PeerIdentity *pp;
2200 size_t msize;
2201
2202 msize = put_path_length * sizeof (struct GNUNET_PeerIdentity) + data_size +
2203 sizeof (struct PeerPutMessage);
2204 if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
2205 {
2206 put_path_length = 0;
2207 msize = data_size + sizeof (struct PeerPutMessage);
2208 }
2209
2210 if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
2211 {
2212 DEBUG("msize = %lu\n",msize);
2213 GNUNET_break (0);
2214 return;
2215 }
2216
2217 GNUNET_assert (NULL !=
2218 (target_friend =
2219 GNUNET_CONTAINER_multipeermap_get (friend_peermap, target_peer)));
2220 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2221 pending->timeout = expiration_time;
2222 ppm = (struct PeerPutMessage *) &pending[1];
2223 pending->msg = &ppm->header;
2224 ppm->header.size = htons (msize);
2225 ppm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_PUT);
2226 ppm->options = htonl (options);
2227 ppm->block_type = htonl (block_type);
2228 ppm->hop_count = htonl (hop_count + 1);
2229 ppm->desired_replication_level = htonl (desired_replication_level);
2230 ppm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time);
2231 ppm->best_known_destination = best_known_dest;
2232 ppm->intermediate_trail_id = intermediate_trail_id;
2233 ppm->key = *key;
2234 pp = (struct GNUNET_PeerIdentity *) &ppm[1];
2235 ppm->put_path_length = htonl (put_path_length);
2236 if(put_path_length > 0)
2237 {
2238 memcpy (pp, put_path,
2239 sizeof (struct GNUNET_PeerIdentity) * put_path_length);
2240 }
2241 memcpy (&pp[put_path_length], data, data_size);
2242 GNUNET_assert (NULL != target_friend);
2243 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2244 target_friend->pending_count++;
2245 process_friend_queue (target_friend);
2246}
2247
2248
2249/**
2250 * Handle the put request from the client.
2251 * @param key Key for the content
2252 * @param block_type Type of the block
2253 * @param options Routing options
2254 * @param desired_replication_level Desired replication count
2255 * @param expiration_time When does the content expire
2256 * @param data Content to store
2257 * @param data_size Size of content @a data in bytes
2258 */
2259void
2260GDS_NEIGHBOURS_handle_put (const struct GNUNET_HashCode *key,
2261 enum GNUNET_BLOCK_Type block_type,
2262 enum GNUNET_DHT_RouteOption options,
2263 uint32_t desired_replication_level,
2264 struct GNUNET_TIME_Absolute expiration_time,
2265 const void *data, size_t data_size)
2266{
2267 struct GNUNET_PeerIdentity best_known_dest;
2268 struct GNUNET_HashCode intermediate_trail_id;
2269 struct GNUNET_PeerIdentity next_hop;
2270 uint64_t key_value;
2271 struct Closest_Peer successor;
2272
2273 memcpy (&key_value, key, sizeof (uint64_t));
2274 key_value = GNUNET_ntohll (key_value);
2275 successor = find_local_best_known_next_hop (key_value,
2276 GDS_FINGER_TYPE_NON_PREDECESSOR);
2277 best_known_dest = successor.best_known_destination;
2278 next_hop = successor.next_hop;
2279 intermediate_trail_id = successor.trail_id;
2280
2281 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&best_known_dest, &my_identity))
2282 {
2283 DEBUG("\n PUT_REQUEST_SUCCESSFUL for key = %s",GNUNET_h2s(key));
2284 /* I am the destination. */
2285 GDS_DATACACHE_handle_put (expiration_time, key, 0, NULL,
2286 block_type,data_size,data);
2287 GDS_CLIENTS_process_put (options, block_type, 0,
2288 ntohl (desired_replication_level),
2289 1, &my_identity, expiration_time, //FIXME: GNUNETnthoh something on expiration time.
2290 key, data, data_size);
2291 return;
2292 }
2293 /* In case we are sending the request to a finger, then send across all of its
2294 trail.*/
2295#if ENABLE_MALICIOUS
2296 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&successor.best_known_destination,
2297 &successor.next_hop))
2298 {
2299 struct FingerInfo *next_hop_finger;
2300 unsigned int i;
2301
2302 next_hop_finger = &finger_table[successor.finger_table_index];
2303 for (i = 0; i < next_hop_finger->trails_count; i++)
2304 {
2305 if (GNUNET_YES == next_hop_finger->trail_list[i].is_present)
2306 {
2307 if(0 == next_hop_finger->trail_list[i].trail_length)
2308 {
2309 GDS_NEIGHBOURS_send_put (key, block_type, options, desired_replication_level,
2310 best_known_dest, intermediate_trail_id, &next_hop,
2311 0, 1, &my_identity, expiration_time,
2312 data, data_size);
2313 return;
2314 }
2315 next_hop = next_hop_finger->trail_list[i].trail_head->peer;
2316 GDS_NEIGHBOURS_send_put (key, block_type, options, desired_replication_level,
2317 best_known_dest,
2318 next_hop_finger->trail_list[i].trail_id,
2319 &next_hop, 0, 1, &my_identity,
2320 expiration_time,
2321 data, data_size);
2322 }
2323 }
2324 return;
2325 }
2326#endif
2327 GDS_NEIGHBOURS_send_put (key, block_type, options, desired_replication_level,
2328 best_known_dest, intermediate_trail_id, &next_hop,
2329 0, 1, &my_identity, expiration_time,
2330 data, data_size);
2331}
2332
2333/**
2334 * Construct a Get message and send it to target_peer.
2335 * @param key Key for the content
2336 * @param block_type Type of the block
2337 * @param options Routing options
2338 * @param desired_replication_level Desired replication count
2339 * @param best_known_dest Peer which should get this message. Same as target peer
2340 * if best_known_dest is a friend else its a finger.
2341 * @param intermediate_trail_id Trail id to reach to @a best_known_dest
2342 * in case it is a finger else set to 0.
2343 * @param target_peer Peer to which this message will be forwarded.
2344 * @param hop_count Number of hops traversed so far.
2345 * @param data Content to store
2346 * @param data_size Size of content @a data in bytes
2347 * @param get_path_length Total number of peers in @a get_path
2348 * @param get_path Number of peers traversed so far
2349 */
2350void
2351GDS_NEIGHBOURS_send_get (const struct GNUNET_HashCode *key,
2352 enum GNUNET_BLOCK_Type block_type,
2353 enum GNUNET_DHT_RouteOption options,
2354 uint32_t desired_replication_level,
2355 struct GNUNET_PeerIdentity best_known_dest,
2356 struct GNUNET_HashCode intermediate_trail_id,
2357 struct GNUNET_PeerIdentity *target_peer,
2358 uint32_t hop_count,
2359 uint32_t get_path_length,
2360 struct GNUNET_PeerIdentity *get_path)
2361{
2362 struct PeerGetMessage *pgm;
2363 struct P2PPendingMessage *pending;
2364 struct FriendInfo *target_friend;
2365 struct GNUNET_PeerIdentity *gp;
2366 size_t msize;
2367
2368 msize = sizeof (struct PeerGetMessage) +
2369 (get_path_length * sizeof (struct GNUNET_PeerIdentity));
2370
2371 if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
2372 {
2373 GNUNET_break (0);
2374 return;
2375 }
2376 GNUNET_assert (NULL !=
2377 (target_friend =
2378 GNUNET_CONTAINER_multipeermap_get (friend_peermap, target_peer)));
2379
2380 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2381 pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT);
2382 pending->importance = 0; /* FIXME */
2383 pgm = (struct PeerGetMessage *) &pending[1];
2384 pending->msg = &pgm->header;
2385 pgm->header.size = htons (msize);
2386 pgm->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_GET);
2387 pgm->get_path_length = htonl (get_path_length);
2388 pgm->best_known_destination = best_known_dest;
2389 pgm->key = *key;
2390 pgm->intermediate_trail_id = intermediate_trail_id;
2391 pgm->hop_count = htonl (hop_count + 1);
2392 pgm->get_path_length = htonl (get_path_length);
2393 gp = (struct GNUNET_PeerIdentity *) &pgm[1];
2394 memcpy (gp, get_path,
2395 sizeof (struct GNUNET_PeerIdentity) * get_path_length);
2396 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2397 target_friend->pending_count++;
2398 process_friend_queue (target_friend);
2399}
2400
2401
2402/**
2403 * Handle the get request from the client file. If I am destination do
2404 * datacache put and return. Else find the target friend and forward message
2405 * to it.
2406 * @param key Key for the content
2407 * @param block_type Type of the block
2408 * @param options Routing options
2409 * @param desired_replication_level Desired replication count
2410 */
2411void
2412GDS_NEIGHBOURS_handle_get(const struct GNUNET_HashCode *key,
2413 enum GNUNET_BLOCK_Type block_type,
2414 enum GNUNET_DHT_RouteOption options,
2415 uint32_t desired_replication_level)
2416{
2417 struct Closest_Peer successor;
2418 struct GNUNET_PeerIdentity best_known_dest;
2419 struct GNUNET_HashCode intermediate_trail_id;
2420 uint64_t key_value;
2421
2422 memcpy (&key_value, key, sizeof (uint64_t));
2423 key_value = GNUNET_ntohll (key_value);
2424
2425 successor = find_local_best_known_next_hop (key_value,
2426 GDS_FINGER_TYPE_NON_PREDECESSOR);
2427
2428 best_known_dest = successor.best_known_destination;
2429 intermediate_trail_id = successor.trail_id;
2430
2431 /* I am the destination. I have the data. */
2432 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity,
2433 &best_known_dest))
2434 {
2435 GDS_DATACACHE_handle_get (key,block_type, NULL, 0,
2436 NULL, 0, 1, &my_identity, NULL,&my_identity);
2437 return;
2438 }
2439
2440#if ENABLE_MALICIOUS
2441 struct GNUNET_PeerIdentity next_hop;
2442 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&successor.best_known_destination,
2443 &successor.next_hop))
2444 {
2445 struct FingerInfo *next_hop_finger;
2446 unsigned int i;
2447
2448 next_hop_finger = &finger_table[successor.finger_table_index];
2449 for (i = 0; i < next_hop_finger->trails_count; i++)
2450 {
2451 if (GNUNET_YES == next_hop_finger->trail_list[i].is_present)
2452 {
2453 if(0 == next_hop_finger->trail_list[i].trail_length)
2454 {
2455 GDS_NEIGHBOURS_send_get (key, block_type, options,
2456 desired_replication_level,
2457 best_known_dest,intermediate_trail_id,
2458 &successor.next_hop,
2459 0, 1, &my_identity);
2460 return;
2461 }
2462 next_hop = next_hop_finger->trail_list[i].trail_head->peer;
2463 GDS_NEIGHBOURS_send_get (key, block_type, options, desired_replication_level,
2464 best_known_dest,
2465 next_hop_finger->trail_list[i].trail_id,
2466 &next_hop, 0, 1, &my_identity);
2467 }
2468 }
2469 return;
2470 }
2471#endif
2472 GDS_NEIGHBOURS_send_get (key, block_type, options, desired_replication_level,
2473 best_known_dest,intermediate_trail_id, &successor.next_hop,
2474 0, 1, &my_identity);
2475}
2476
2477
2478/**
2479 * Send the get result to requesting client.
2480 *
2481 * @param key Key of the requested data.
2482 * @param type Block type
2483 * @param target_peer Next peer to forward the message to.
2484 * @param source_peer Peer which has the data for the key.
2485 * @param put_path_length Number of peers in @a put_path
2486 * @param put_path Path taken to put the data at its stored location.
2487 * @param get_path_length Number of peers in @a get_path
2488 * @param get_path Path taken to reach to the location of the key.
2489 * @param expiration When will this result expire?
2490 * @param data Payload to store
2491 * @param data_size Size of the @a data
2492 */
2493void
2494GDS_NEIGHBOURS_send_get_result (const struct GNUNET_HashCode *key,
2495 enum GNUNET_BLOCK_Type type,
2496 const struct GNUNET_PeerIdentity *target_peer,
2497 const struct GNUNET_PeerIdentity *source_peer,
2498 unsigned int put_path_length,
2499 const struct GNUNET_PeerIdentity *put_path,
2500 unsigned int get_path_length,
2501 const struct GNUNET_PeerIdentity *get_path,
2502 struct GNUNET_TIME_Absolute expiration,
2503 const void *data, size_t data_size)
2504{
2505 struct PeerGetResultMessage *get_result;
2506 struct GNUNET_PeerIdentity *paths;
2507 struct P2PPendingMessage *pending;
2508 struct FriendInfo *target_friend;
2509 int current_path_index;
2510 size_t msize;
2511
2512 msize = (put_path_length + get_path_length )* sizeof (struct GNUNET_PeerIdentity) +
2513 data_size +
2514 sizeof (struct PeerGetResultMessage);
2515
2516 if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
2517 {
2518 put_path_length = 0;
2519 msize = msize - put_path_length * sizeof (struct GNUNET_PeerIdentity);
2520 }
2521
2522 if (msize >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
2523 {
2524 GNUNET_break(0);
2525 return;
2526 }
2527 current_path_index = 0;
2528 if(get_path_length > 0)
2529 {
2530 current_path_index = search_my_index(get_path, get_path_length);
2531 if (-1 == current_path_index)
2532 {
2533 GNUNET_break (0);
2534 return;
2535 }
2536 if ((get_path_length + 1) == current_path_index)
2537 {
2538 DEBUG ("Peer found twice in get path. Not allowed \n");
2539 GNUNET_break (0);
2540 return;
2541 }
2542 }
2543 if (0 == current_path_index)
2544 {
2545 DEBUG ("GET_RESULT TO CLIENT KEY = %s, Peer = %s",GNUNET_h2s(key),GNUNET_i2s(&my_identity));
2546 GDS_CLIENTS_handle_reply (expiration, key, get_path_length,
2547 get_path, put_path_length,
2548 put_path, type, data_size, data);
2549 return;
2550 }
2551
2552 pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize);
2553 pending->timeout = GNUNET_TIME_relative_to_absolute (PENDING_MESSAGE_TIMEOUT);
2554 pending->importance = 0;
2555 get_result = (struct PeerGetResultMessage *)&pending[1];
2556 pending->msg = &get_result->header;
2557 get_result->header.size = htons (msize);
2558 get_result->header.type = htons (GNUNET_MESSAGE_TYPE_XDHT_P2P_GET_RESULT);
2559 get_result->key = *key;
2560 get_result->querying_peer = *source_peer;
2561 get_result->expiration_time = expiration;
2562 get_result->get_path_length = htonl (get_path_length);
2563 get_result->put_path_length = htonl (put_path_length);
2564 paths = (struct GNUNET_PeerIdentity *)&get_result[1];
2565 memcpy (paths, put_path,
2566 put_path_length * sizeof (struct GNUNET_PeerIdentity));
2567 memcpy (&paths[put_path_length], get_path,
2568 get_path_length * sizeof (struct GNUNET_PeerIdentity));
2569 memcpy (&paths[put_path_length + get_path_length], data, data_size);
2570
2571 GNUNET_assert (NULL !=
2572 (target_friend =
2573 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2574 &get_path[current_path_index - 1])));
2575 GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending);
2576 target_friend->pending_count++;
2577 process_friend_queue (target_friend);
2578}
2579
2580
2581/**
2582 * Randomly choose one of your friends (which is not congested and have not crossed
2583 * trail threshold) from the friend_peermap
2584 * @return Friend Randomly chosen friend.
2585 * NULL in case friend peermap is empty, or all the friends are either
2586 * congested or have crossed trail threshold.
2587 */
2588static struct FriendInfo *
2589select_random_friend ()
2590{
2591 unsigned int current_size;
2592 uint32_t index;
2593 unsigned int j = 0;
2594 struct GNUNET_CONTAINER_MultiPeerMapIterator *iter;
2595 struct GNUNET_PeerIdentity key_ret;
2596 struct FriendInfo *friend;
2597
2598 current_size = GNUNET_CONTAINER_multipeermap_size (friend_peermap);
2599
2600 /* No friends.*/
2601 if (0 == current_size)
2602 return NULL;
2603
2604 index = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, current_size);
2605 iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap);
2606
2607 /* Iterate till you don't reach to index. */
2608 for (j = 0; j < index ; j++)
2609 GNUNET_assert (GNUNET_YES ==
2610 GNUNET_CONTAINER_multipeermap_iterator_next (iter, NULL, NULL));
2611
2612 do
2613 {
2614 /* Reset the index in friend peermap to 0 as we reached to the end. */
2615 if (j == current_size)
2616 {
2617 j = 0;
2618 GNUNET_CONTAINER_multipeermap_iterator_destroy (iter);
2619 iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap);
2620
2621 }
2622
2623 /* Get the friend stored at the index, j*/
2624 GNUNET_assert (GNUNET_YES ==
2625 GNUNET_CONTAINER_multipeermap_iterator_next (iter,
2626 &key_ret,
2627 (const void **)&friend));
2628
2629 /* This friend is not congested and has not crossed trail threshold. */
2630 if ((friend->trails_count < TRAILS_THROUGH_FRIEND_THRESHOLD) &&
2631 (0 == GNUNET_TIME_absolute_get_remaining (friend->congestion_timestamp).rel_value_us))
2632 {
2633 break;
2634 }
2635 friend = NULL;
2636 j++;
2637 } while (j != index);
2638
2639 GNUNET_CONTAINER_multipeermap_iterator_destroy (iter);
2640 return friend;
2641}
2642
2643
2644/**
2645 * Compute 64 bit value of finger_identity corresponding to a finger index using
2646 * chord formula.
2647 * For all fingers, n.finger[i] = n + pow (2,i),
2648 * For predecessor, n.finger[PREDECESSOR_FINGER_ID] = n - 1, where
2649 * n = my_identity, i = finger_index, n.finger[i] = 64 bit finger value
2650 * @param finger_index Index corresponding to which we calculate 64 bit value.
2651 * @return 64 bit value.
2652 */
2653static uint64_t
2654compute_finger_identity_value (unsigned int finger_index)
2655{
2656 uint64_t my_id64;
2657
2658 memcpy (&my_id64, &my_identity, sizeof (uint64_t));
2659 my_id64 = GNUNET_ntohll (my_id64);
2660
2661 /* Are we looking for immediate predecessor? */
2662 if (PREDECESSOR_FINGER_ID == finger_index)
2663 return (my_id64 - 1);
2664 else
2665 {
2666 uint64_t add = (uint64_t)1 << finger_index;
2667 return (my_id64 + add);
2668 }
2669}
2670
2671
2672/*
2673 * Choose a random friend. Calculate the next finger identity to search,from
2674 * current_search_finger_index. Start looking for the trail to reach to
2675 * finger identity through this random friend.
2676 *
2677 * @param cls closure for this task
2678 * @param tc the context under which the task is running
2679 */
2680static void
2681send_find_finger_trail_message (void *cls,
2682 const struct GNUNET_SCHEDULER_TaskContext *tc)
2683{
2684 struct FriendInfo *target_friend;
2685 struct GNUNET_HashCode trail_id;
2686 struct GNUNET_HashCode intermediate_trail_id;
2687 unsigned int is_predecessor = 0;
2688 uint64_t finger_id_value;
2689
2690 /* Schedule another send_find_finger_trail_message task. After one round of
2691 * finger search, this time is exponentially backoff. */
2692 find_finger_trail_task_next_send_time.rel_value_us =
2693 find_finger_trail_task_next_send_time.rel_value_us +
2694 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
2695 DHT_FIND_FINGER_TRAIL_INTERVAL.rel_value_us);
2696 find_finger_trail_task =
2697 GNUNET_SCHEDULER_add_delayed (find_finger_trail_task_next_send_time,
2698 &send_find_finger_trail_message,
2699 NULL);
2700
2701 /* No space in my routing table. (Source and destination peers also store entries
2702 * in their routing table). */
2703 if (GNUNET_YES == GDS_ROUTING_threshold_reached())
2704 return;
2705
2706 target_friend = select_random_friend ();
2707 if (NULL == target_friend)
2708 {
2709 return;
2710 }
2711
2712 finger_id_value = compute_finger_identity_value (current_search_finger_index);
2713 if (PREDECESSOR_FINGER_ID == current_search_finger_index)
2714 is_predecessor = 1;
2715
2716 /* Generate a unique trail id for trail we are trying to setup. */
2717 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
2718 &trail_id, sizeof (trail_id));
2719 memset(&intermediate_trail_id, 0, sizeof (struct GNUNET_HashCode));
2720 GDS_NEIGHBOURS_send_trail_setup (my_identity, finger_id_value,
2721 target_friend->id, target_friend, 0, NULL,
2722 is_predecessor, trail_id,
2723 intermediate_trail_id);
2724}
2725
2726
2727/**
2728 * In case there are already maximum number of possible trails to reach to a
2729 * finger, then check if the new trail's length is lesser than any of the
2730 * existing trails.
2731 * If yes then replace that old trail by new trail.
2732 *
2733 * Note: Here we are taking length as a parameter to choose the best possible
2734 * trail, but there could be other parameters also like:
2735 * 1. duration of existence of a trail - older the better.
2736 * 2. if the new trail is completely disjoint than the
2737 * other trails, then may be choosing it is better.
2738 *
2739 * @param finger Finger
2740 * @param new_finger_trail List of peers to reach from me to @a finger, NOT
2741 * including the endpoints.
2742 * @param new_finger_trail_length Total number of peers in @a new_finger_trail
2743 * @param new_finger_trail_id Unique identifier of @a new_finger_trail.
2744 */
2745static void
2746select_and_replace_trail (struct FingerInfo *finger,
2747 const struct GNUNET_PeerIdentity *new_trail,
2748 unsigned int new_trail_length,
2749 struct GNUNET_HashCode new_trail_id)
2750{
2751 struct Trail *current_trail;
2752 unsigned int largest_trail_length;
2753 unsigned int largest_trail_index;
2754 struct Trail_Element *trail_element;
2755 struct GNUNET_PeerIdentity *next_hop;
2756 unsigned int i;
2757
2758 largest_trail_length = new_trail_length;
2759 largest_trail_index = MAXIMUM_TRAILS_PER_FINGER + 1;
2760
2761 GNUNET_assert (MAXIMUM_TRAILS_PER_FINGER == finger->trails_count);
2762
2763 for (i = 0; i < finger->trails_count; i++)
2764 {
2765 current_trail = &finger->trail_list[i];
2766 GNUNET_assert (GNUNET_YES == current_trail->is_present);
2767 if (current_trail->trail_length > largest_trail_length)
2768 {
2769 largest_trail_length = current_trail->trail_length;
2770 largest_trail_index = i;
2771 }
2772 }
2773
2774 /* New trail is not better than existing ones. Send trail teardown. */
2775 if (largest_trail_index == (MAXIMUM_TRAILS_PER_FINGER + 1))
2776 {
2777 next_hop = GDS_ROUTING_get_next_hop (new_trail_id, GDS_ROUTING_SRC_TO_DEST);
2778 GDS_ROUTING_remove_trail (new_trail_id);
2779 GDS_NEIGHBOURS_send_trail_teardown (&new_trail_id,
2780 GDS_ROUTING_SRC_TO_DEST,
2781 next_hop);
2782 return;
2783 }
2784
2785 /* Send trail teardown message across the replaced trail. */
2786 struct Trail *replace_trail = &finger->trail_list[largest_trail_index];
2787 next_hop = GDS_ROUTING_get_next_hop (replace_trail->trail_id, GDS_ROUTING_SRC_TO_DEST);
2788 GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (replace_trail->trail_id));
2789 GDS_NEIGHBOURS_send_trail_teardown (&replace_trail->trail_id,
2790 GDS_ROUTING_SRC_TO_DEST,
2791 next_hop);
2792
2793 /* Free the trail. */
2794 while (NULL != (trail_element = replace_trail->trail_head))
2795 {
2796 GNUNET_CONTAINER_DLL_remove (replace_trail->trail_head,
2797 replace_trail->trail_tail, trail_element);
2798 GNUNET_free_non_null (trail_element);
2799 }
2800
2801 /* Add new trial at that location. */
2802 replace_trail->is_present = GNUNET_YES;
2803 replace_trail->trail_length = new_trail_length;
2804 replace_trail->trail_id = new_trail_id;
2805
2806 for (i = 0; i < new_trail_length; i++)
2807 {
2808 struct Trail_Element *element = GNUNET_new (struct Trail_Element);
2809 element->peer = new_trail[i];
2810
2811 GNUNET_CONTAINER_DLL_insert_tail (replace_trail->trail_head,
2812 replace_trail->trail_tail,
2813 element);
2814 }
2815 /* FIXME: URGENT Are we adding the trail back to the list. */
2816}
2817
2818
2819/**
2820 * Check if the new trail to reach to finger is unique or do we already have
2821 * such a trail present for finger.
2822 * @param existing_finger Finger identity
2823 * @param new_trail New trail to reach @a existing_finger
2824 * @param trail_length Total number of peers in new_trail.
2825 * @return #GNUNET_YES if the new trail is unique
2826 * #GNUNET_NO if same trail is already present.
2827 */
2828static int
2829is_new_trail_unique (struct FingerInfo *existing_finger,
2830 const struct GNUNET_PeerIdentity *new_trail,
2831 unsigned int trail_length)
2832{
2833 struct Trail *current_trail;
2834 struct Trail_Element *trail_element;
2835 int i;
2836 int j;
2837
2838 GNUNET_assert (existing_finger->trails_count > 0);
2839
2840 /* Iterate over list of trails. */
2841 for (i = 0; i < existing_finger->trails_count; i++)
2842 {
2843 current_trail = &(existing_finger->trail_list[i]);
2844 if(GNUNET_NO == current_trail->is_present)
2845 continue;
2846
2847 /* New trail and existing trail length are not same. */
2848 if (current_trail->trail_length != trail_length)
2849 {
2850 return GNUNET_YES;
2851 }
2852
2853 trail_element = current_trail->trail_head;
2854 for (j = 0; j < current_trail->trail_length; j++)
2855 {
2856 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&new_trail[j],
2857 &trail_element->peer))
2858 {
2859 return GNUNET_YES;
2860 }
2861 trail_element = trail_element->next;
2862 }
2863 }
2864 return GNUNET_NO;
2865}
2866
2867/**
2868 * FIXME; In case of multiple trails, we may have a case where a trail from in
2869 * between has been removed, then we should try to find a free slot , not simply
2870 * add a trail at then end of the list.
2871 * Add a new trail at a free slot in trail array of existing finger.
2872 * @param existing_finger Finger
2873 * @param new_finger_trail New trail from me to finger, NOT including endpoints
2874 * @param new_finger_trail_length Total number of peers in @a new_finger_trail
2875 * @param new_finger_trail_id Unique identifier of the trail.
2876 */
2877static void
2878add_new_trail (struct FingerInfo *existing_finger,
2879 const struct GNUNET_PeerIdentity *new_trail,
2880 unsigned int new_trail_length,
2881 struct GNUNET_HashCode new_trail_id)
2882{
2883 struct FriendInfo *friend;
2884 struct Trail *trail;
2885 unsigned int i;
2886 int free_slot = -1;
2887
2888 if (GNUNET_NO == is_new_trail_unique (existing_finger, new_trail,
2889 new_trail_length))
2890 return;
2891
2892 for (i = 0; i < existing_finger->trails_count; i++)
2893 {
2894 if (GNUNET_NO == existing_finger->trail_list[i].is_present)
2895 {
2896 free_slot = i;
2897 break;
2898 }
2899 }
2900
2901 if (-1 == free_slot)
2902 free_slot = i;
2903
2904 trail = &existing_finger->trail_list[free_slot];
2905 GNUNET_assert (GNUNET_NO == trail->is_present);
2906 trail->trail_id = new_trail_id;
2907 trail->trail_length = new_trail_length;
2908 existing_finger->trails_count++;
2909 trail->is_present = GNUNET_YES;
2910 if (0 == new_trail_length)
2911 {
2912 friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2913 &existing_finger->finger_identity);
2914 }
2915 else
2916 {
2917 friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2918 &new_trail[0]);
2919 }
2920 GNUNET_assert (NULL != friend);
2921 friend->trails_count++;
2922 for (i = 0; i < new_trail_length; i++)
2923 {
2924 struct Trail_Element *element;
2925
2926 element = GNUNET_new (struct Trail_Element);
2927 element->peer = new_trail[i];
2928 GNUNET_CONTAINER_DLL_insert_tail (trail->trail_head,
2929 trail->trail_tail,
2930 element);
2931 }
2932
2933 existing_finger->trail_list[free_slot].trail_head = trail->trail_head;
2934 existing_finger->trail_list[free_slot].trail_tail = trail->trail_tail;
2935 existing_finger->trail_list[free_slot].trail_length = new_trail_length;
2936 existing_finger->trail_list[free_slot].trail_id = new_trail_id;
2937 existing_finger->trail_list[free_slot].is_present = GNUNET_YES;
2938}
2939
2940
2941#if 0
2942/**
2943 * FIXME; In case of multiple trails, we may have a case where a trail from in
2944 * between has been removed, then we should try to find a free slot , not simply
2945 * add a trail at then end of the list.
2946 * Add a new trail at a free slot in trail array of existing finger.
2947 * @param existing_finger Finger
2948 * @param new_finger_trail New trail from me to finger, NOT including endpoints
2949 * @param new_finger_trail_length Total number of peers in @a new_finger_trail
2950 * @param new_finger_trail_id Unique identifier of the trail.
2951 */
2952static void
2953add_new_trail (struct FingerInfo *existing_finger,
2954 const struct GNUNET_PeerIdentity *new_trail,
2955 unsigned int new_trail_length,
2956 struct GNUNET_HashCode new_trail_id)
2957{
2958 struct Trail *trail;
2959 struct FriendInfo *first_friend;
2960 int i;
2961 int index;
2962
2963 if (GNUNET_NO == is_new_trail_unique (existing_finger, new_trail,
2964 new_trail_length))
2965 return;
2966
2967 index = existing_finger->trails_count;
2968 trail = &existing_finger->trail_list[index];
2969 GNUNET_assert (GNUNET_NO == trail->is_present);
2970 trail->trail_id = new_trail_id;
2971 trail->trail_length = new_trail_length;
2972 existing_finger->trails_count++;
2973 trail->is_present = GNUNET_YES;
2974
2975 GNUNET_assert (NULL == (GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2976 &existing_finger->finger_identity)));
2977 /* If finger is a friend then we never call this function. */
2978 GNUNET_assert (new_trail_length > 0);
2979
2980 first_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
2981 &new_trail[0]);
2982 first_friend->trails_count++;
2983
2984 for (i = 0; i < new_trail_length; i++)
2985 {
2986 struct Trail_Element *element;
2987
2988 element = GNUNET_new (struct Trail_Element);
2989 element->peer = new_trail[i];
2990 GNUNET_CONTAINER_DLL_insert_tail (trail->trail_head,
2991 trail->trail_tail,
2992 element);
2993 }
2994 /* Do we need to add trail head and trail tail in the trail list itearator.*/
2995 existing_finger->trail_list[index].trail_head = trail->trail_head;
2996 existing_finger->trail_list[index].trail_tail = trail->trail_tail;
2997 existing_finger->trail_list[index].trail_length = new_trail_length;
2998 existing_finger->trail_list[index].trail_id = new_trail_id;
2999 existing_finger->trail_list[index].is_present = GNUNET_YES;
3000}
3001#endif
3002
3003/**
3004 * Get the next hop to send trail teardown message from routing table and
3005 * then delete the entry from routing table. Send trail teardown message for a
3006 * specific trail of a finger.
3007 * @param finger Finger whose trail is to be removed.
3008 * @param trail List of peers in trail from me to a finger, NOT including
3009 * endpoints.
3010 */
3011static void
3012send_trail_teardown (struct FingerInfo *finger,
3013 struct Trail *trail)
3014{
3015 struct FriendInfo *friend;
3016 struct GNUNET_PeerIdentity *next_hop;
3017
3018 next_hop = GDS_ROUTING_get_next_hop (trail->trail_id,
3019 GDS_ROUTING_SRC_TO_DEST);
3020 if (NULL == next_hop)
3021 {
3022// DEBUG(" NO ENTRY FOUND IN %s ROUTING TABLE for trail id %s, line=%d,traillength = %d",
3023// GNUNET_i2s(&my_identity), GNUNET_h2s(&trail->trail_id), __LINE__,trail->trail_length);
3024 return;
3025 }
3026 GNUNET_assert (0 != GNUNET_CRYPTO_cmp_peer_identity (&finger->finger_identity,
3027 &my_identity));
3028
3029 GNUNET_assert(GNUNET_YES == trail->is_present);
3030 if (trail->trail_length > 0)
3031 {
3032 friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
3033 &trail->trail_head->peer);
3034 }
3035 else
3036 {
3037 friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
3038 &finger->finger_identity);
3039 }
3040
3041 if(NULL == friend)
3042 {
3043 DEBUG ("\n LINE NO: = %d, Friend not found for trail id %s of peer %s trail length = %d",
3044 __LINE__,GNUNET_h2s(&trail->trail_id), GNUNET_i2s(&my_identity),trail->trail_length);
3045 return;
3046 }
3047 if (0 != GNUNET_CRYPTO_cmp_peer_identity (next_hop, &friend->id)
3048 && (0 == trail->trail_length))
3049 {
3050 DEBUG ("\n LINE NO: = %d, Friend not found for trail id %s of peer %s trail length = %d",
3051 __LINE__,GNUNET_h2s(&trail->trail_id), GNUNET_i2s(&my_identity),trail->trail_length);
3052 return;
3053 }
3054 GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (trail->trail_id));
3055 friend->trails_count--;
3056 GDS_NEIGHBOURS_send_trail_teardown (&trail->trail_id,
3057 GDS_ROUTING_SRC_TO_DEST,
3058 &friend->id);
3059}
3060
3061
3062/**
3063 * Send trail teardown message across all the trails to reach to finger.
3064 * @param finger Finger whose all the trail should be freed.
3065 */
3066static void
3067send_all_finger_trails_teardown (struct FingerInfo *finger)
3068{
3069 unsigned int i;
3070
3071 for (i = 0; i < finger->trails_count; i++)
3072 {
3073 struct Trail *trail;
3074
3075 trail = &finger->trail_list[i];
3076 if (GNUNET_YES == trail->is_present)
3077 {
3078 send_trail_teardown (finger, trail);
3079 trail->is_present = GNUNET_NO;
3080 }
3081 }
3082}
3083
3084
3085/**
3086 * Free a specific trail
3087 * @param trail List of peers to be freed.
3088 */
3089static void
3090free_trail (struct Trail *trail)
3091{
3092 struct Trail_Element *trail_element;
3093
3094 while (NULL != (trail_element = trail->trail_head))
3095 {
3096 GNUNET_CONTAINER_DLL_remove (trail->trail_head,
3097 trail->trail_tail,
3098 trail_element);
3099 GNUNET_free_non_null (trail_element);
3100 }
3101 trail->trail_head = NULL;
3102 trail->trail_tail = NULL;
3103}
3104
3105
3106/**
3107 * Free finger and its trail.
3108 * @param finger Finger to be freed.
3109 * @param finger_table_index Index at which finger is stored.
3110 */
3111static void
3112free_finger (struct FingerInfo *finger, unsigned int finger_table_index)
3113{
3114 struct Trail *trail;
3115 unsigned int i;
3116 for (i = 0; i < finger->trails_count; i++)
3117 {
3118 trail = &finger->trail_list[i];
3119 if (GNUNET_NO == trail->is_present)
3120 continue;
3121
3122 if (trail->trail_length > 0)
3123 free_trail (trail);
3124 trail->is_present = GNUNET_NO;
3125 }
3126
3127 finger->is_present = GNUNET_NO;
3128 memset ((void *)&finger_table[finger_table_index], 0, sizeof (finger_table[finger_table_index]));
3129}
3130
3131
3132/**
3133 * Add a new entry in finger table at finger_table_index.
3134 * In case I am my own finger, then we don't have a trail. In case of a friend,
3135 * we have a trail with unique id and '0' trail length.
3136 * In case a finger is a friend, then increment the trails count of the friend.
3137 * @param finger_identity Peer Identity of new finger
3138 * @param finger_trail Trail to reach from me to finger (excluding both end points).
3139 * @param finger_trail_length Total number of peers in @a finger_trail.
3140 * @param trail_id Unique identifier of the trail.
3141 * @param finger_table_index Index in finger table.
3142 */
3143static void
3144add_new_finger (struct GNUNET_PeerIdentity finger_identity,
3145 const struct GNUNET_PeerIdentity *finger_trail,
3146 unsigned int finger_trail_length,
3147 struct GNUNET_HashCode trail_id,
3148 unsigned int finger_table_index)
3149{
3150 struct FingerInfo *new_entry;
3151 struct FriendInfo *first_trail_hop;
3152 struct Trail *trail;
3153 unsigned int i;
3154
3155 new_entry = GNUNET_new (struct FingerInfo);
3156 new_entry->finger_identity = finger_identity;
3157 new_entry->finger_table_index = finger_table_index;
3158 new_entry->is_present = GNUNET_YES;
3159
3160 /* If the new entry is my own identity. */
3161 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity,
3162 &finger_identity))
3163 {
3164 new_entry->trails_count = 0;
3165 finger_table[finger_table_index] = *new_entry;
3166 GNUNET_free (new_entry);
3167 return;
3168 }
3169
3170 /* Finger is a friend. */
3171 if (0 == finger_trail_length)
3172 {
3173 new_entry->trail_list[0].trail_id = trail_id;
3174 new_entry->trails_count = 1;
3175 new_entry->trail_list[0].is_present = GNUNET_YES;
3176 new_entry->trail_list[0].trail_length = 0;
3177 new_entry->trail_list[0].trail_head = NULL;
3178 new_entry->trail_list[0].trail_tail = NULL;
3179 finger_table[finger_table_index] = *new_entry;
3180 GNUNET_assert (NULL !=
3181 (first_trail_hop =
3182 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
3183 &finger_identity)));
3184
3185 first_trail_hop->trails_count++;
3186 GNUNET_free (new_entry);
3187 return;
3188 }
3189
3190 GNUNET_assert (NULL !=
3191 (first_trail_hop =
3192 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
3193 &finger_trail[0])));
3194 new_entry->trails_count = 1;
3195 first_trail_hop->trails_count++;
3196 /* Copy the finger trail into trail. */
3197 trail = &new_entry->trail_list[0];
3198 for(i = 0; i < finger_trail_length; i++)
3199 {
3200 struct Trail_Element *element = GNUNET_new (struct Trail_Element);
3201
3202 element->next = NULL;
3203 element->prev = NULL;
3204 element->peer = finger_trail[i];
3205 GNUNET_CONTAINER_DLL_insert_tail (trail->trail_head,
3206 trail->trail_tail,
3207 element);
3208 }
3209
3210 /* Add trail to trail list. */
3211 trail->trail_length = finger_trail_length;
3212 trail->trail_id = trail_id;
3213 trail->is_present = GNUNET_YES;
3214 finger_table[finger_table_index] = *new_entry;
3215 GNUNET_free (new_entry);
3216}
3217
3218
3219/**
3220 * Periodic task to verify current successor. There can be multiple trails to reach
3221 * to successor, choose the shortest one and send verify successor message
3222 * across that trail.
3223 * @param cls closure for this task
3224 * @param tc the context under which the task is running
3225 */
3226static void
3227send_verify_successor_message (void *cls,
3228 const struct GNUNET_SCHEDULER_TaskContext *tc)
3229{
3230 struct FriendInfo *target_friend;
3231 struct GNUNET_HashCode trail_id;
3232 struct Trail *trail;
3233 struct Trail_Element *element;
3234 unsigned int trail_length;
3235 unsigned int i = 0;
3236 struct FingerInfo *successor;
3237
3238 successor = &finger_table[0];
3239
3240 /* This task will be scheduled when the result for Verify Successor is received. */
3241 send_verify_successor_task = NULL;
3242
3243 /* When verify successor is being called for first time *for current context*
3244 * cls will be NULL. If send_verify_successor_retry_task is not NO_TASK, we
3245 * must cancel the retry task scheduled for verify_successor of previous
3246 * context.
3247 */
3248 if (NULL == cls)
3249 {
3250 /* FIXME: Here we are scheduling a new verify successor task, as we
3251 got a new successor. But a send verify successor task may be in progress.
3252 1. We need to be sure that this is indeed a new successor. As this function
3253 is called even if we add a new trail to reach t old successor.
3254 2. Assuming the new successor is different, then verify successor message
3255 * to old successor may be following stages.
3256 * --> Waiting for verify successor result. Don't wait anymore. there is
3257 * no trail to reach from old successor to me, hence, routing
3258 * lookup will fail.
3259 * --> Waiting for notify confirmation. again don't wait for it. notify
3260 * confirmation will not succeded.
3261 */
3262 if (send_verify_successor_retry_task != NULL)
3263 {
3264 /* FIXME: Are we scheduling retry task as soon as we send verify message.
3265 If yes then here before making this task, first check if the message
3266 is for the same peer again. */
3267 struct VerifySuccessorContext *old_ctx =
3268 GNUNET_SCHEDULER_cancel(send_verify_successor_retry_task);
3269 /* old_ctx must not be NULL, as the retry task had been scheduled */
3270 GNUNET_assert(NULL != old_ctx);
3271 GNUNET_free(old_ctx);
3272 /* FIXME: Why don't we reset the task to NO_TASK here? */
3273 }
3274
3275 struct VerifySuccessorContext *ctx;
3276 ctx = GNUNET_new(struct VerifySuccessorContext);
3277
3278 ctx->num_retries_scheduled++;
3279 send_verify_successor_retry_task =
3280 GNUNET_SCHEDULER_add_delayed (verify_successor_retry_time,
3281 &send_verify_successor_message,
3282 ctx);
3283 }
3284 else
3285 {
3286 /* This is a retry attempt for verify_successor for a previous context */
3287 struct VerifySuccessorContext *ctx;
3288
3289 ctx = cls;
3290 ctx->num_retries_scheduled++;
3291 send_verify_successor_retry_task =
3292 GNUNET_SCHEDULER_add_delayed (verify_successor_retry_time,
3293 &send_verify_successor_message,
3294 ctx);
3295 }
3296
3297 /* Among all the trails to reach to successor, select first one which is present.*/
3298 for (i = 0; i < successor->trails_count; i++)
3299 {
3300 trail = &successor->trail_list[i];
3301 if(GNUNET_YES == trail->is_present)
3302 break;
3303 }
3304
3305 /* No valid trail found to reach to successor. */
3306 if (i == successor->trails_count)
3307 return;
3308
3309 GNUNET_assert(0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity,
3310 &successor->finger_identity));
3311 /* Trail stored at this index. */
3312 GNUNET_assert (GNUNET_YES == trail->is_present);
3313 trail_id = trail->trail_id;
3314 if (NULL == GDS_ROUTING_get_next_hop(trail_id,GDS_ROUTING_SRC_TO_DEST))
3315 {
3316 DEBUG(" NO ENTRY FOUND IN %s ROUTING TABLE for trail id %s, line",
3317 GNUNET_i2s(&my_identity), GNUNET_h2s(&trail->trail_id), __LINE__);
3318 GNUNET_break(0);
3319 return;
3320 }
3321 trail_length = trail->trail_length;
3322 if (trail_length > 0)
3323 {
3324 /* Copy the trail into peer list. */
3325 struct GNUNET_PeerIdentity peer_list[trail_length];
3326 element = trail->trail_head;
3327 for(i = 0; i < trail_length; i++)
3328 {
3329 peer_list[i] = element->peer;
3330 element = element->next;
3331 }
3332 GNUNET_assert (NULL != (target_friend =
3333 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
3334 &peer_list[0])));
3335 GDS_NEIGHBOURS_send_verify_successor_message (my_identity,
3336 successor->finger_identity,
3337 trail_id, peer_list, trail_length,
3338 target_friend);
3339 }
3340 else
3341 {
3342 GNUNET_assert (NULL != (target_friend =
3343 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
3344 &successor->finger_identity)));
3345 GDS_NEIGHBOURS_send_verify_successor_message (my_identity,
3346 successor->finger_identity,
3347 trail_id, NULL, 0,
3348 target_friend);
3349 }
3350}
3351
3352
3353/**
3354 * FIXME: should this be a periodic task, incrementing the search finger index?
3355 * Update the current search finger index.
3356 * @a finger_identity
3357 * @a finger_table_index
3358 */
3359static void
3360update_current_search_finger_index (unsigned int finger_table_index)
3361{
3362 struct FingerInfo *successor;
3363
3364 /* FIXME correct this: only move current index periodically */
3365 if (finger_table_index != current_search_finger_index)
3366 return;
3367
3368 successor = &finger_table[0];
3369 GNUNET_assert (GNUNET_YES == successor->is_present);
3370
3371 /* We were looking for immediate successor. */
3372 if (0 == current_search_finger_index)
3373 {
3374 current_search_finger_index = PREDECESSOR_FINGER_ID;
3375 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &successor->finger_identity))
3376 {
3377 if (NULL == send_verify_successor_task)
3378 {
3379 send_verify_successor_task =
3380 GNUNET_SCHEDULER_add_now (&send_verify_successor_message, NULL);
3381 }
3382 }
3383 return;
3384 }
3385
3386 current_search_finger_index = current_search_finger_index - 1;
3387 return;
3388}
3389
3390
3391/**
3392 * Get the least significant bit set in val.
3393 *
3394 * @param val Value
3395 * @return Position of first bit set, 65 in case of error.
3396 */
3397static unsigned int
3398find_set_bit (uint64_t val)
3399{
3400 uint64_t i;
3401 unsigned int pos;
3402
3403 i = 1;
3404 pos = 0;
3405
3406 while (!(i & val))
3407 {
3408 i = i << 1;
3409 pos++;
3410 if (pos > 63)
3411 {
3412 GNUNET_break (0);
3413 return 65;
3414 }
3415 }
3416
3417 if (val/i != 1)
3418 return 65; /* Some other bit was set to 1 as well. */
3419
3420 return pos;
3421}
3422
3423
3424/**
3425 * Calculate finger_table_index from initial 64 bit finger identity value that
3426 * we send in trail setup message.
3427 * @param ultimate_destination_finger_value Value that we calculated from our
3428 * identity and finger_table_index.
3429 * @param is_predecessor Is the entry for predecessor or not?
3430 * @return finger_table_index Value between 0 <= finger_table_index <= 64
3431 * finger_table_index > PREDECESSOR_FINGER_ID, if error occurs.
3432 */
3433static unsigned int
3434get_finger_table_index (uint64_t ultimate_destination_finger_value,
3435 unsigned int is_predecessor)
3436{
3437 uint64_t my_id64;
3438 uint64_t diff;
3439 unsigned int finger_table_index;
3440
3441 memcpy (&my_id64, &my_identity, sizeof (uint64_t));
3442 my_id64 = GNUNET_ntohll (my_id64);
3443
3444 /* Is this a predecessor finger? */
3445 if (1 == is_predecessor)
3446 {
3447 diff = my_id64 - ultimate_destination_finger_value;
3448 if (1 == diff)
3449 finger_table_index = PREDECESSOR_FINGER_ID;
3450 else
3451 finger_table_index = PREDECESSOR_FINGER_ID + 1; //error value
3452
3453 }
3454 else
3455 {
3456 diff = ultimate_destination_finger_value - my_id64;
3457 finger_table_index = find_set_bit (diff);
3458 }
3459 return finger_table_index;
3460}
3461
3462
3463/**
3464 * Remove finger and its associated data structures from finger table.
3465 * @param existing_finger Finger to be removed which is in finger table.
3466 * @param finger_table_index Index in finger table where @a existing_finger
3467 * is stored.
3468 */
3469static void
3470remove_existing_finger (struct FingerInfo *existing_finger,
3471 unsigned int finger_table_index)
3472{
3473 GNUNET_assert (GNUNET_YES == existing_finger->is_present);
3474
3475 /* If I am my own finger, then we have no trails. */
3476 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&existing_finger->finger_identity,
3477 &my_identity))
3478 {
3479 existing_finger->is_present = GNUNET_NO;
3480 memset ((void *)&finger_table[finger_table_index], 0,
3481 sizeof (finger_table[finger_table_index]));
3482 return;
3483 }
3484
3485 /* For all other fingers, send trail teardown across all the trails to reach
3486 finger, and free the finger. */
3487 send_all_finger_trails_teardown (existing_finger);
3488 free_finger (existing_finger, finger_table_index);
3489}
3490
3491
3492/**
3493 * Check if there is already an entry in finger_table at finger_table_index.
3494 * We get the finger_table_index from 64bit finger value we got from the network.
3495 * -- If yes, then select the closest finger.
3496 * -- If new and existing finger are same, then check if you can store more
3497 * trails.
3498 * -- If yes then add trail, else keep the best trails to reach to the
3499 * finger.
3500 * -- If the new finger is closest, remove the existing entry, send trail
3501 * teardown message across all the trails to reach the existing entry.
3502 * Add the new finger.
3503 * -- If new and existing finger are different, and existing finger is closest
3504 * then do nothing.
3505 * -- Update current_search_finger_index.
3506 * @param finger_identity Peer Identity of new finger
3507 * @param finger_trail Trail to reach the new finger
3508 * @param finger_trail_length Total number of peers in @a new_finger_trail.
3509 * @param is_predecessor Is this entry for predecessor in finger_table?
3510 * @param finger_value 64 bit value of finger identity that we got from network.
3511 * @param finger_trail_id Unique identifier of @finger_trail.
3512 */
3513static void
3514finger_table_add (struct GNUNET_PeerIdentity finger_identity,
3515 const struct GNUNET_PeerIdentity *finger_trail,
3516 unsigned int finger_trail_length,
3517 unsigned int is_predecessor,
3518 uint64_t finger_value,
3519 struct GNUNET_HashCode finger_trail_id)
3520{
3521 struct FingerInfo *existing_finger;
3522 struct GNUNET_PeerIdentity closest_peer;
3523 struct FingerInfo *successor;
3524 unsigned int finger_table_index;
3525
3526 /* Get the finger_table_index corresponding to finger_value we got from network.*/
3527 finger_table_index = get_finger_table_index (finger_value, is_predecessor);
3528
3529 /* Invalid finger_table_index. */
3530 if ((finger_table_index > PREDECESSOR_FINGER_ID))
3531 {
3532 GNUNET_break_op (0);
3533 return;
3534 }
3535
3536 /* Check if new entry is same as successor. */
3537 if ((0 != finger_table_index) &&
3538 (PREDECESSOR_FINGER_ID != finger_table_index))
3539 {
3540 successor = &finger_table[0];
3541 if (GNUNET_NO == successor->is_present)
3542 {
3543 GNUNET_break (0); //ASSERTION FAILS HERE. FIXME
3544 return;
3545 }
3546 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger_identity,
3547 &successor->finger_identity))
3548 {
3549 if (0 == fingers_round_count)
3550 {
3551 find_finger_trail_task_next_send_time =
3552 GNUNET_TIME_STD_BACKOFF(find_finger_trail_task_next_send_time);
3553 }
3554 else
3555 fingers_round_count--;
3556 current_search_finger_index = 0;
3557 GNUNET_STATISTICS_update (GDS_stats,
3558 gettext_noop
3559 ("# FINGERS_COUNT"), (int64_t) total_fingers_found,
3560 GNUNET_NO);
3561 total_fingers_found = 0;
3562 return;
3563 }
3564
3565 struct FingerInfo prev_finger;
3566 prev_finger = finger_table[finger_table_index - 1];
3567 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger_identity,
3568 &prev_finger.finger_identity))
3569 {
3570 current_search_finger_index--;
3571 return;
3572 }
3573 }
3574
3575 total_fingers_found++;
3576 existing_finger = &finger_table[finger_table_index];
3577
3578 /* No entry present in finger_table for given finger map index. */
3579 if (GNUNET_NO == existing_finger->is_present)
3580 {
3581 /* Shorten the trail if possible. */
3582 add_new_finger (finger_identity, finger_trail,
3583 finger_trail_length,
3584 finger_trail_id, finger_table_index);
3585 update_current_search_finger_index (finger_table_index);
3586 return;
3587 }
3588
3589 /* If existing entry and finger identity are not same. */
3590 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&(existing_finger->finger_identity),
3591 &finger_identity))
3592 {
3593 closest_peer = select_closest_peer (&existing_finger->finger_identity,
3594 &finger_identity,
3595 finger_value,
3596 is_predecessor);
3597
3598 /* If the new finger is the closest peer. */
3599 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&finger_identity, &closest_peer))
3600 {
3601 remove_existing_finger (existing_finger, finger_table_index);
3602 add_new_finger (finger_identity, finger_trail, finger_trail_length,
3603 finger_trail_id, finger_table_index);
3604 }
3605 else
3606 {
3607 /* Existing finger is the closest one. We need to send trail teardown
3608 across the trail setup in routing table of all the peers. */
3609 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&finger_identity, &my_identity))
3610 {
3611 if (finger_trail_length > 0)
3612 GDS_NEIGHBOURS_send_trail_teardown (&finger_trail_id,
3613 GDS_ROUTING_SRC_TO_DEST,
3614 &finger_trail[0]);
3615 else
3616 GDS_NEIGHBOURS_send_trail_teardown (&finger_trail_id,
3617 GDS_ROUTING_SRC_TO_DEST,
3618 &finger_identity);
3619 }
3620 }
3621 }
3622 else
3623 {
3624 /* If both new and existing entry are same as my_identity, then do nothing. */
3625 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(existing_finger->finger_identity),
3626 &my_identity))
3627 {
3628 return;
3629 }
3630
3631 /* If there is space to store more trails. */
3632 if (existing_finger->trails_count < MAXIMUM_TRAILS_PER_FINGER)
3633 add_new_trail (existing_finger, finger_trail,
3634 finger_trail_length, finger_trail_id);
3635 else
3636 select_and_replace_trail (existing_finger, finger_trail,
3637 finger_trail_length, finger_trail_id);
3638 }
3639 update_current_search_finger_index (finger_table_index);
3640 return;
3641}
3642
3643
3644/**
3645 * Core handler for P2P put messages.
3646 * @param cls closure
3647 * @param peer sender of the request
3648 * @param message message
3649 * @return #GNUNET_OK to keep the connection open,
3650 * #GNUNET_SYSERR to close it (signal serious error)
3651 */
3652static int
3653handle_dht_p2p_put (void *cls, const struct GNUNET_PeerIdentity *peer,
3654 const struct GNUNET_MessageHeader *message)
3655{
3656 struct PeerPutMessage *put;
3657 struct GNUNET_PeerIdentity *put_path;
3658 struct GNUNET_PeerIdentity current_best_known_dest;
3659 struct GNUNET_PeerIdentity best_known_dest;
3660 struct GNUNET_HashCode received_intermediate_trail_id;
3661 struct GNUNET_HashCode intermediate_trail_id;
3662 struct GNUNET_PeerIdentity next_hop;
3663 struct GNUNET_PeerIdentity *next_routing_hop;
3664 enum GNUNET_DHT_RouteOption options;
3665 struct GNUNET_HashCode test_key;
3666 void *payload;
3667 size_t msize;
3668 uint32_t putlen;
3669 uint32_t hop_count;
3670 size_t payload_size;
3671 uint64_t key_value;
3672
3673 msize = ntohs (message->size);
3674 if (msize < sizeof (struct PeerPutMessage))
3675 {
3676 GNUNET_break_op (0);
3677 return GNUNET_OK;
3678 }
3679
3680 put = (struct PeerPutMessage *) message;
3681 putlen = ntohl (put->put_path_length);
3682 if ((msize <
3683 sizeof (struct PeerPutMessage) +
3684 putlen * sizeof (struct GNUNET_PeerIdentity)) ||
3685 (putlen >
3686 GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3687 {
3688 GNUNET_break_op (0);
3689 return GNUNET_OK;
3690 }
3691#if ENABLE_MALICIOUS
3692 if(1 == act_malicious)
3693 {
3694 DEBUG("\n I AM MALICIOUS PUT_REQUEST_DROPPED for key = %ss",GNUNET_h2s(&put->key));
3695 return GNUNET_OK;
3696 }
3697#endif
3698 GNUNET_STATISTICS_update (GDS_stats,
3699 gettext_noop
3700 ("# Bytes received from other peers"), (int64_t) msize,
3701 GNUNET_NO);
3702
3703 current_best_known_dest = put->best_known_destination;
3704 put_path = (struct GNUNET_PeerIdentity *) &put[1];
3705 payload = &put_path[putlen];
3706 options = ntohl (put->options);
3707 received_intermediate_trail_id = put->intermediate_trail_id;
3708 hop_count = ntohl(put->hop_count);
3709 payload_size = msize - (sizeof (struct PeerPutMessage) +
3710 putlen * sizeof (struct GNUNET_PeerIdentity));
3711 hop_count++;
3712 switch (GNUNET_BLOCK_get_key (GDS_block_context, ntohl (put->block_type),
3713 payload, payload_size, &test_key))
3714 {
3715 case GNUNET_YES:
3716 if (0 != memcmp (&test_key, &put->key, sizeof (struct GNUNET_HashCode)))
3717 {
3718 char *put_s = GNUNET_strdup (GNUNET_h2s_full (&put->key));
3719 GNUNET_break_op (0);
3720 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3721 "PUT with key `%s' for block with key %s\n",
3722 put_s, GNUNET_h2s_full (&test_key));
3723 GNUNET_free (put_s);
3724 return GNUNET_OK;
3725 }
3726 break;
3727 case GNUNET_NO:
3728 GNUNET_break_op (0);
3729 return GNUNET_OK;
3730 case GNUNET_SYSERR:
3731 /* cannot verify, good luck */
3732 break;
3733 }
3734
3735 if (ntohl (put->block_type) == GNUNET_BLOCK_TYPE_REGEX) /* FIXME: do for all tpyes */
3736 {
3737 switch (GNUNET_BLOCK_evaluate (GDS_block_context,
3738 ntohl (put->block_type),
3739 GNUNET_BLOCK_EO_NONE,
3740 NULL, /* query */
3741 NULL, 0, /* bloom filer */
3742 NULL, 0, /* xquery */
3743 payload, payload_size))
3744 {
3745 case GNUNET_BLOCK_EVALUATION_OK_MORE:
3746 case GNUNET_BLOCK_EVALUATION_OK_LAST:
3747 break;
3748
3749 case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE:
3750 case GNUNET_BLOCK_EVALUATION_RESULT_INVALID:
3751 case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT:
3752 case GNUNET_BLOCK_EVALUATION_REQUEST_VALID:
3753 case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID:
3754 case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED:
3755 default:
3756 GNUNET_break_op (0);
3757 return GNUNET_OK;
3758 }
3759 }
3760
3761 /* Check if you are already a part of put path. */
3762 unsigned int i;
3763 for (i = 0; i < putlen; i++)
3764 {
3765 if(0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &put_path[i]))
3766 {
3767 putlen = i;
3768 break;
3769 }
3770 }
3771
3772 /* Add yourself to the list. */
3773 struct GNUNET_PeerIdentity pp[putlen + 1];
3774 //if (0 != (options & GNUNET_DHT_RO_RECORD_ROUTE))
3775 if (1)
3776 {
3777 memcpy (pp, put_path, putlen * sizeof (struct GNUNET_PeerIdentity));
3778 pp[putlen] = my_identity;
3779 putlen++;
3780 }
3781 else
3782 putlen = 0;
3783
3784 memcpy (&key_value, &(put->key), sizeof (uint64_t));
3785 struct Closest_Peer successor;
3786 key_value = GNUNET_ntohll (key_value);
3787 successor = find_local_best_known_next_hop (key_value,
3788 GDS_FINGER_TYPE_NON_PREDECESSOR);
3789 next_hop = successor.next_hop;
3790 intermediate_trail_id = successor.trail_id;
3791 best_known_dest = successor.best_known_destination;
3792
3793 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (&current_best_known_dest, &my_identity)))
3794 {
3795 next_routing_hop = GDS_ROUTING_get_next_hop (received_intermediate_trail_id,
3796 GDS_ROUTING_SRC_TO_DEST);
3797 if (NULL != next_routing_hop)
3798 {
3799 next_hop = *next_routing_hop;
3800 intermediate_trail_id = received_intermediate_trail_id;
3801 best_known_dest = current_best_known_dest;
3802 }
3803 }
3804
3805 GDS_CLIENTS_process_put (options,
3806 ntohl (put->block_type),
3807 hop_count,
3808 ntohl (put->desired_replication_level),
3809 putlen, pp,
3810 GNUNET_TIME_absolute_ntoh (put->expiration_time),
3811 &put->key,
3812 payload,
3813 payload_size);
3814
3815 /* I am the final destination */
3816 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &best_known_dest))
3817 {
3818 DEBUG("\n PUT_REQUEST_SUCCESSFUL for key = %s",GNUNET_h2s(&put->key));
3819 GDS_DATACACHE_handle_put (GNUNET_TIME_absolute_ntoh (put->expiration_time),
3820 &(put->key),putlen, pp, ntohl (put->block_type),
3821 payload_size, payload);
3822 }
3823 else
3824 {
3825#if ENABLE_MALICIOUS
3826 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&successor.best_known_destination,
3827 &successor.next_hop))
3828 {
3829 struct FingerInfo *next_hop_finger;
3830 unsigned int i;
3831
3832 next_hop_finger = &finger_table[successor.finger_table_index];
3833 for (i = 0; i < next_hop_finger->trails_count; i++)
3834 {
3835 if (GNUNET_YES == next_hop_finger->trail_list[i].is_present)
3836 {
3837 if(0 == next_hop_finger->trail_list[i].trail_length)
3838 {
3839 GDS_NEIGHBOURS_send_put (&put->key,
3840 ntohl (put->block_type),ntohl (put->options),
3841 ntohl (put->desired_replication_level),
3842 best_known_dest, intermediate_trail_id, &next_hop,
3843 hop_count, putlen, pp,
3844 GNUNET_TIME_absolute_ntoh (put->expiration_time),
3845 payload, payload_size);
3846 return GNUNET_OK;
3847 }
3848 next_hop = next_hop_finger->trail_list[i].trail_head->peer;
3849 GDS_NEIGHBOURS_send_put (&put->key,
3850 ntohl (put->block_type),ntohl (put->options),
3851 ntohl (put->desired_replication_level),
3852 best_known_dest,
3853 next_hop_finger->trail_list[i].trail_id,
3854 &next_hop, hop_count, putlen, pp,
3855 GNUNET_TIME_absolute_ntoh (put->expiration_time),
3856 payload, payload_size);
3857 }
3858 }
3859 return GNUNET_OK;
3860 }
3861#endif
3862 GDS_NEIGHBOURS_send_put (&put->key,
3863 ntohl (put->block_type),ntohl (put->options),
3864 ntohl (put->desired_replication_level),
3865 best_known_dest, intermediate_trail_id, &next_hop,
3866 hop_count, putlen, pp,
3867 GNUNET_TIME_absolute_ntoh (put->expiration_time),
3868 payload, payload_size);
3869 }
3870 return GNUNET_OK;
3871}
3872
3873
3874/**
3875 * FIXME: Check for loop in the request. If you already are part of get path,
3876 * then you need to reset the get path length.
3877 * Core handler for p2p get requests.
3878 *
3879 * @param cls closure
3880 * @param peer sender of the request
3881 * @param message message
3882 * @return #GNUNET_OK to keep the connection open,
3883 * #GNUNET_SYSERR to close it (signal serious error)
3884 */
3885static int
3886handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer,
3887 const struct GNUNET_MessageHeader *message)
3888{
3889 const struct PeerGetMessage *get;
3890 const struct GNUNET_PeerIdentity *get_path;
3891 struct GNUNET_PeerIdentity best_known_dest;
3892 struct GNUNET_PeerIdentity current_best_known_dest;
3893 struct GNUNET_HashCode intermediate_trail_id;
3894 struct GNUNET_HashCode received_intermediate_trail_id;
3895 struct Closest_Peer successor;
3896 struct GNUNET_PeerIdentity next_hop;
3897 struct GNUNET_PeerIdentity *next_routing_hop;
3898 uint32_t get_length;
3899 uint64_t key_value;
3900 uint32_t hop_count;
3901 size_t msize;
3902
3903 msize = ntohs (message->size);
3904 if (msize < sizeof (struct PeerGetMessage))
3905 {
3906 GNUNET_break_op (0);
3907 return GNUNET_YES;
3908 }
3909
3910 get = (const struct PeerGetMessage *)message;
3911 get_length = ntohl (get->get_path_length);
3912 if ((msize <
3913 sizeof (struct PeerGetMessage) +
3914 get_length * sizeof (struct GNUNET_PeerIdentity)) ||
3915 (get_length >
3916 GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)))
3917 {
3918 GNUNET_break_op (0);
3919 return GNUNET_YES;
3920 }
3921
3922#if ENABLE_MALICIOUS
3923 if(1 == act_malicious)
3924 {
3925 DEBUG("I am malicious,GET_REQUEST_DROPPED for key = %s. \n",GNUNET_h2s(&get->key));
3926 return GNUNET_OK;
3927 }
3928#endif
3929 current_best_known_dest = get->best_known_destination;
3930 received_intermediate_trail_id = get->intermediate_trail_id;
3931 get_path = (const struct GNUNET_PeerIdentity *)&get[1];
3932 hop_count = get->hop_count;
3933 hop_count++;
3934
3935
3936 GNUNET_STATISTICS_update (GDS_stats,
3937 gettext_noop
3938 ("# Bytes received from other peers"), msize,
3939 GNUNET_NO);
3940
3941 memcpy (&key_value, &(get->key), sizeof (uint64_t));
3942 key_value = GNUNET_ntohll (key_value);
3943
3944 /* Check if you are already a part of get path. */
3945 unsigned int i;
3946 for (i = 0; i < get_length; i++)
3947 {
3948 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &get_path[i]))
3949 {
3950 get_length = i;
3951 break;
3952 }
3953 }
3954
3955 /* Add yourself in the get path. */
3956 struct GNUNET_PeerIdentity gp[get_length + 1];
3957 memcpy (gp, get_path, get_length * sizeof (struct GNUNET_PeerIdentity));
3958 gp[get_length] = my_identity;
3959 get_length = get_length + 1;
3960 GDS_CLIENTS_process_get (get->options, get->block_type, hop_count,
3961 get->desired_replication_level, get->get_path_length,
3962 gp, &get->key);
3963
3964
3965 successor = find_local_best_known_next_hop (key_value,
3966 GDS_FINGER_TYPE_NON_PREDECESSOR);
3967 next_hop = successor.next_hop;
3968 best_known_dest = successor.best_known_destination;
3969 intermediate_trail_id = successor.trail_id;
3970 /* I am not the final destination. I am part of trail to reach final dest. */
3971 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (&current_best_known_dest, &my_identity)))
3972 {
3973 next_routing_hop = GDS_ROUTING_get_next_hop (received_intermediate_trail_id,
3974 GDS_ROUTING_SRC_TO_DEST);
3975 if (NULL != next_routing_hop)
3976 {
3977 next_hop = *next_routing_hop;
3978 best_known_dest = current_best_known_dest;
3979 intermediate_trail_id = received_intermediate_trail_id;
3980 }
3981 }
3982
3983 /* I am the final destination. */
3984 if (0 == GNUNET_CRYPTO_cmp_peer_identity(&my_identity, &best_known_dest))
3985 {
3986 if (1 == get_length)
3987 {
3988 DEBUG("\n GET_REQUEST DONE for key = %s",GNUNET_h2s(&get->key));
3989 GDS_DATACACHE_handle_get (&(get->key),(get->block_type), NULL, 0,
3990 NULL, 0, 1, &my_identity, NULL,&my_identity);
3991 }
3992 else
3993 {
3994 GDS_DATACACHE_handle_get (&(get->key),(get->block_type), NULL, 0, NULL, 0,
3995 get_length, gp, &gp[get_length - 2],
3996 &my_identity);
3997 }
3998 }
3999 else
4000 {
4001
4002#if ENABLE_MALICIOUS
4003 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&successor.best_known_destination,
4004 &successor.next_hop))
4005 {
4006 struct FingerInfo *next_hop_finger;
4007 unsigned int i;
4008
4009 next_hop_finger = &finger_table[successor.finger_table_index];
4010 for (i = 0; i < next_hop_finger->trails_count; i++)
4011 {
4012 if(0 == next_hop_finger->trail_list[i].trail_length)
4013 {
4014 GDS_NEIGHBOURS_send_get (&(get->key), get->block_type, get->options,
4015 get->desired_replication_level, best_known_dest,
4016 intermediate_trail_id, &next_hop, hop_count,
4017 get_length, gp);
4018 return GNUNET_OK;
4019 }
4020 if (GNUNET_YES == next_hop_finger->trail_list[i].is_present)
4021 {
4022 next_hop = next_hop_finger->trail_list[i].trail_head->peer;
4023 GDS_NEIGHBOURS_send_get (&(get->key), get->block_type, get->options,
4024 get->desired_replication_level, best_known_dest,
4025 next_hop_finger->trail_list[i].trail_id,
4026 &next_hop, hop_count,
4027 get_length, gp);
4028 }
4029 }
4030 return GNUNET_OK;
4031 }
4032#endif
4033 GDS_NEIGHBOURS_send_get (&(get->key), get->block_type, get->options,
4034 get->desired_replication_level, best_known_dest,
4035 intermediate_trail_id, &next_hop, hop_count,
4036 get_length, gp);
4037 }
4038 return GNUNET_YES;
4039}
4040
4041
4042/**
4043 * Core handler for get result
4044 * @param cls closure
4045 * @param peer sender of the request
4046 * @param message message
4047 * @return #GNUNET_OK to keep the connection open,
4048 * #GNUNET_SYSERR to close it (signal serious error)
4049 */
4050static int
4051handle_dht_p2p_get_result (void *cls, const struct GNUNET_PeerIdentity *peer,
4052 const struct GNUNET_MessageHeader *message)
4053{
4054 const struct PeerGetResultMessage *get_result;
4055 const struct GNUNET_PeerIdentity *get_path;
4056 const struct GNUNET_PeerIdentity *put_path;
4057 const void *payload;
4058 size_t payload_size;
4059 size_t msize;
4060 unsigned int getlen;
4061 unsigned int putlen;
4062 int current_path_index;
4063
4064 msize = ntohs (message->size);
4065 if (msize < sizeof (struct PeerGetResultMessage))
4066 {
4067 GNUNET_break_op (0);
4068 return GNUNET_YES;
4069 }
4070
4071 get_result = (const struct PeerGetResultMessage *)message;
4072 getlen = ntohl (get_result->get_path_length);
4073 putlen = ntohl (get_result->put_path_length);
4074
4075 if ((msize <
4076 sizeof (struct PeerGetResultMessage) +
4077 getlen * sizeof (struct GNUNET_PeerIdentity) +
4078 putlen * sizeof (struct GNUNET_PeerIdentity)) ||
4079 (getlen >
4080 GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity) ||
4081 (putlen >
4082 GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))))
4083 {
4084 GNUNET_break_op (0);
4085 return GNUNET_YES;
4086 }
4087 DEBUG("GET_RESULT FOR DATA_SIZE = %lu\n",msize);
4088 GNUNET_STATISTICS_update (GDS_stats,
4089 gettext_noop
4090 ("# Bytes received from other peers"), msize,
4091 GNUNET_NO);
4092
4093 put_path = (const struct GNUNET_PeerIdentity *) &get_result[1];
4094 get_path = &put_path[putlen];
4095 payload = (const void *) &get_path[getlen];
4096 payload_size = msize - (sizeof (struct PeerGetResultMessage) +
4097 (getlen + putlen) * sizeof (struct GNUNET_PeerIdentity));
4098
4099 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &(get_path[0]))))
4100 {
4101 GDS_CLIENTS_handle_reply (get_result->expiration_time, &(get_result->key),
4102 getlen, get_path, putlen,
4103 put_path, get_result->type, payload_size, payload);
4104 return GNUNET_YES;
4105 }
4106 else
4107 {
4108 current_path_index = search_my_index (get_path, getlen);
4109 if (-1 == current_path_index )
4110 {
4111 DEBUG ("No entry found in get path.\n");
4112 GNUNET_break (0);
4113 return GNUNET_SYSERR;
4114 }
4115 if((getlen + 1) == current_path_index)
4116 {
4117 DEBUG("Present twice in get path. Not allowed. \n");
4118 GNUNET_break (0);
4119 return GNUNET_SYSERR;
4120 }
4121 GDS_NEIGHBOURS_send_get_result (&(get_result->key), get_result->type,
4122 &get_path[current_path_index - 1],
4123 &(get_result->querying_peer), putlen, put_path,
4124 getlen, get_path, get_result->expiration_time,
4125 payload, payload_size);
4126 return GNUNET_YES;
4127 }
4128 return GNUNET_SYSERR;
4129}
4130
4131
4132/**
4133 * Find the next hop to pass trail setup message. First find the local best known
4134 * hop from your own identity, friends and finger. If you were part of trail,
4135 * then get the next hop from routing table. Compare next_hop from routing table
4136 * and local best known hop, and return the closest one to final_dest_finger_val
4137 * @param final_dest_finger_val 64 bit value of finger identity
4138 * @param intermediate_trail_id If you are part of trail to reach to some other
4139 * finger, then it is the trail id to reach to
4140 * that finger, else set to 0.
4141 * @param is_predecessor Are we looking for closest successor or predecessor.
4142 * @param source Source of trail setup message.
4143 * @param current_dest In case you are part of trail, then finger to which
4144 * we should forward the message. Else my own identity
4145 * @return Closest Peer for @a final_dest_finger_val
4146 */
4147static struct Closest_Peer
4148get_local_best_known_next_hop (uint64_t final_dest_finger_val,
4149 struct GNUNET_HashCode intermediate_trail_id,
4150 unsigned int is_predecessor,
4151 struct GNUNET_PeerIdentity source,
4152 struct GNUNET_PeerIdentity *current_dest)
4153{
4154 struct Closest_Peer peer;
4155
4156 peer = find_local_best_known_next_hop (final_dest_finger_val, is_predecessor);
4157
4158 /* Am I just a part of a trail towards a finger (current_destination)? */
4159 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity, current_dest) &&
4160 0 != GNUNET_CRYPTO_cmp_peer_identity (&peer.best_known_destination,
4161 current_dest))
4162 {
4163 struct GNUNET_PeerIdentity closest_peer;
4164
4165 /* Select best successor among one found locally and current_destination
4166 * that we got from network.*/
4167 closest_peer = select_closest_peer (&peer.best_known_destination,
4168 current_dest,
4169 final_dest_finger_val,
4170 is_predecessor);
4171
4172 /* Is current dest (end point of the trail of which I am a part) closest_peer? */
4173 if (0 == GNUNET_CRYPTO_cmp_peer_identity (current_dest, &closest_peer))
4174 {
4175 struct GNUNET_PeerIdentity *next_hop;
4176
4177 next_hop = GDS_ROUTING_get_next_hop (intermediate_trail_id,
4178 GDS_ROUTING_SRC_TO_DEST);
4179 /* next_hop NULL is a valid case. This intermediate trail id is set by
4180 some other finger, and while this trail setup is in progress, that other
4181 peer might have found a better trail ,and send trail teardown message
4182 across the network. In case we got the trail teardown message first,
4183 then next_hop will be NULL. A possible solution could be to keep track
4184 * of all removed trail id, and be sure that there is no other reason . */
4185 if(NULL != next_hop)
4186 {
4187 peer.next_hop = *next_hop;
4188 peer.best_known_destination = *current_dest;
4189 peer.trail_id = intermediate_trail_id;
4190 }
4191 }
4192 }
4193 return peer;
4194}
4195
4196
4197/*
4198 * Core handle for PeerTrailSetupMessage.
4199 * @param cls closure
4200 * @param message message
4201 * @param peer peer identity this notification is about
4202 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
4203 */
4204static int
4205handle_dht_p2p_trail_setup (void *cls, const struct GNUNET_PeerIdentity *peer,
4206 const struct GNUNET_MessageHeader *message)
4207{
4208 const struct PeerTrailSetupMessage *trail_setup;
4209 const struct GNUNET_PeerIdentity *trail_peer_list;
4210 struct GNUNET_PeerIdentity current_dest;
4211 struct FriendInfo *target_friend;
4212 struct GNUNET_PeerIdentity source;
4213 struct GNUNET_HashCode intermediate_trail_id;
4214 struct GNUNET_HashCode trail_id;
4215 unsigned int is_predecessor;
4216 uint32_t trail_length;
4217 uint64_t final_dest_finger_val;
4218 int i;
4219 size_t msize;
4220
4221 msize = ntohs (message->size);
4222 if (msize < sizeof (struct PeerTrailSetupMessage))
4223 {
4224 GNUNET_break_op (0);
4225 return GNUNET_SYSERR;
4226 }
4227
4228 trail_setup = (const struct PeerTrailSetupMessage *) message;
4229 if ((msize - sizeof (struct PeerTrailSetupMessage)) %
4230 sizeof (struct GNUNET_PeerIdentity) != 0)
4231 {
4232 GNUNET_break_op (0);
4233 return GNUNET_OK;
4234 }
4235 trail_length = (msize - sizeof (struct PeerTrailSetupMessage))/
4236 sizeof (struct GNUNET_PeerIdentity);
4237
4238 GNUNET_STATISTICS_update (GDS_stats,
4239 gettext_noop
4240 ("# Bytes received from other peers"), msize,
4241 GNUNET_NO);
4242
4243 trail_peer_list = (const struct GNUNET_PeerIdentity *)&trail_setup[1];
4244 current_dest = trail_setup->best_known_destination;
4245 trail_id = trail_setup->trail_id;
4246 final_dest_finger_val =
4247 GNUNET_ntohll (trail_setup->final_destination_finger_value);
4248 source = trail_setup->source_peer;
4249 is_predecessor = ntohl (trail_setup->is_predecessor);
4250 intermediate_trail_id = trail_setup->intermediate_trail_id;
4251
4252 /* Did the friend insert its ID in the trail list? */
4253 if (trail_length > 0 &&
4254 0 != memcmp (&trail_peer_list[trail_length-1], peer, sizeof (struct GNUNET_PeerIdentity)))
4255 {
4256 GNUNET_break_op (0);
4257 return GNUNET_SYSERR;
4258 }
4259
4260 /* If I was the source and got the message back, then set trail length to 0.*/
4261 if (0 == GNUNET_CRYPTO_cmp_peer_identity(&my_identity, &source))
4262 {
4263 trail_length = 0;
4264 }
4265
4266 /* Check if you are present in the trail seen so far? */
4267 for (i = 0; i < trail_length ; i++)
4268 {
4269 if(0 == GNUNET_CRYPTO_cmp_peer_identity(&trail_peer_list[i],&my_identity))
4270 {
4271 /* We will add ourself later in code, if NOT destination. */
4272 trail_length = i;
4273 break;
4274 }
4275 }
4276
4277 /* Is my routing table full? */
4278 if (GNUNET_YES == GDS_ROUTING_threshold_reached())
4279 {
4280 if (trail_length > 0)
4281 target_friend =
4282 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
4283 &trail_peer_list[trail_length - 1]);
4284 else
4285 target_friend =
4286 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
4287 &source);
4288 if(NULL == target_friend)
4289 {
4290 DEBUG ("\n friend not found");
4291 GNUNET_break(0);
4292 return GNUNET_OK;
4293 }
4294 GDS_NEIGHBOURS_send_trail_rejection (source, final_dest_finger_val,
4295 my_identity, is_predecessor,
4296 trail_peer_list, trail_length,
4297 trail_id, target_friend,
4298 CONGESTION_TIMEOUT);
4299 return GNUNET_OK;
4300 }
4301
4302 /* Get the next hop to forward the trail setup request. */
4303 struct Closest_Peer next_peer =
4304 get_local_best_known_next_hop (final_dest_finger_val,
4305 intermediate_trail_id,
4306 is_predecessor,
4307 source,
4308 &current_dest);
4309
4310 /* Am I the final destination? */
4311 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&next_peer.best_known_destination,
4312 &my_identity)))
4313 {
4314 if(0 == GNUNET_CRYPTO_cmp_peer_identity (&source, &my_identity))
4315 {
4316 finger_table_add (my_identity, NULL, 0, is_predecessor,
4317 final_dest_finger_val, trail_id);
4318 return GNUNET_OK;
4319 }
4320
4321 if (trail_length > 0)
4322 target_friend =
4323 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
4324 &trail_peer_list[trail_length-1]);
4325 else
4326 target_friend =
4327 GNUNET_CONTAINER_multipeermap_get (friend_peermap, &source);
4328 if (NULL == target_friend)
4329 {
4330 GNUNET_break_op (0);
4331 return GNUNET_SYSERR;
4332 }
4333 GDS_ROUTING_add (trail_id, target_friend->id, my_identity);
4334 GDS_NEIGHBOURS_send_trail_setup_result (source,
4335 my_identity,
4336 target_friend, trail_length,
4337 trail_peer_list,
4338 is_predecessor,
4339 final_dest_finger_val,trail_id);
4340 }
4341 else /* I'm not the final destination. */
4342 {
4343 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap,
4344 &next_peer.next_hop);
4345 if(NULL == target_friend)
4346 {
4347 DEBUG ("\n target friend not found for peer = %s", GNUNET_i2s(&next_peer.next_hop));
4348 GNUNET_break (0);
4349 return GNUNET_OK;
4350 }
4351 if (0 != GNUNET_CRYPTO_cmp_peer_identity(&my_identity, &source))
4352 {
4353 /* Add yourself to list of peers. */
4354 struct GNUNET_PeerIdentity peer_list[trail_length + 1];
4355
4356 memcpy (peer_list, trail_peer_list,
4357 trail_length * sizeof (struct GNUNET_PeerIdentity));
4358 peer_list[trail_length] = my_identity;
4359 GDS_NEIGHBOURS_send_trail_setup (source,
4360 final_dest_finger_val,
4361 next_peer.best_known_destination,
4362 target_friend, trail_length + 1, peer_list,
4363 is_predecessor, trail_id,
4364 next_peer.trail_id);
4365 }
4366 else
4367 GDS_NEIGHBOURS_send_trail_setup (source,
4368 final_dest_finger_val,
4369 next_peer.best_known_destination,
4370 target_friend, 0, NULL,
4371 is_predecessor, trail_id,
4372 next_peer.trail_id);
4373 }
4374 return GNUNET_OK;
4375}
4376
4377
4378/**
4379 * Core handle for p2p trail setup result messages.
4380 * @param closure
4381 * @param message message
4382 * @param peer sender of this message.
4383 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
4384 */
4385static int
4386handle_dht_p2p_trail_setup_result(void *cls, const struct GNUNET_PeerIdentity *peer,
4387 const struct GNUNET_MessageHeader *message)
4388{
4389 const struct PeerTrailSetupResultMessage *trail_result;
4390 const struct GNUNET_PeerIdentity *trail_peer_list;
4391 struct GNUNET_PeerIdentity next_hop;
4392 struct FriendInfo *target_friend;
4393 struct GNUNET_PeerIdentity querying_peer;
4394 struct GNUNET_PeerIdentity finger_identity;
4395 uint32_t trail_length;
4396 uint64_t ulitmate_destination_finger_value;
4397 uint32_t is_predecessor;
4398 struct GNUNET_HashCode trail_id;
4399 int my_index;
4400 size_t msize;
4401
4402 msize = ntohs (message->size);
4403 if (msize < sizeof (struct PeerTrailSetupResultMessage))
4404 {
4405 GNUNET_break_op (0);
4406 return GNUNET_YES;
4407 }
4408
4409 trail_result = (const struct PeerTrailSetupResultMessage *) message;
4410 if ((msize - sizeof (struct PeerTrailSetupResultMessage)) %
4411 sizeof (struct GNUNET_PeerIdentity) != 0)
4412 {
4413 GNUNET_break_op (0);
4414 return GNUNET_OK;
4415 }
4416 trail_length = (msize - sizeof (struct PeerTrailSetupResultMessage))/
4417 sizeof (struct GNUNET_PeerIdentity);
4418
4419 GNUNET_STATISTICS_update (GDS_stats,
4420 gettext_noop
4421 ("# Bytes received from other peers"), msize,
4422 GNUNET_NO);
4423
4424 is_predecessor = ntohl (trail_result->is_predecessor);
4425 querying_peer = trail_result->querying_peer;
4426 finger_identity = trail_result->finger_identity;
4427 trail_id = trail_result->trail_id;
4428 trail_peer_list = (const struct GNUNET_PeerIdentity *) &trail_result[1];
4429 ulitmate_destination_finger_value =
4430 GNUNET_ntohll (trail_result->ulitmate_destination_finger_value);
4431
4432 /* Am I the one who initiated the query? */
4433 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&querying_peer, &my_identity)))
4434 {
4435 /* Check that you got the message from the correct peer. */
4436 if (trail_length > 0)
4437 {
4438 GNUNET_assert(0 == GNUNET_CRYPTO_cmp_peer_identity (&trail_peer_list[0],
4439 peer));
4440 }
4441 else
4442 {
4443 GNUNET_assert(0 == GNUNET_CRYPTO_cmp_peer_identity (&finger_identity,
4444 peer));
4445 }
4446 GDS_ROUTING_add (trail_id, my_identity, *peer);
4447 finger_table_add (finger_identity, trail_peer_list, trail_length,
4448 is_predecessor, ulitmate_destination_finger_value, trail_id);
4449 return GNUNET_YES;
4450 }
4451
4452 /* Get my location in the trail. */
4453 my_index = search_my_index (trail_peer_list, trail_length);
4454 if (-1 == my_index)
4455 {
4456 DEBUG ("Not found in trail\n");
4457 GNUNET_break_op(0);
4458 return GNUNET_SYSERR;
4459 }
4460 //TODO; return -2.
4461 if ((trail_length + 1) == my_index)
4462 {
4463 DEBUG ("Found twice in trail.\n");
4464 GNUNET_break_op(0);
4465 return GNUNET_SYSERR;
4466 }
4467
4468 //TODO; Refactor code here and above to check if sender peer is correct
4469 if (my_index == 0)
4470 {
4471 if(trail_length > 1)
4472 GNUNET_assert(0 == GNUNET_CRYPTO_cmp_peer_identity (&trail_peer_list[1],
4473 peer));
4474 else
4475 GNUNET_assert(0 == GNUNET_CRYPTO_cmp_peer_identity (&finger_identity,
4476 peer));
4477 next_hop = trail_result->querying_peer;
4478 }
4479 else
4480 {
4481 if(my_index == trail_length - 1)
4482 {
4483 GNUNET_assert(0 ==
4484 GNUNET_CRYPTO_cmp_peer_identity (&finger_identity,
4485 peer));
4486 }
4487 else
4488 GNUNET_assert(0 ==
4489 GNUNET_CRYPTO_cmp_peer_identity (&trail_peer_list[my_index + 1],
4490 peer));
4491 next_hop = trail_peer_list[my_index - 1];
4492 }
4493
4494 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
4495 if (NULL == target_friend)
4496 {
4497 GNUNET_break_op (0);
4498 return GNUNET_SYSERR;
4499 }
4500 GDS_ROUTING_add (trail_id, next_hop, *peer);
4501 GDS_NEIGHBOURS_send_trail_setup_result (querying_peer, finger_identity,
4502 target_friend, trail_length, trail_peer_list,
4503 is_predecessor,
4504 ulitmate_destination_finger_value,
4505 trail_id);
4506 return GNUNET_OK;
4507}
4508
4509
4510/**
4511 * Invert the trail.
4512 * @param trail Trail to be inverted
4513 * @param trail_length Total number of peers in the trail.
4514 * @return Updated trail
4515 */
4516static struct GNUNET_PeerIdentity *
4517invert_trail (const struct GNUNET_PeerIdentity *trail,
4518 unsigned int trail_length)
4519{
4520 int i;
4521 int j;
4522 struct GNUNET_PeerIdentity *inverted_trail;
4523
4524 inverted_trail = GNUNET_malloc (sizeof(struct GNUNET_PeerIdentity) *
4525 trail_length);
4526 i = 0;
4527 j = trail_length - 1;
4528 while (i < trail_length)
4529 {
4530 inverted_trail[i] = trail[j];
4531 i++;
4532 j--;
4533 }
4534
4535 GNUNET_assert(NULL != GNUNET_CONTAINER_multipeermap_get(friend_peermap,
4536 &inverted_trail[0]));
4537 return inverted_trail;
4538}
4539
4540
4541/**
4542 * Return the shortest trail among all the trails to reach to finger from me.
4543 * @param finger Finger
4544 * @param shortest_trail_length[out] Trail length of shortest trail from me
4545 * to @a finger
4546 * @return Shortest trail.
4547 */
4548static struct GNUNET_PeerIdentity *
4549get_shortest_trail (struct FingerInfo *finger,
4550 unsigned int *trail_length)
4551{
4552 struct Trail *trail;
4553 unsigned int flag = 0;
4554 unsigned int shortest_trail_index = 0;
4555 int shortest_trail_length = -1;
4556 struct Trail_Element *trail_element;
4557 struct GNUNET_PeerIdentity *trail_list;
4558 unsigned int i;
4559
4560 /* Get the shortest trail to reach to current successor. */
4561 for (i = 0; i < finger->trails_count; i++)
4562 {
4563 trail = &finger->trail_list[i];
4564
4565 if (0 == flag)
4566 {
4567 shortest_trail_index = i;
4568 shortest_trail_length = trail->trail_length;
4569 flag = 1;
4570 continue;
4571 }
4572
4573 if (shortest_trail_length > trail->trail_length)
4574 {
4575 shortest_trail_index = i;
4576 shortest_trail_length = trail->trail_length;
4577 }
4578 continue;
4579 }
4580
4581 /* Copy the shortest trail and return. */
4582 trail = &finger->trail_list[shortest_trail_index];
4583 trail_element = trail->trail_head;
4584
4585 trail_list = GNUNET_malloc (sizeof(struct GNUNET_PeerIdentity)*
4586 shortest_trail_length);
4587
4588 for(i = 0; i < shortest_trail_length; i++,trail_element = trail_element->next)
4589 {
4590 trail_list[i] = trail_element->peer;
4591 }
4592
4593 GNUNET_assert(shortest_trail_length != -1);
4594
4595 *trail_length = shortest_trail_length;
4596 return trail_list;
4597}
4598
4599
4600/**
4601 * Check if trail_1 and trail_2 have any common element. If yes then join
4602 * them at common element. trail_1 always preceeds trail_2 in joined trail.
4603 * @param trail_1 Trail from source to me, NOT including endpoints.
4604 * @param trail_1_len Total number of peers @a trail_1
4605 * @param trail_2 Trail from me to current predecessor, NOT including endpoints.
4606 * @param trail_2_len Total number of peers @a trail_2
4607 * @param joined_trail_len Total number of peers in combined trail of trail_1
4608 * trail_2.
4609 * @return Joined trail.
4610 */
4611static struct GNUNET_PeerIdentity *
4612check_for_duplicate_entries (const struct GNUNET_PeerIdentity *trail_1,
4613 unsigned int trail_1_len,
4614 struct GNUNET_PeerIdentity *trail_2,
4615 unsigned int trail_2_len,
4616 unsigned int *joined_trail_len)
4617{
4618 struct GNUNET_PeerIdentity *joined_trail;
4619 unsigned int i;
4620 unsigned int j;
4621 unsigned int k;
4622
4623 for (i = 0; i < trail_1_len; i++)
4624 {
4625 for (j = 0; j < trail_2_len; j++)
4626 {
4627 if(0 != GNUNET_CRYPTO_cmp_peer_identity (&trail_1[i],&trail_2[j]))
4628 continue;
4629
4630 *joined_trail_len = i + (trail_2_len - j);
4631 joined_trail = GNUNET_malloc (*joined_trail_len *
4632 sizeof(struct GNUNET_PeerIdentity));
4633
4634
4635 /* Copy all the elements from 0 to i into joined_trail. */
4636 for(k = 0; k < ( i+1); k++)
4637 {
4638 joined_trail[k] = trail_1[k];
4639 }
4640
4641 /* Increment j as entry stored is same as entry stored at i*/
4642 j = j+1;
4643
4644 /* Copy all the elements from j to trail_2_len-1 to joined trail.*/
4645 while(k <= (*joined_trail_len - 1))
4646 {
4647 joined_trail[k] = trail_2[j];
4648 j++;
4649 k++;
4650 }
4651
4652 return joined_trail;
4653 }
4654 }
4655
4656 /* Here you should join the trails. */
4657 *joined_trail_len = trail_1_len + trail_2_len + 1;
4658 joined_trail = GNUNET_malloc (*joined_trail_len *
4659 sizeof(struct GNUNET_PeerIdentity));
4660
4661
4662 for(i = 0; i < trail_1_len;i++)
4663 {
4664 joined_trail[i] = trail_1[i];
4665 }
4666
4667 joined_trail[i] = my_identity;
4668 i++;
4669
4670 for (j = 0; i < *joined_trail_len; i++,j++)
4671 {
4672 joined_trail[i] = trail_2[j];
4673 }
4674
4675 return joined_trail;
4676}
4677
4678
4679/**
4680 * Return the trail from source to my current predecessor. Check if source
4681 * is already part of the this trail, if yes then return the shorten trail.
4682 * @param current_trail Trail from source to me, NOT including the endpoints.
4683 * @param current_trail_length Number of peers in @a current_trail.
4684 * @param trail_src_to_curr_pred_length[out] Number of peers in trail from
4685 * source to my predecessor, NOT including
4686 * the endpoints.
4687 * @return Trail from source to my predecessor.
4688 */
4689static struct GNUNET_PeerIdentity *
4690get_trail_src_to_curr_pred (struct GNUNET_PeerIdentity source_peer,
4691 const struct GNUNET_PeerIdentity *trail_src_to_me,
4692 unsigned int trail_src_to_me_len,
4693 unsigned int *trail_src_to_curr_pred_length)
4694{
4695 struct GNUNET_PeerIdentity *trail_me_to_curr_pred;
4696 struct GNUNET_PeerIdentity *trail_src_to_curr_pred;
4697 unsigned int trail_me_to_curr_pred_length;
4698 struct FingerInfo *current_predecessor;
4699 int i;
4700 unsigned int j;
4701 unsigned int len;
4702
4703 current_predecessor = &finger_table[PREDECESSOR_FINGER_ID];
4704
4705 /* Check if trail_src_to_me contains current_predecessor. */
4706 for (i = 0; i < trail_src_to_me_len; i++)
4707 {
4708 if (0 != GNUNET_CRYPTO_cmp_peer_identity(&trail_src_to_me[i],
4709 &current_predecessor->finger_identity))
4710 continue;
4711
4712
4713 *trail_src_to_curr_pred_length = i;
4714
4715 if(0 == i)
4716 return NULL;
4717
4718 trail_src_to_curr_pred = GNUNET_malloc (*trail_src_to_curr_pred_length *
4719 sizeof(struct GNUNET_PeerIdentity));
4720 for (j = 0; j < i; j++)
4721 trail_src_to_curr_pred[j] = trail_src_to_me[j];
4722 return trail_src_to_curr_pred;
4723 }
4724
4725
4726 trail_me_to_curr_pred = get_shortest_trail (current_predecessor,
4727 &trail_me_to_curr_pred_length);
4728
4729 /* Check if trail contains the source_peer. */
4730 for (i = trail_me_to_curr_pred_length - 1; i >= 0; i--)
4731 {
4732 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&source_peer,
4733 &trail_me_to_curr_pred[i]))
4734 continue;
4735
4736 /* Source is NOT part of trail. */
4737 i++;
4738
4739 /* Source is the last element in the trail to reach to my pred.
4740 Source is direct friend of the pred. */
4741 if (trail_me_to_curr_pred_length == i)
4742 {
4743 *trail_src_to_curr_pred_length = 0;
4744 GNUNET_free_non_null (trail_me_to_curr_pred);
4745 return NULL;
4746 }
4747
4748 *trail_src_to_curr_pred_length = trail_me_to_curr_pred_length - i;
4749 trail_src_to_curr_pred = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)*
4750 *trail_src_to_curr_pred_length);
4751
4752 for (j = 0; j < *trail_src_to_curr_pred_length; i++,j++)
4753 trail_src_to_curr_pred[j] = trail_me_to_curr_pred[i];
4754 GNUNET_free_non_null (trail_me_to_curr_pred);
4755 return trail_src_to_curr_pred;
4756 }
4757
4758 trail_src_to_curr_pred = check_for_duplicate_entries (trail_src_to_me,
4759 trail_src_to_me_len,
4760 trail_me_to_curr_pred,
4761 trail_me_to_curr_pred_length,
4762 &len);
4763 *trail_src_to_curr_pred_length = len;
4764 GNUNET_free_non_null(trail_me_to_curr_pred);
4765 return trail_src_to_curr_pred;
4766}
4767
4768
4769/**
4770 * Add finger as your predecessor. To add, first generate a new trail id, invert
4771 * the trail to get the trail from me to finger, add an entry in your routing
4772 * table, send add trail message to peers which are part of trail from me to
4773 * finger and add finger in finger table.
4774 * @param finger
4775 * @param trail
4776 * @param trail_length
4777 */
4778static void
4779update_predecessor (struct GNUNET_PeerIdentity finger,
4780 struct GNUNET_PeerIdentity *trail,
4781 unsigned int trail_length)
4782{
4783 struct GNUNET_HashCode trail_to_new_predecessor_id;
4784 struct GNUNET_PeerIdentity *trail_to_new_predecessor;
4785 struct FriendInfo *target_friend;
4786
4787 /* Generate trail id for trail from me to new predecessor = finger. */
4788 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
4789 &trail_to_new_predecessor_id,
4790 sizeof (trail_to_new_predecessor_id));
4791
4792 if (0 == trail_length)
4793 {
4794 trail_to_new_predecessor = NULL;
4795 GDS_ROUTING_add (trail_to_new_predecessor_id, my_identity, finger);
4796 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, &finger);
4797 if (NULL == target_friend)
4798 {
4799 GNUNET_break (0);
4800 return;
4801 }
4802 }
4803 else
4804 {
4805 /* Invert the trail to get the trail from me to finger, NOT including the
4806 endpoints.*/
4807 GNUNET_assert(NULL != GNUNET_CONTAINER_multipeermap_get(friend_peermap,
4808 &trail[trail_length-1]));
4809 trail_to_new_predecessor = invert_trail (trail, trail_length);
4810
4811 /* Add an entry in your routing table. */
4812 GDS_ROUTING_add (trail_to_new_predecessor_id,
4813 my_identity,
4814 trail_to_new_predecessor[0]);
4815
4816 GNUNET_assert (NULL != (target_friend =
4817 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
4818 &trail_to_new_predecessor[0])));
4819 }
4820
4821 /* Add entry in routing table of all peers that are part of trail from me
4822 to finger, including finger. */
4823 GDS_NEIGHBOURS_send_add_trail (my_identity,
4824 finger,
4825 trail_to_new_predecessor_id,
4826 trail_to_new_predecessor,
4827 trail_length,
4828 target_friend);
4829
4830 add_new_finger (finger, trail_to_new_predecessor, trail_length,
4831 trail_to_new_predecessor_id, PREDECESSOR_FINGER_ID);
4832 GNUNET_free_non_null(trail_to_new_predecessor);
4833}
4834
4835
4836/*
4837 * Check if you already have a predecessor. If not then add finger as your
4838 * predecessor. If you have predecessor, then compare two peer identites.
4839 * If finger is correct predecessor, then remove the old entry, add finger in
4840 * finger table and send add_trail message to add the trail in the routing
4841 * table of all peers which are part of trail to reach from me to finger.
4842 * @param finger New peer which may be our predecessor.
4843 * @param trail List of peers to reach from @finger to me.
4844 * @param trail_length Total number of peer in @a trail.
4845 */
4846static void
4847compare_and_update_predecessor (struct GNUNET_PeerIdentity finger,
4848 struct GNUNET_PeerIdentity *trail,
4849 unsigned int trail_length)
4850{
4851 struct FingerInfo *current_predecessor;
4852 struct GNUNET_PeerIdentity closest_peer;
4853 uint64_t predecessor_value;
4854 unsigned int is_predecessor = 1;
4855
4856 current_predecessor = &finger_table[PREDECESSOR_FINGER_ID];
4857 GNUNET_assert (0 != GNUNET_CRYPTO_cmp_peer_identity (&finger, &my_identity));
4858
4859 /* No predecessor. Add finger as your predecessor. */
4860 if (GNUNET_NO == current_predecessor->is_present)
4861 {
4862 update_predecessor (finger, trail, trail_length);
4863 return;
4864 }
4865
4866 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&current_predecessor->finger_identity,
4867 &finger))
4868 {
4869 return;
4870 }
4871
4872 predecessor_value = compute_finger_identity_value (PREDECESSOR_FINGER_ID);
4873 closest_peer = select_closest_peer (&finger,
4874 &current_predecessor->finger_identity,
4875 predecessor_value, is_predecessor);
4876
4877 /* Finger is the closest predecessor. Remove the existing one and add the new
4878 one. */
4879 if (0 == GNUNET_CRYPTO_cmp_peer_identity(&closest_peer, &finger))
4880 {
4881 remove_existing_finger (current_predecessor, PREDECESSOR_FINGER_ID);
4882 update_predecessor (finger, trail, trail_length);
4883 return;
4884 }
4885 return;
4886}
4887
4888
4889/*
4890 * Core handle for p2p verify successor messages.
4891 * @param cls closure
4892 * @param message message
4893 * @param peer peer identity this notification is about
4894 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
4895 */
4896static int
4897handle_dht_p2p_verify_successor(void *cls,
4898 const struct GNUNET_PeerIdentity *peer,
4899 const struct GNUNET_MessageHeader *message)
4900{
4901 const struct PeerVerifySuccessorMessage *vsm;
4902 struct GNUNET_HashCode trail_id;
4903 struct GNUNET_PeerIdentity successor;
4904 struct GNUNET_PeerIdentity source_peer;
4905 struct GNUNET_PeerIdentity *trail;
4906 struct GNUNET_PeerIdentity *next_hop;
4907 struct FingerInfo current_predecessor;
4908 struct FriendInfo *target_friend;
4909 unsigned int trail_src_to_curr_pred_len = 0;
4910 struct GNUNET_PeerIdentity *trail_src_to_curr_pred;
4911 unsigned int trail_length;
4912 size_t msize;
4913
4914 msize = ntohs (message->size);
4915
4916 if (msize < sizeof (struct PeerVerifySuccessorMessage))
4917 {
4918 GNUNET_break_op (0);
4919 return GNUNET_YES;
4920 }
4921
4922 vsm = (const struct PeerVerifySuccessorMessage *) message;
4923 trail_length = (msize - sizeof (struct PeerVerifySuccessorMessage))/
4924 sizeof (struct GNUNET_PeerIdentity);
4925 if ((msize - sizeof (struct PeerVerifySuccessorMessage)) %
4926 sizeof (struct GNUNET_PeerIdentity) != 0)
4927 {
4928 GNUNET_break_op (0);
4929 return GNUNET_OK;
4930 }
4931
4932 GNUNET_STATISTICS_update (GDS_stats,
4933 gettext_noop
4934 ("# Bytes received from other peers"), msize,
4935 GNUNET_NO);
4936
4937 trail_id = vsm->trail_id;
4938 source_peer = vsm->source_peer;
4939 successor = vsm->successor;
4940 trail = (struct GNUNET_PeerIdentity *)&vsm[1];
4941
4942 /* I am NOT the successor of source_peer. Pass the message to next_hop on
4943 * the trail. */
4944 if(0 != (GNUNET_CRYPTO_cmp_peer_identity (&successor, &my_identity)))
4945 {
4946 next_hop = GDS_ROUTING_get_next_hop (trail_id, GDS_ROUTING_SRC_TO_DEST);
4947 if (NULL == next_hop)
4948 {
4949 return GNUNET_OK;
4950 }
4951
4952 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
4953
4954 if(NULL == target_friend)
4955 {
4956 GNUNET_break_op(0);
4957 return GNUNET_OK;
4958 }
4959 GDS_NEIGHBOURS_send_verify_successor_message (source_peer, successor,
4960 trail_id, trail, trail_length,
4961 target_friend);
4962 return GNUNET_OK;
4963 }
4964
4965 /* I am the destination of this message. */
4966
4967 /* Check if the source_peer could be our predecessor and if yes then update
4968 * it. */
4969 compare_and_update_predecessor (source_peer, trail, trail_length);
4970 current_predecessor = finger_table[PREDECESSOR_FINGER_ID];
4971
4972 /* Is source of this message NOT my predecessor. */
4973 if (0 != (GNUNET_CRYPTO_cmp_peer_identity (&current_predecessor.finger_identity,
4974 &source_peer)))
4975 {
4976 trail_src_to_curr_pred =
4977 get_trail_src_to_curr_pred (source_peer,
4978 trail,
4979 trail_length,
4980 &trail_src_to_curr_pred_len);
4981 }
4982 else
4983 {
4984 trail_src_to_curr_pred_len = trail_length;
4985 unsigned int i;
4986
4987 trail_src_to_curr_pred =
4988 GNUNET_malloc (sizeof(struct GNUNET_PeerIdentity)
4989 *trail_src_to_curr_pred_len);
4990 for(i = 0; i < trail_src_to_curr_pred_len; i++)
4991 {
4992 trail_src_to_curr_pred[i] = trail[i];
4993 }
4994 }
4995
4996 GNUNET_assert (NULL !=
4997 (target_friend =
4998 GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer)));
4999 GDS_NEIGHBOURS_send_verify_successor_result (source_peer, my_identity,
5000 current_predecessor.finger_identity,
5001 trail_id, trail_src_to_curr_pred,
5002 trail_src_to_curr_pred_len,
5003 GDS_ROUTING_DEST_TO_SRC,
5004 target_friend);
5005 GNUNET_free_non_null(trail_src_to_curr_pred);
5006 return GNUNET_OK;
5007}
5008
5009
5010/**
5011 * If the trail from me to my probable successor contains a friend not
5012 * at index 0, then we can shorten the trail.
5013 * @param probable_successor Peer which is our probable successor
5014 * @param trail_me_to_probable_successor Peers in path from me to my probable
5015 * successor, NOT including the endpoints.
5016 * @param trail_me_to_probable_successor_len Total number of peers in
5017 * @a trail_me_to_probable_succesor.
5018 * @return Updated trail, if any friend found.
5019 * Else the trail_me_to_probable_successor.
5020 */
5021struct GNUNET_PeerIdentity *
5022check_trail_me_to_probable_succ (struct GNUNET_PeerIdentity probable_successor,
5023 const struct GNUNET_PeerIdentity *trail_me_to_probable_successor,
5024 unsigned int trail_me_to_probable_successor_len,
5025 unsigned int *trail_to_new_successor_length)
5026{
5027 unsigned int i;
5028 unsigned int j;
5029 struct GNUNET_PeerIdentity *trail_to_new_successor;
5030
5031 /* Probable successor is a friend */
5032 if (NULL != GNUNET_CONTAINER_multipeermap_get (friend_peermap,
5033 &probable_successor))
5034 {
5035 trail_to_new_successor = NULL;
5036 *trail_to_new_successor_length = 0;
5037 return trail_to_new_successor;
5038 }
5039
5040 /* Is there any friend of yours in this trail. */
5041 if(trail_me_to_probable_successor_len > 1)
5042 {
5043 for (i = trail_me_to_probable_successor_len - 1; i > 0; i--)
5044 {
5045 if (NULL == GNUNET_CONTAINER_multipeermap_get (friend_peermap,
5046 &trail_me_to_probable_successor[i]))
5047 continue;
5048
5049 *trail_to_new_successor_length = (trail_me_to_probable_successor_len - i);
5050 trail_to_new_successor = GNUNET_malloc (sizeof(struct GNUNET_PeerIdentity)*
5051 *trail_to_new_successor_length);
5052
5053
5054 for(j = 0; j < *trail_to_new_successor_length; i++,j++)
5055 {
5056 trail_to_new_successor[j] = trail_me_to_probable_successor[i];
5057 }
5058
5059 return trail_to_new_successor;
5060 }
5061 }
5062
5063 *trail_to_new_successor_length = trail_me_to_probable_successor_len;
5064 return (struct GNUNET_PeerIdentity*)trail_me_to_probable_successor;
5065}
5066
5067// TODO: Move up
5068struct SendNotifyContext
5069{
5070 struct GNUNET_PeerIdentity source_peer;
5071 struct GNUNET_PeerIdentity successor;
5072 struct GNUNET_PeerIdentity *successor_trail;
5073 unsigned int successor_trail_length;
5074 struct GNUNET_HashCode succesor_trail_id;
5075 struct FriendInfo *target_friend;
5076 unsigned int num_retries_scheduled;
5077};
5078
5079void
5080send_notify_new_successor (void *cls,
5081 const struct GNUNET_SCHEDULER_TaskContext
5082 * tc);
5083
5084/**
5085 * Check if the peer which sent us verify successor result message is still ours
5086 * successor or not. If not, then compare existing successor and probable successor.
5087 * In case probable successor is the correct successor, remove the existing
5088 * successor. Add probable successor as new successor. Send notify new successor
5089 * message to new successor.
5090 * @param curr_succ Peer to which we sent the verify successor message. It may
5091 * or may not be our real current successor, as we may have few iterations of
5092 * find finger trail task.
5093 * @param probable_successor Peer which should be our successor accroding to @a
5094 * curr_succ
5095 * @param trail List of peers to reach from me to @a probable successor, NOT including
5096 * endpoints.
5097 * @param trail_length Total number of peers in @a trail.
5098 */
5099static void
5100compare_and_update_successor (struct GNUNET_PeerIdentity curr_succ,
5101 struct GNUNET_PeerIdentity probable_successor,
5102 const struct GNUNET_PeerIdentity *trail,
5103 unsigned int trail_length)
5104{
5105 struct FingerInfo *current_successor;
5106 struct GNUNET_PeerIdentity closest_peer;
5107 struct GNUNET_HashCode trail_id;
5108 struct GNUNET_PeerIdentity *trail_me_to_probable_succ;
5109 struct FriendInfo *target_friend;
5110 unsigned int trail_me_to_probable_succ_len;
5111 unsigned int is_predecessor = 0;
5112 uint64_t successor_value;
5113
5114 current_successor = &finger_table[0];
5115 successor_value = compute_finger_identity_value(0);
5116
5117 /* If probable successor is same as current_successor, do nothing. */
5118 if(0 == GNUNET_CRYPTO_cmp_peer_identity (&probable_successor,
5119 &current_successor->finger_identity))
5120 {
5121 if ((NULL != GDS_stats))
5122 {
5123 char *my_id_str;
5124 uint64_t succ;
5125 char *key;
5126 uint64_t my_id;
5127 memcpy (&my_id, &my_identity, sizeof(uint64_t));
5128 my_id_str = GNUNET_strdup (GNUNET_i2s_full (&my_identity));
5129 memcpy(&succ, &current_successor->finger_identity, sizeof(uint64_t));
5130 succ = GNUNET_ntohll(succ);
5131 GNUNET_asprintf (&key, "XDHT:%s:", my_id_str);
5132 GNUNET_free (my_id_str);
5133
5134 GNUNET_STATISTICS_set (GDS_stats, key, succ, 0);
5135 GNUNET_free (key);
5136 }
5137 if (send_verify_successor_task == NULL)
5138 send_verify_successor_task =
5139 GNUNET_SCHEDULER_add_delayed(verify_successor_next_send_time,
5140 &send_verify_successor_message,
5141 NULL);
5142 return;
5143 }
5144 closest_peer = select_closest_peer (&probable_successor,
5145 &current_successor->finger_identity,
5146 successor_value, is_predecessor);
5147
5148 /* If the current_successor in the finger table is closest, then do nothing. */
5149 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&closest_peer ,
5150 &current_successor->finger_identity))
5151 {
5152 //FIXME: Is this a good place to return the stats.
5153 if ((NULL != GDS_stats))
5154 {
5155 char *my_id_str;
5156 uint64_t succ;
5157 char *key;
5158
5159 my_id_str = GNUNET_strdup (GNUNET_i2s_full (&my_identity));
5160 memcpy(&succ, &current_successor->finger_identity, sizeof(uint64_t));
5161 GNUNET_asprintf (&key, "XDHT:%s:", my_id_str);
5162 GNUNET_free (my_id_str);
5163 GNUNET_STATISTICS_set (GDS_stats, key, succ, 0);
5164 GNUNET_free (key);
5165 }
5166
5167 if(0 == successor_times)
5168 {
5169// successor_times = 3;
5170 verify_successor_next_send_time =
5171 GNUNET_TIME_STD_BACKOFF (verify_successor_next_send_time);
5172 }
5173 else
5174 successor_times--;
5175
5176
5177 if (send_verify_successor_task == NULL)
5178 send_verify_successor_task =
5179 GNUNET_SCHEDULER_add_delayed(verify_successor_next_send_time,
5180 &send_verify_successor_message,
5181 NULL);
5182 return;
5183 }
5184
5185 /* Probable successor is the closest peer.*/
5186 if(trail_length > 0)
5187 {
5188 GNUNET_assert(NULL != GNUNET_CONTAINER_multipeermap_get(friend_peermap,
5189 &trail[0]));
5190 }
5191 else
5192 {
5193 GNUNET_assert(NULL != GNUNET_CONTAINER_multipeermap_get(friend_peermap,
5194 &probable_successor));
5195 }
5196
5197 trail_me_to_probable_succ_len = 0;
5198 trail_me_to_probable_succ =
5199 check_trail_me_to_probable_succ (probable_successor,
5200 trail, trail_length,
5201 &trail_me_to_probable_succ_len);
5202
5203 /* Remove the existing successor. */
5204 remove_existing_finger (current_successor, 0);
5205 /* Generate a new trail id to reach to your new successor. */
5206 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
5207 &trail_id, sizeof (trail_id));
5208
5209 if (trail_me_to_probable_succ_len > 0)
5210 {
5211 GDS_ROUTING_add (trail_id, my_identity, trail_me_to_probable_succ[0]);
5212 GNUNET_assert (NULL !=
5213 (target_friend =
5214 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
5215 &trail_me_to_probable_succ[0])));
5216 }
5217 else
5218 {
5219 GDS_ROUTING_add (trail_id, my_identity, probable_successor);
5220 GNUNET_assert (NULL !=
5221 (target_friend =
5222 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
5223 &probable_successor)));
5224 }
5225
5226 add_new_finger (probable_successor, trail_me_to_probable_succ,
5227 trail_me_to_probable_succ_len, trail_id, 0);
5228
5229 struct SendNotifyContext *notify_ctx;
5230
5231 notify_ctx = GNUNET_new(struct SendNotifyContext);
5232
5233 notify_ctx->source_peer = my_identity;
5234 notify_ctx->successor = probable_successor;
5235 notify_ctx->successor_trail =
5236 GNUNET_malloc(sizeof(struct GNUNET_PeerIdentity) * trail_me_to_probable_succ_len);
5237 memcpy(notify_ctx->successor_trail, trail_me_to_probable_succ,
5238 sizeof(struct GNUNET_PeerIdentity) * trail_me_to_probable_succ_len);
5239 notify_ctx->successor_trail_length = trail_me_to_probable_succ_len;
5240 notify_ctx->succesor_trail_id = trail_id;
5241 notify_ctx->target_friend = target_friend;
5242 notify_ctx->num_retries_scheduled = 0;
5243 GNUNET_free_non_null (trail_me_to_probable_succ);
5244
5245 // TODO: Check if we should verify before schedule if already scheduled.
5246 GNUNET_SCHEDULER_add_now(&send_notify_new_successor, (void*)notify_ctx);
5247}
5248
5249
5250
5251void
5252send_notify_new_successor (void *cls,
5253 const struct GNUNET_SCHEDULER_TaskContext
5254 * tc)
5255{
5256 struct SendNotifyContext *ctx = (struct SendNotifyContext *) cls;
5257
5258 GDS_NEIGHBOURS_send_notify_new_successor (ctx->source_peer,
5259 ctx->successor,
5260 ctx->successor_trail,
5261 ctx->successor_trail_length,
5262 ctx->succesor_trail_id,
5263 ctx->target_friend);
5264
5265 if (0 == ctx->num_retries_scheduled &&
5266 send_notify_new_successor_retry_task != NULL)
5267 {
5268 // Result from previous notify successos hasn't arrived, so the retry task
5269 // hasn't been cancelled! Already a new notify successor must be called.
5270 // We will cancel the retry request.
5271 struct SendNotifyContext *old_notify_ctx;
5272 old_notify_ctx = GNUNET_SCHEDULER_cancel(send_notify_new_successor_retry_task);
5273 GNUNET_free (old_notify_ctx->successor_trail);
5274 GNUNET_free (old_notify_ctx);
5275 send_notify_new_successor_retry_task = NULL;
5276 }
5277
5278 ctx->num_retries_scheduled++;
5279 send_notify_new_successor_retry_task = GNUNET_SCHEDULER_add_delayed(notify_successor_retry_time,
5280 &send_notify_new_successor,
5281 cls);
5282}
5283
5284/*
5285 * Core handle for p2p verify successor result messages.
5286 * @param cls closure
5287 * @param message message
5288 * @param peer peer identity this notification is about
5289 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
5290 */
5291static int
5292handle_dht_p2p_verify_successor_result(void *cls,
5293 const struct GNUNET_PeerIdentity *peer,
5294 const struct GNUNET_MessageHeader *message)
5295{
5296 const struct PeerVerifySuccessorResultMessage *vsrm;
5297 enum GDS_ROUTING_trail_direction trail_direction;
5298 struct GNUNET_PeerIdentity querying_peer;
5299 struct GNUNET_HashCode trail_id;
5300 struct GNUNET_PeerIdentity *next_hop;
5301 struct FriendInfo *target_friend;
5302 struct GNUNET_PeerIdentity probable_successor;
5303 struct GNUNET_PeerIdentity current_successor;
5304 const struct GNUNET_PeerIdentity *trail;
5305 unsigned int trail_length;
5306 size_t msize;
5307
5308 msize = ntohs (message->size);
5309 if (msize < sizeof (struct PeerVerifySuccessorResultMessage))
5310 {
5311 GNUNET_break_op (0);
5312 return GNUNET_YES;
5313 }
5314
5315 vsrm = (const struct PeerVerifySuccessorResultMessage *) message;
5316 if ((msize - sizeof (struct PeerVerifySuccessorResultMessage)) %
5317 sizeof (struct GNUNET_PeerIdentity) != 0)
5318 {
5319 GNUNET_break_op (0);
5320 return GNUNET_OK;
5321 }
5322 trail_length = (msize - sizeof (struct PeerVerifySuccessorResultMessage))/
5323 sizeof (struct GNUNET_PeerIdentity);
5324
5325 GNUNET_STATISTICS_update (GDS_stats,
5326 gettext_noop
5327 ("# Bytes received from other peers"), msize,
5328 GNUNET_NO);
5329
5330 trail = (const struct GNUNET_PeerIdentity *) &vsrm[1];
5331 querying_peer = vsrm->querying_peer;
5332 trail_direction = ntohl (vsrm->trail_direction);
5333 trail_id = vsrm->trail_id;
5334 probable_successor = vsrm->probable_successor;
5335 current_successor = vsrm->current_successor;
5336
5337 /* I am the querying_peer. */
5338 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&querying_peer, &my_identity)))
5339 {
5340 /* Cancel Retry Task */
5341 if (NULL != send_verify_successor_retry_task)
5342 {
5343 struct VerifySuccessorContext *ctx;
5344 ctx = GNUNET_SCHEDULER_cancel(send_verify_successor_retry_task);
5345 GNUNET_free(ctx);
5346 send_verify_successor_retry_task = NULL;
5347 }
5348 compare_and_update_successor (current_successor,
5349 probable_successor, trail, trail_length);
5350 return GNUNET_OK;
5351 }
5352
5353 /*If you are not the querying peer then pass on the message */
5354 if(NULL == (next_hop =
5355 GDS_ROUTING_get_next_hop (trail_id, trail_direction)))
5356 {
5357 /* Here it may happen that source peer has found a new successor, and removed
5358 the trail, Hence no entry found in the routing table. Fail silently.*/
5359 DEBUG(" NO ENTRY FOUND IN %s ROUTING TABLE for trail id %s, line",
5360 GNUNET_i2s(&my_identity), GNUNET_h2s(&trail_id), __LINE__);
5361 GNUNET_break_op(0);
5362 return GNUNET_OK;
5363 }
5364 if (NULL == (target_friend =
5365 GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop)))
5366 {
5367 GNUNET_break_op(0);
5368 return GNUNET_OK;
5369 }
5370 GDS_NEIGHBOURS_send_verify_successor_result (querying_peer,
5371 vsrm->current_successor,
5372 probable_successor, trail_id,
5373 trail,
5374 trail_length,
5375 trail_direction, target_friend);
5376 return GNUNET_OK;
5377}
5378
5379
5380/*
5381 * Core handle for p2p notify new successor messages.
5382 * @param cls closure
5383 * @param message message
5384 * @param peer peer identity this notification is about
5385 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
5386 */
5387static int
5388handle_dht_p2p_notify_new_successor(void *cls,
5389 const struct GNUNET_PeerIdentity *peer,
5390 const struct GNUNET_MessageHeader *message)
5391{
5392 const struct PeerNotifyNewSuccessorMessage *nsm;
5393 struct GNUNET_PeerIdentity *trail;
5394 struct GNUNET_PeerIdentity source;
5395 struct GNUNET_PeerIdentity new_successor;
5396 struct GNUNET_HashCode trail_id;
5397 struct GNUNET_PeerIdentity next_hop;
5398 struct FriendInfo *target_friend;
5399 int my_index;
5400 size_t msize;
5401 uint32_t trail_length;
5402
5403 msize = ntohs (message->size);
5404 if (msize < sizeof (struct PeerNotifyNewSuccessorMessage))
5405 {
5406 GNUNET_break_op (0);
5407 return GNUNET_YES;
5408 }
5409 nsm = (const struct PeerNotifyNewSuccessorMessage *) message;
5410 if ((msize - sizeof (struct PeerNotifyNewSuccessorMessage)) %
5411 sizeof (struct GNUNET_PeerIdentity) != 0)
5412 {
5413 GNUNET_break_op (0);
5414 return GNUNET_OK;
5415 }
5416 trail_length = (msize - sizeof (struct PeerNotifyNewSuccessorMessage))/
5417 sizeof (struct GNUNET_PeerIdentity);
5418 GNUNET_STATISTICS_update (GDS_stats,
5419 gettext_noop
5420 ("# Bytes received from other peers"), msize,
5421 GNUNET_NO);
5422
5423 trail = (struct GNUNET_PeerIdentity *) &nsm[1];
5424 source = nsm->source_peer;
5425 new_successor = nsm->new_successor;
5426 trail_id = nsm->trail_id;
5427
5428 /* I am the new_successor to source_peer. */
5429 if ( 0 == GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &new_successor))
5430 {
5431 if(trail_length > 0)
5432 GNUNET_assert(0 == GNUNET_CRYPTO_cmp_peer_identity(&trail[trail_length - 1],
5433 peer));
5434 else
5435 GNUNET_assert(0 == GNUNET_CRYPTO_cmp_peer_identity(&source, peer));
5436
5437 compare_and_update_predecessor (source, trail, trail_length);
5438 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer);
5439 GNUNET_assert (NULL != target_friend);
5440 GDS_NEIGHBOURS_send_notify_succcessor_confirmation (trail_id,
5441 GDS_ROUTING_DEST_TO_SRC,
5442 target_friend);
5443 return GNUNET_OK;
5444 }
5445
5446 GNUNET_assert(trail_length > 0);
5447 /* I am part of trail to reach to successor. */
5448 my_index = search_my_index (trail, trail_length);
5449 if (-1 == my_index)
5450 {
5451 DEBUG ("No entry found in trail\n");
5452 GNUNET_break_op (0);
5453 return GNUNET_SYSERR;
5454 }
5455 if((trail_length + 1) == my_index)
5456 {
5457 DEBUG ("Found twice in trail.\n");
5458 GNUNET_break_op (0);
5459 return GNUNET_SYSERR;
5460 }
5461 if ((trail_length-1) == my_index)
5462 next_hop = new_successor;
5463 else
5464 next_hop = trail[my_index + 1];
5465
5466 GDS_ROUTING_add(trail_id, *peer, next_hop);
5467 target_friend =
5468 GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop);
5469 if (NULL == target_friend)
5470 {
5471 GNUNET_break(0);
5472 return GNUNET_OK;
5473 }
5474 GDS_NEIGHBOURS_send_notify_new_successor (source, new_successor, trail,
5475 trail_length,
5476 trail_id, target_friend);
5477 return GNUNET_OK;
5478
5479}
5480
5481
5482/**
5483 * Core handler for P2P notify successor message
5484 * @param cls closure
5485 * @param message message
5486 * @param peer peer identity this notification is about
5487 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
5488 */
5489static int
5490handle_dht_p2p_notify_succ_confirmation (void *cls,
5491 const struct GNUNET_PeerIdentity *peer,
5492 const struct GNUNET_MessageHeader *message)
5493{
5494 const struct PeerNotifyConfirmationMessage *notify_confirmation;
5495 enum GDS_ROUTING_trail_direction trail_direction;
5496 struct GNUNET_HashCode trail_id;
5497 struct FriendInfo *target_friend;
5498 struct GNUNET_PeerIdentity *next_hop;
5499 size_t msize;
5500
5501 msize = ntohs (message->size);
5502
5503 if (msize != sizeof (struct PeerNotifyConfirmationMessage))
5504 {
5505 GNUNET_break_op (0);
5506 return GNUNET_OK;
5507 }
5508 GNUNET_STATISTICS_update (GDS_stats,
5509 gettext_noop
5510 ("# Bytes received from other peers"), msize,
5511 GNUNET_NO);
5512
5513 notify_confirmation = (const struct PeerNotifyConfirmationMessage *) message;
5514 trail_direction = ntohl (notify_confirmation->trail_direction);
5515 trail_id = notify_confirmation->trail_id;
5516
5517 next_hop = GDS_ROUTING_get_next_hop (trail_id, trail_direction);
5518 if (NULL == next_hop)
5519 {
5520 /* The source of notify new successor, might have found even a better
5521 successor. In that case it send a trail teardown message, and hence,
5522 the next hop is NULL. */
5523 //Fixme: Add some print to confirm the above theory.
5524 return GNUNET_OK;
5525 }
5526
5527 /* I peer which sent the notify successor message to the successor. */
5528 if (0 == GNUNET_CRYPTO_cmp_peer_identity (next_hop, &my_identity))
5529 {
5530 /*
5531 * Schedule another round of verify sucessor with your current successor
5532 * which may or may not be source of this message. This message is used
5533 * only to ensure that we have a path setup to reach to our successor.
5534 */
5535
5536 // TODO: cancel schedule of notify_successor_retry_task
5537 if (send_notify_new_successor_retry_task != NULL)
5538 {
5539 struct SendNotifyContext *notify_ctx;
5540 notify_ctx = GNUNET_SCHEDULER_cancel(send_notify_new_successor_retry_task);
5541 GNUNET_free (notify_ctx->successor_trail);
5542 GNUNET_free (notify_ctx);
5543 send_notify_new_successor_retry_task = NULL;
5544 }
5545 if (send_verify_successor_task == NULL)
5546 {
5547 verify_successor_next_send_time.rel_value_us =
5548 DHT_SEND_VERIFY_SUCCESSOR_INTERVAL.rel_value_us +
5549 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
5550 DHT_SEND_VERIFY_SUCCESSOR_INTERVAL.rel_value_us);
5551 send_verify_successor_task =
5552 GNUNET_SCHEDULER_add_delayed(verify_successor_next_send_time,
5553 &send_verify_successor_message,
5554 NULL);
5555 }
5556 }
5557 else
5558 {
5559 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop);
5560 if (NULL == target_friend)
5561 {
5562 DEBUG ("\n friend not found, line number = %d",__LINE__);
5563 return GNUNET_SYSERR;
5564 }
5565 GDS_NEIGHBOURS_send_notify_succcessor_confirmation (trail_id,
5566 GDS_ROUTING_DEST_TO_SRC,
5567 target_friend);
5568 }
5569 return GNUNET_OK;
5570}
5571
5572
5573/**
5574 * Core handler for P2P trail rejection message
5575 * @param cls closure
5576 * @param message message
5577 * @param peer peer identity this notification is about
5578 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
5579 */
5580static int
5581handle_dht_p2p_trail_setup_rejection (void *cls,
5582 const struct GNUNET_PeerIdentity *peer,
5583 const struct GNUNET_MessageHeader *message)
5584{
5585 const struct PeerTrailRejectionMessage *trail_rejection;
5586 unsigned int trail_length;
5587 const struct GNUNET_PeerIdentity *trail_peer_list;
5588 struct FriendInfo *target_friend;
5589 struct GNUNET_TIME_Relative congestion_timeout;
5590 struct GNUNET_HashCode trail_id;
5591 struct GNUNET_PeerIdentity next_peer;
5592 struct GNUNET_PeerIdentity source;
5593 uint64_t ultimate_destination_finger_value;
5594 unsigned int is_predecessor;
5595 size_t msize;
5596
5597 msize = ntohs (message->size);
5598 if (msize < sizeof (struct PeerTrailRejectionMessage))
5599 {
5600 GNUNET_break_op (0);
5601 return GNUNET_YES;
5602 }
5603 trail_rejection = (const struct PeerTrailRejectionMessage *) message;
5604 if ((msize - sizeof (struct PeerTrailRejectionMessage)) %
5605 sizeof (struct GNUNET_PeerIdentity) != 0)
5606 {
5607 GNUNET_break_op (0);
5608 return GNUNET_OK;
5609 }
5610 trail_length = (msize - sizeof (struct PeerTrailRejectionMessage))/
5611 sizeof (struct GNUNET_PeerIdentity);
5612 GNUNET_STATISTICS_update (GDS_stats,
5613 gettext_noop
5614 ("# Bytes received from other peers"), msize,
5615 GNUNET_NO);
5616
5617 trail_peer_list = (const struct GNUNET_PeerIdentity *)&trail_rejection[1];
5618 is_predecessor = ntohl (trail_rejection->is_predecessor);
5619 congestion_timeout = trail_rejection->congestion_time;
5620 source = trail_rejection->source_peer;
5621 trail_id = trail_rejection->trail_id;
5622 ultimate_destination_finger_value =
5623 GNUNET_ntohll (trail_rejection->ultimate_destination_finger_value);
5624 /* First set the congestion time of the friend that sent you this message. */
5625 target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer);
5626 if (NULL == target_friend)
5627 {
5628 DEBUG ("\nLINE = %d ,No friend found.",__LINE__);
5629 GNUNET_break(0);
5630 return GNUNET_OK;
5631 }
5632 target_friend->congestion_timestamp =
5633 GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(),
5634 congestion_timeout);
5635
5636 /* I am the source peer which wants to setup the trail. Do nothing.
5637 * send_find_finger_trail_task is scheduled periodically.*/
5638 if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &source)))
5639 return GNUNET_OK;
5640
5641 /* If I am congested then pass this message to peer before me in trail. */
5642 if(GNUNET_YES == GDS_ROUTING_threshold_reached())
5643 {
5644 /* First remove yourself from the trail. */
5645 unsigned int new_trail_length = trail_length - 1;
5646 struct GNUNET_PeerIdentity trail[new_trail_length];
5647
5648 memcpy (trail, trail_peer_list, new_trail_length * sizeof(struct GNUNET_PeerIdentity));
5649 if (0 == trail_length)
5650 next_peer = source;
5651 else
5652 next_peer = trail[new_trail_length-1];
5653
5654 target_friend =
5655 GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_peer);
5656 if (NULL == target_friend)
5657 {
5658 DEBUG ("\nLINE = %d ,No friend found.",__LINE__);
5659 GNUNET_break(0);
5660 return GNUNET_OK;
5661 }
5662 GDS_NEIGHBOURS_send_trail_rejection (source,
5663 ultimate_destination_finger_value,
5664 my_identity, is_predecessor,
5665 trail, new_trail_length, trail_id,
5666 target_friend, CONGESTION_TIMEOUT);
5667 return GNUNET_OK;
5668 }
5669
5670 struct Closest_Peer successor;
5671 successor = find_local_best_known_next_hop (ultimate_destination_finger_value, is_predecessor);
5672
5673 /* Am I the final destination? */
5674 if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&successor.best_known_destination,
5675 &my_identity)))
5676 {
5677 /*Here you are already part of trail. Copy the trail removing yourself. */
5678 unsigned int new_trail_length = trail_length - 1;
5679 struct GNUNET_PeerIdentity trail[new_trail_length];
5680
5681 memcpy (trail, trail_peer_list, new_trail_length * sizeof(struct GNUNET_PeerIdentity));
5682
5683 if (0 == new_trail_length)
5684 next_peer = source;
5685 else
5686 {
5687 next_peer = trail[new_trail_length-1];
5688 }
5689 target_friend =
5690 GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_peer);
5691
5692 if (NULL == target_friend)
5693 {
5694 DEBUG ("\nLINE = %d ,No friend found.",__LINE__);
5695 GNUNET_break(0);
5696 return GNUNET_OK;
5697 }
5698 GDS_NEIGHBOURS_send_trail_setup_result (source,
5699 my_identity,
5700 target_friend, new_trail_length,
5701 trail,
5702 is_predecessor,
5703 ultimate_destination_finger_value,
5704 trail_id);
5705 }
5706 else
5707 {
5708 /* Here I was already part of trail. So no need to add. */
5709 target_friend =
5710 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
5711 &successor.next_hop);
5712 if (NULL == target_friend)
5713 {
5714 DEBUG ("\nLINE = %d ,No friend found.",__LINE__);
5715 GNUNET_break(0);
5716 return GNUNET_OK;
5717 }
5718
5719 GDS_NEIGHBOURS_send_trail_setup (source,
5720 ultimate_destination_finger_value,
5721 successor.best_known_destination,
5722 target_friend, trail_length, trail_peer_list,
5723 is_predecessor, trail_id,
5724 successor.trail_id);
5725 }
5726 return GNUNET_OK;
5727}
5728
5729
5730/**
5731 * Core handler for trail teardown message.
5732 * @param cls closure
5733 * @param message message
5734 * @param peer sender of this messsage.
5735 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
5736 */
5737static int
5738handle_dht_p2p_trail_teardown (void *cls, const struct GNUNET_PeerIdentity *peer,
5739 const struct GNUNET_MessageHeader *message)
5740{
5741 const struct PeerTrailTearDownMessage *trail_teardown;
5742 enum GDS_ROUTING_trail_direction trail_direction;
5743 struct GNUNET_HashCode trail_id;
5744 struct GNUNET_PeerIdentity *next_hop;
5745 size_t msize;
5746
5747 msize = ntohs (message->size);
5748
5749 /* Here we pass only the trail id. */
5750 if (msize != sizeof (struct PeerTrailTearDownMessage))
5751 {
5752 GNUNET_break_op (0);
5753 return GNUNET_OK;
5754 }
5755
5756 GNUNET_STATISTICS_update (GDS_stats,
5757 gettext_noop
5758 ("# Bytes received from other peers"), msize,
5759 GNUNET_NO);
5760
5761 trail_teardown = (const struct PeerTrailTearDownMessage *) message;
5762 trail_direction = ntohl (trail_teardown->trail_direction);
5763 trail_id = trail_teardown->trail_id;
5764
5765 /* Check if peer is the real peer from which we should get this message.*/
5766 /* Get the prev_hop for this trail by getting the next hop in opposite direction. */
5767#if 0
5768 GNUNET_assert (NULL != (prev_hop =
5769 GDS_ROUTING_get_next_hop (trail_id, !trail_direction)));
5770 if (0 != GNUNET_CRYPTO_cmp_peer_identity (prev_hop, peer))
5771 {
5772 GNUNET_break (0);
5773 return GNUNET_SYSERR;
5774 }
5775#endif
5776
5777 next_hop = GDS_ROUTING_get_next_hop (trail_id, trail_direction);
5778 if (NULL == next_hop)
5779 {
5780 DEBUG(" NO ENTRY FOUND IN %s ROUTING TABLE for trail id %s, line",
5781 GNUNET_i2s(&my_identity), GNUNET_h2s(&trail_id), __LINE__);
5782 GNUNET_break (0);
5783 return GNUNET_SYSERR;
5784 }
5785
5786 /* I am the next hop, which means I am the final destination. */
5787 if (0 == GNUNET_CRYPTO_cmp_peer_identity (next_hop, &my_identity))
5788 {
5789 GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (trail_id));
5790 return GNUNET_OK;
5791 }
5792 else
5793 {
5794 /* If not final destination, then send a trail teardown message to next hop.*/
5795 GNUNET_assert (NULL != GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop));
5796 GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (trail_id));
5797 GDS_NEIGHBOURS_send_trail_teardown (&trail_id, trail_direction, next_hop);
5798 }
5799
5800 return GNUNET_OK;
5801}
5802
5803
5804/**
5805 * Core handle for p2p add trail message.
5806 * @param cls closure
5807 * @param message message
5808 * @param peer peer identity this notification is about
5809 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
5810 */
5811static int
5812handle_dht_p2p_add_trail (void *cls, const struct GNUNET_PeerIdentity *peer,
5813 const struct GNUNET_MessageHeader *message)
5814{
5815 const struct PeerAddTrailMessage *add_trail;
5816 const struct GNUNET_PeerIdentity *trail;
5817 struct GNUNET_HashCode trail_id;
5818 struct GNUNET_PeerIdentity destination_peer;
5819 struct GNUNET_PeerIdentity source_peer;
5820 struct GNUNET_PeerIdentity next_hop;
5821 unsigned int trail_length;
5822 unsigned int my_index;
5823 size_t msize;
5824
5825 msize = ntohs (message->size);
5826 /* In this message we pass the whole trail from source to destination as we
5827 * are adding that trail.*/
5828 //FIXME: failed when run with 1000 pears. check why.
5829 if (msize < sizeof (struct PeerAddTrailMessage))
5830 {
5831 GNUNET_break_op (0);
5832 return GNUNET_OK;
5833 }
5834
5835 add_trail = (const struct PeerAddTrailMessage *) message;
5836 trail_length = (msize - sizeof (struct PeerAddTrailMessage))/
5837 sizeof (struct GNUNET_PeerIdentity);
5838 if ((msize - sizeof (struct PeerAddTrailMessage)) %
5839 sizeof (struct GNUNET_PeerIdentity) != 0)
5840 {
5841 GNUNET_break_op (0);
5842 return GNUNET_OK;
5843 }
5844
5845 GNUNET_STATISTICS_update (GDS_stats,
5846 gettext_noop
5847 ("# Bytes received from other peers"), msize,
5848 GNUNET_NO);
5849
5850 trail = (const struct GNUNET_PeerIdentity *)&add_trail[1];
5851 destination_peer = add_trail->destination_peer;
5852 source_peer = add_trail->source_peer;
5853 trail_id = add_trail->trail_id;
5854
5855 /* I am not the destination of the trail. */
5856 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &destination_peer))
5857 {
5858 struct FriendInfo *target_friend;
5859
5860 /* Get my location in the trail. */
5861 my_index = search_my_index (trail, trail_length);
5862 if (-1 == my_index)
5863 {
5864 GNUNET_break_op (0);
5865 return GNUNET_SYSERR;
5866 }
5867 if((trail_length + 1) == my_index)
5868 {
5869 DEBUG ("Found twice in trail.\n");
5870 GNUNET_break_op (0);
5871 return GNUNET_SYSERR;
5872 }
5873 if ((trail_length - 1) == my_index)
5874 {
5875 next_hop = destination_peer;
5876 }
5877 else
5878 {
5879 next_hop = trail[my_index + 1];
5880 }
5881 /* Add in your routing table. */
5882 GNUNET_assert (GNUNET_OK == GDS_ROUTING_add (trail_id, *peer, next_hop));
5883 //GNUNET_assert (GNUNET_OK == GDS_ROUTING_add (trail_id, next_hop, *peer));
5884 GNUNET_assert (NULL !=
5885 (target_friend =
5886 GNUNET_CONTAINER_multipeermap_get (friend_peermap, &next_hop)));
5887 GDS_NEIGHBOURS_send_add_trail (source_peer, destination_peer, trail_id,
5888 trail, trail_length, target_friend);
5889 return GNUNET_OK;
5890 }
5891 /* I am the destination. Add an entry in routing table. */
5892 GNUNET_assert (GNUNET_OK == GDS_ROUTING_add (trail_id, *peer, my_identity));
5893 return GNUNET_OK;
5894}
5895
5896
5897/**
5898 * Free the finger trail in which the first friend to reach to a finger is
5899 * disconnected_friend. Also remove entry from routing table for that particular
5900 * trail id.
5901 * @param disconnected_friend PeerIdentity of friend which got disconnected
5902 * @param remove_finger Finger whose trail we need to check if it has
5903 * disconnected_friend as the first hop.
5904 * @return Total number of trails in which disconnected_friend was the first
5905 * hop.
5906 */
5907static int
5908remove_matching_trails (const struct GNUNET_PeerIdentity *disconnected_friend,
5909 struct FingerInfo *finger)
5910{
5911 struct GNUNET_PeerIdentity *next_hop;
5912 struct FriendInfo *remove_friend;
5913 struct Trail *current_trail;
5914 unsigned int matching_trails_count = 0;
5915 int i;
5916
5917 /* Iterate over all the trails of finger. */
5918 for (i = 0; i < finger->trails_count; i++)
5919 {
5920 current_trail = &finger->trail_list[i];
5921 if (GNUNET_NO == current_trail->is_present)
5922 continue;
5923
5924 /* First friend to reach to finger is disconnected_peer. */
5925 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&current_trail->trail_head->peer,
5926 disconnected_friend))
5927 {
5928 remove_friend =
5929 GNUNET_CONTAINER_multipeermap_get (friend_peermap,
5930 disconnected_friend);
5931 GNUNET_assert (NULL != remove_friend);
5932 next_hop = GDS_ROUTING_get_next_hop (current_trail->trail_id,
5933 GDS_ROUTING_SRC_TO_DEST);
5934
5935 /* Here it may happen that as all the peers got disconnected, the entry in
5936 routing table for that particular trail has been removed, because the
5937 previously disconnected peer was either a next hop or prev hop of that
5938 peer. */
5939 if (NULL != next_hop)
5940 {
5941 GNUNET_assert (0 == (GNUNET_CRYPTO_cmp_peer_identity (disconnected_friend,
5942 next_hop)));
5943 GNUNET_assert (GNUNET_YES == GDS_ROUTING_remove_trail (current_trail->trail_id));
5944 }
5945 matching_trails_count++;
5946 free_trail (current_trail);
5947 current_trail->is_present = GNUNET_NO;
5948 }
5949 }
5950 return matching_trails_count;
5951}
5952
5953
5954/**
5955 * Iterate over finger_table entries.
5956 * 0. Ignore finger which is my_identity or if no valid entry present at
5957 * that finger index.
5958 * 1. If disconnected_friend is a finger, then remove the routing entry from
5959 your own table. Free the trail.
5960 * 2. Check if disconnected_friend is the first friend in the trail to reach to a finger.
5961 * 2.1 Remove all the trails and entry from routing table in which disconnected
5962 * friend is the first friend in the trail. If disconnected_friend is the
5963 * first friend in all the trails to reach finger, then remove the finger.
5964 * @param disconnected_friend Peer identity of friend which got disconnected.
5965 */
5966static void
5967remove_matching_fingers (const struct GNUNET_PeerIdentity *disconnected_peer)
5968{
5969 struct FingerInfo *current_finger;
5970 int removed_trails_count;
5971 int i;
5972
5973 /* Iterate over finger table entries. */
5974 for (i = 0; i < MAX_FINGERS; i++)
5975 {
5976 current_finger = &finger_table[i];
5977
5978 /* No finger stored at this trail index or I am the finger. */
5979 if ((GNUNET_NO == current_finger->is_present) ||
5980 (0 == GNUNET_CRYPTO_cmp_peer_identity (&current_finger->finger_identity,
5981 &my_identity)))
5982 continue;
5983
5984 /* Is disconnected_peer a finger? */
5985 if (0 == GNUNET_CRYPTO_cmp_peer_identity (disconnected_peer,
5986 &current_finger->finger_identity))
5987 {
5988 remove_existing_finger (current_finger, i);
5989 }
5990
5991 /* If finger is a friend but not disconnected_friend, then continue. */
5992 if (NULL != GNUNET_CONTAINER_multipeermap_get (friend_peermap,
5993 &current_finger->finger_identity))
5994 continue;
5995
5996 /* Iterate over the list of trails to reach remove_finger. Check if
5997 * disconnected_friend is the first friend in any of the trail. */
5998 removed_trails_count = remove_matching_trails (disconnected_peer,
5999 current_finger);
6000 current_finger->trails_count =
6001 current_finger->trails_count - removed_trails_count;
6002 if (0 == current_finger->trails_count)
6003 {
6004 current_finger->is_present = GNUNET_NO;
6005 memset ((void *)&finger_table[i], 0, sizeof (finger_table[i]));
6006 }
6007 }
6008}
6009
6010
6011/**
6012 * Method called whenever a peer disconnects.
6013 *
6014 * @param cls closure
6015 * @param peer peer identity this notification is about
6016 */
6017static void
6018handle_core_disconnect (void *cls,
6019 const struct GNUNET_PeerIdentity *peer)
6020{
6021 struct FriendInfo *remove_friend;
6022 struct P2PPendingMessage *pos;
6023 unsigned int discarded;
6024
6025 /* If disconnected to own identity, then return. */
6026 if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
6027 return;
6028
6029 if(NULL == (remove_friend =
6030 GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer)))
6031 {
6032 DEBUG("\n friend already disconnected.");
6033 return;
6034 }
6035
6036 remove_matching_fingers (peer);
6037 GNUNET_assert (GNUNET_SYSERR != GDS_ROUTING_remove_trail_by_peer (peer));
6038 GNUNET_assert (GNUNET_YES ==
6039 GNUNET_CONTAINER_multipeermap_remove (friend_peermap,
6040 peer,
6041 remove_friend));
6042
6043 /* Remove all the messages queued in pending list of this peer is discarded.*/
6044 if (remove_friend->th != NULL)
6045 {
6046 GNUNET_CORE_notify_transmit_ready_cancel(remove_friend->th);
6047 remove_friend->th = NULL;
6048 }
6049
6050 discarded = 0;
6051 while (NULL != (pos = remove_friend->head))
6052 {
6053 GNUNET_CONTAINER_DLL_remove (remove_friend->head, remove_friend->tail, pos);
6054 discarded++;
6055 GNUNET_free (pos);
6056 }
6057
6058 GNUNET_STATISTICS_update (GDS_stats,
6059 gettext_noop
6060 ("# Queued messages discarded (peer disconnected)"),
6061 discarded, GNUNET_NO);
6062 //GNUNET_free (remove_friend);
6063
6064 if (0 != GNUNET_CONTAINER_multipeermap_size (friend_peermap))
6065 return;
6066
6067 if (NULL != find_finger_trail_task)
6068 {
6069 GNUNET_SCHEDULER_cancel (find_finger_trail_task);
6070 find_finger_trail_task = NULL;
6071 }
6072 else
6073 GNUNET_break (0);
6074}
6075
6076
6077/**
6078 * Method called whenever a peer connects.
6079 *
6080 * @param cls closure
6081 * @param peer_identity peer identity this notification is about
6082 */
6083static void
6084handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer_identity)
6085{
6086 struct FriendInfo *friend;
6087
6088 /* Check for connect to self message */
6089 if (0 == memcmp (&my_identity, peer_identity, sizeof (struct GNUNET_PeerIdentity)))
6090 return;
6091
6092 /* If peer already exists in our friend_peermap, then exit. */
6093 if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (friend_peermap,
6094 peer_identity))
6095 {
6096 GNUNET_break (0);
6097 return;
6098 }
6099
6100 friend = GNUNET_new (struct FriendInfo);
6101 friend->id = *peer_identity;
6102
6103 GNUNET_assert (GNUNET_OK ==
6104 GNUNET_CONTAINER_multipeermap_put (friend_peermap,
6105 peer_identity, friend,
6106 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
6107
6108 /* FIXME: now we are not making a distinction between fingers which are friends
6109 * also.But later, we should add a congestion timestamp on the friend, so that it is
6110 * selected after some time out. This is to ensure that both peers have added
6111 * each other as their friend. */
6112 /* Got a first connection, good time to start with FIND FINGER TRAIL requests...*/
6113 if (NULL == find_finger_trail_task)
6114 {
6115 find_finger_trail_task = GNUNET_SCHEDULER_add_now (&send_find_finger_trail_message, NULL);
6116 }
6117}
6118
6119
6120/**
6121 * To be called on core init/fail.
6122 *
6123 * @param cls service closure
6124 * @param identity the public identity of this peer
6125 */
6126static void
6127core_init (void *cls,
6128 const struct GNUNET_PeerIdentity *identity)
6129{
6130 my_identity = *identity;
6131}
6132
6133
6134/**
6135 * Initialize finger table entries.
6136 */
6137static void
6138finger_table_init ()
6139{
6140 memset (&finger_table, 0, sizeof (finger_table));
6141}
6142
6143
6144/**
6145 * Initialize neighbours subsystem.
6146 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
6147 */
6148int
6149GDS_NEIGHBOURS_init (void)
6150{
6151 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
6152 {&handle_dht_p2p_put, GNUNET_MESSAGE_TYPE_XDHT_P2P_PUT, 0},
6153 {&handle_dht_p2p_get, GNUNET_MESSAGE_TYPE_XDHT_P2P_GET, 0},
6154 {&handle_dht_p2p_get_result, GNUNET_MESSAGE_TYPE_XDHT_P2P_GET_RESULT, 0},
6155 {&handle_dht_p2p_trail_setup, GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP, 0},
6156 {&handle_dht_p2p_trail_setup_result, GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP_RESULT, 0},
6157 {&handle_dht_p2p_verify_successor, GNUNET_MESSAGE_TYPE_XDHT_P2P_VERIFY_SUCCESSOR, 0},
6158 {&handle_dht_p2p_verify_successor_result, GNUNET_MESSAGE_TYPE_XDHT_P2P_VERIFY_SUCCESSOR_RESULT, 0},
6159 {&handle_dht_p2p_notify_new_successor, GNUNET_MESSAGE_TYPE_XDHT_P2P_NOTIFY_NEW_SUCCESSOR, 0},
6160 {&handle_dht_p2p_trail_setup_rejection, GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_SETUP_REJECTION, 0},
6161 {&handle_dht_p2p_trail_teardown, GNUNET_MESSAGE_TYPE_XDHT_P2P_TRAIL_TEARDOWN,
6162 sizeof (struct PeerTrailTearDownMessage)},
6163 {&handle_dht_p2p_add_trail, GNUNET_MESSAGE_TYPE_XDHT_P2P_ADD_TRAIL, 0},
6164 {&handle_dht_p2p_notify_succ_confirmation, GNUNET_MESSAGE_TYPE_XDHT_P2P_NOTIFY_SUCCESSOR_CONFIRMATION,
6165 sizeof (struct PeerNotifyConfirmationMessage)},
6166 {NULL, 0, 0}
6167 };
6168
6169#if ENABLE_MALICIOUS
6170 act_malicious = 0;
6171#endif
6172
6173 core_api =
6174 GNUNET_CORE_connect (GDS_cfg, NULL, &core_init, &handle_core_connect,
6175 &handle_core_disconnect, NULL, GNUNET_NO, NULL,
6176 GNUNET_NO, core_handlers);
6177
6178 if (NULL == core_api)
6179 return GNUNET_SYSERR;
6180
6181 //TODO: check size of this peer map?
6182 friend_peermap = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO);
6183 finger_table_init ();
6184 successor_times = 10;
6185 fingers_round_count = 5;
6186 find_finger_trail_task_next_send_time.rel_value_us =
6187 DHT_FIND_FINGER_TRAIL_INTERVAL.rel_value_us +
6188 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
6189 DHT_FIND_FINGER_TRAIL_INTERVAL.rel_value_us);
6190
6191 verify_successor_next_send_time.rel_value_us =
6192 DHT_SEND_VERIFY_SUCCESSOR_INTERVAL.rel_value_us +
6193 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
6194 DHT_SEND_VERIFY_SUCCESSOR_INTERVAL.rel_value_us);
6195
6196 verify_successor_retry_time.rel_value_us =
6197 DHT_SEND_VERIFY_SUCCESSOR_RETRY_INTERVAL.rel_value_us +
6198 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
6199 DHT_SEND_VERIFY_SUCCESSOR_RETRY_INTERVAL.rel_value_us);
6200
6201 notify_successor_retry_time.rel_value_us =
6202 DHT_SEND_NOTIFY_SUCCESSOR_RETRY_INTERVAL.rel_value_us +
6203 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
6204 DHT_SEND_NOTIFY_SUCCESSOR_RETRY_INTERVAL.rel_value_us);
6205
6206
6207 return GNUNET_OK;
6208}
6209
6210
6211/**
6212 * Free the memory held up by trails of a finger.
6213 */
6214static void
6215delete_finger_table_entries()
6216{
6217 unsigned int i;
6218 unsigned int j;
6219
6220 for(i = 0; i < MAX_FINGERS; i++)
6221 {
6222 if(GNUNET_YES == finger_table[i].is_present)
6223 {
6224 for(j = 0; j < finger_table[i].trails_count; j++)
6225 free_trail(&finger_table[i].trail_list[j]);
6226 }
6227 }
6228}
6229
6230
6231/**
6232 * Shutdown neighbours subsystem.
6233 */
6234void
6235GDS_NEIGHBOURS_done (void)
6236{
6237 if (NULL == core_api)
6238 return;
6239
6240 GNUNET_CORE_disconnect (core_api);
6241 core_api = NULL;
6242
6243 delete_finger_table_entries();
6244 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friend_peermap));
6245 GNUNET_CONTAINER_multipeermap_destroy (friend_peermap);
6246 friend_peermap = NULL;
6247
6248 if (NULL != find_finger_trail_task)
6249 {
6250 GNUNET_SCHEDULER_cancel (find_finger_trail_task);
6251 find_finger_trail_task = NULL;
6252 }
6253
6254 if (NULL != send_verify_successor_task)
6255 {
6256 GNUNET_SCHEDULER_cancel (send_verify_successor_task);
6257 send_verify_successor_task = NULL;
6258 }
6259
6260 if (NULL != send_verify_successor_retry_task)
6261 {
6262 struct VerifySuccessorContext *ctx;
6263 ctx = GNUNET_SCHEDULER_cancel (send_verify_successor_retry_task);
6264 GNUNET_free(ctx);
6265 send_verify_successor_retry_task = NULL;
6266 }
6267
6268 if (send_notify_new_successor_retry_task != NULL)
6269 {
6270 struct SendNotifyContext *notify_ctx;
6271 notify_ctx = GNUNET_SCHEDULER_cancel(send_notify_new_successor_retry_task);
6272 GNUNET_free (notify_ctx->successor_trail);
6273 GNUNET_free (notify_ctx);
6274 send_notify_new_successor_retry_task = NULL;
6275 }
6276}
6277
6278
6279/**
6280 * Get my identity
6281 *
6282 * @return my identity
6283 */
6284struct GNUNET_PeerIdentity
6285GDS_NEIGHBOURS_get_my_id (void)
6286{
6287 return my_identity;
6288}
6289
6290/* end of gnunet-service-xdht_neighbours.c */
diff --git a/src/dht/gnunet-service-wdht_neighbours.h b/src/dht/gnunet-service-wdht_neighbours.h
new file mode 100644
index 000000000..edb241a6c
--- /dev/null
+++ b/src/dht/gnunet-service-wdht_neighbours.h
@@ -0,0 +1,146 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file dht/gnunet-service-xdht_neighbours.h
23 * @brief GNUnet DHT routing code
24 * @author Supriti Singh
25 */
26
27#ifndef GNUNET_SERVICE_XDHT_NEIGHBOURS_H
28#define GNUNET_SERVICE_XDHT_NEIGHBOURS_H
29
30#include "gnunet_util_lib.h"
31#include "gnunet_block_lib.h"
32#include "gnunet_dht_service.h"
33
34
35#if ENABLE_MALICIOUS
36/**
37 * Set the ENABLE_MALICIOUS value to malicious.
38 * @param malicious
39 */
40int
41GDS_NEIGHBOURS_act_malicious (unsigned int malicious);
42#endif
43
44/**
45 * Handle the put request from the client.
46 * @param key Key for the content
47 * @param block_type Type of the block
48 * @param options Routing options
49 * @param desired_replication_level Desired replication count
50 * @param expiration_time When does the content expire
51 * @param data Content to store
52 * @param data_size Size of content @a data in bytes
53 */
54void
55GDS_NEIGHBOURS_handle_put (const struct GNUNET_HashCode *key,
56 enum GNUNET_BLOCK_Type block_type,
57 enum GNUNET_DHT_RouteOption options,
58 uint32_t desired_replication_level,
59 struct GNUNET_TIME_Absolute expiration_time,
60 const void *data, size_t data_size);
61
62/**
63 * Handle the get request from the client file. If I am destination do
64 * datacache put and return. Else find the target friend and forward message
65 * to it.
66 * @param key Key for the content
67 * @param block_type Type of the block
68 * @param options Routing options
69 * @param desired_replication_level Desired replication count
70 */
71void
72GDS_NEIGHBOURS_handle_get(const struct GNUNET_HashCode *key,
73 enum GNUNET_BLOCK_Type block_type,
74 enum GNUNET_DHT_RouteOption options,
75 uint32_t desired_replication_level);
76
77/**
78 * Send the get result to requesting client.
79 * @param key Key of the requested data.
80 * @param type Block type
81 * @param target_peer Next peer to forward the message to.
82 * @param source_peer Peer which has the data for the key.
83 * @param put_path_length Number of peers in @a put_path
84 * @param put_path Path taken to put the data at its stored location.
85 * @param get_path_length Number of peers in @a get_path
86 * @param get_path Path taken to reach to the location of the key.
87 * @param expiration When will this result expire?
88 * @param data Payload to store
89 * @param data_size Size of the @a data
90 */
91void
92GDS_NEIGHBOURS_send_get_result (const struct GNUNET_HashCode *key,
93 enum GNUNET_BLOCK_Type type,
94 const struct GNUNET_PeerIdentity *target_peer,
95 const struct GNUNET_PeerIdentity *source_peer,
96 unsigned int put_path_length,
97 const struct GNUNET_PeerIdentity *put_path,
98 unsigned int get_path_length,
99 const struct GNUNET_PeerIdentity *get_path,
100 struct GNUNET_TIME_Absolute expiration,
101 const void *data, size_t data_size);
102
103/**
104 * Construct a trail teardown message and forward it to target friend.
105 * @param trail_id Unique identifier of the trail.
106 * @param trail_direction Direction of trail.
107 * @param target_friend Friend to get this message.
108 */
109void
110GDS_NEIGHBOURS_send_trail_teardown (const struct GNUNET_HashCode *trail_id,
111 unsigned int trail_direction,
112 const struct GNUNET_PeerIdentity *peer);
113
114/**
115 * Return friend corresponding to peer.
116 * @param peer
117 * @return Friend
118 */
119struct FriendInfo *
120GDS_NEIGHBOURS_get_friend (struct GNUNET_PeerIdentity peer);
121/**
122 * Initialize neighbours subsystem.
123 *
124 * @return #GNUNET_OK on success,
125 * #GNUNET_SYSERR on error
126 */
127int
128GDS_NEIGHBOURS_init (void);
129
130
131/**
132 * Shutdown neighbours subsystem.
133 */
134void
135GDS_NEIGHBOURS_done (void);
136
137
138/**
139 * Get my identity
140 *
141 * @return my identity
142 */
143struct GNUNET_PeerIdentity
144GDS_NEIGHBOURS_get_my_id (void);
145
146#endif
diff --git a/src/dht/gnunet-service-wdht_nse.c b/src/dht/gnunet-service-wdht_nse.c
new file mode 100644
index 000000000..4cce88f6e
--- /dev/null
+++ b/src/dht/gnunet-service-wdht_nse.c
@@ -0,0 +1,116 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file dht/gnunet-service-xdht_nse.c
23 * @brief GNUnet DHT integration with NSE
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_nse_service.h"
28#include "gnunet-service-wdht.h"
29#include "gnunet-service-wdht_nse.h"
30
31/**
32 * log of the current network size estimate, used as the point where
33 * we switch between random and deterministic routing. Default
34 * value of 4.0 is used if NSE module is not available (i.e. not
35 * configured).
36 */
37static double log_of_network_size_estimate = 4.0;
38
39/**
40 * Network size estimation handle.
41 */
42static struct GNUNET_NSE_Handle *nse;
43
44
45/**
46 * Callback that is called when network size estimate is updated.
47 *
48 * @param cls closure
49 * @param timestamp time when the estimate was received from the server (or created by the server)
50 * @param logestimate the log(Base 2) value of the current network size estimate
51 * @param std_dev standard deviation for the estimate
52 *
53 */
54static void
55update_network_size_estimate (void *cls, struct GNUNET_TIME_Absolute timestamp,
56 double logestimate, double std_dev)
57{
58 GNUNET_STATISTICS_update (GDS_stats,
59 gettext_noop ("# Network size estimates received"),
60 1, GNUNET_NO);
61 /* do not allow estimates < 0.5 */
62 log_of_network_size_estimate = GNUNET_MAX (0.5, logestimate);
63}
64
65
66/**
67 * Return the log of the current network size estimate.
68 *
69 * @return log of NSE
70 */
71double
72GDS_NSE_get ()
73{
74 return log_of_network_size_estimate;
75}
76
77
78/**
79 * Initialize NSE subsystem.
80 */
81void
82GDS_NSE_init ()
83{
84 unsigned long long hops;
85
86 if ( (GNUNET_YES ==
87 GNUNET_CONFIGURATION_have_value (GDS_cfg,
88 "dht",
89 "FORCE_NSE")) &&
90 (GNUNET_OK ==
91 GNUNET_CONFIGURATION_get_value_number (GDS_cfg,
92 "dht",
93 "FORCE_NSE",
94 &hops)) )
95 {
96 log_of_network_size_estimate = (double) hops;
97 return;
98 }
99 nse = GNUNET_NSE_connect (GDS_cfg, &update_network_size_estimate, NULL);
100}
101
102
103/**
104 * Shutdown NSE subsystem.
105 */
106void
107GDS_NSE_done ()
108{
109 if (NULL != nse)
110 {
111 GNUNET_NSE_disconnect (nse);
112 nse = NULL;
113 }
114}
115
116/* end of gnunet-service-dht_nse.c */
diff --git a/src/dht/gnunet-service-wdht_nse.h b/src/dht/gnunet-service-wdht_nse.h
new file mode 100644
index 000000000..86ce9d68e
--- /dev/null
+++ b/src/dht/gnunet-service-wdht_nse.h
@@ -0,0 +1,52 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file dht/gnunet-service-xdht_nse.h
23 * @brief GNUnet DHT integration with NSE
24 * @author Christian Grothoff
25 */
26#ifndef GNUNET_SERVICE_XDHT_NSE_H
27#define GNUNET_SERVICE_XDHT_NSE_H
28
29
30/**
31 * Return the log of the current network size estimate.
32 *
33 * @return log of NSE
34 */
35double
36GDS_NSE_get (void);
37
38
39/**
40 * Initialize NSE subsystem.
41 */
42void
43GDS_NSE_init (void);
44
45
46/**
47 * Shutdown NSE subsystem.
48 */
49void
50GDS_NSE_done (void);
51
52#endif
diff --git a/src/dht/gnunet-service-wdht_routing.c b/src/dht/gnunet-service-wdht_routing.c
new file mode 100644
index 000000000..986eb11ac
--- /dev/null
+++ b/src/dht/gnunet-service-wdht_routing.c
@@ -0,0 +1,363 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011 - 2014 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file dht/gnunet-service-xdht_routing.c
23 * @brief GNUnet DHT tracking of requests for routing replies
24 * @author Supriti Singh
25 */
26#include "platform.h"
27#include "gnunet-service-wdht_neighbours.h"
28#include "gnunet-service-wdht_routing.h"
29#include "gnunet-service-wdht.h"
30
31
32/**
33 * FIXME: Check if its better to store pointer to friend rather than storing
34 * peer identity next_hop or prev_hop.
35 * keep entries in destnation and source peer also. so when we send the trail
36 * teardown message then we don't know the source but if source gets the message
37 * then it shold remove that trail id from its finger table. But how does
38 * source know what is the desination finger ? It will whenevr contact a trail
39 * will do a lookup in routing table and if no trail id present the remove
40 * that trail of the finger and if only one trail then remove the finger.
41 * because of this use case of trail teardown I think trail compression
42 * and trail teardown should not be merged.
43 * 2. store a pointer to friendInfo in place o peer identity.
44 */
45/**
46 * Maximum number of entries in routing table.
47 */
48#define ROUTING_TABLE_THRESHOLD 80000
49
50/**
51 * FIXME: Store friend pointer instead of peer identifier.
52 * Routing table entry .
53 */
54struct RoutingTrail
55{
56 /**
57 * Global Unique identifier of the trail.
58 */
59 struct GNUNET_HashCode trail_id;
60
61 /**
62 * The peer to which this request should be passed to.
63 */
64 struct GNUNET_PeerIdentity next_hop;
65
66 /**
67 * Peer just before next hop in the trail.
68 */
69 struct GNUNET_PeerIdentity prev_hop;
70};
71
72/**
73 * Routing table of the peer
74 */
75static struct GNUNET_CONTAINER_MultiHashMap *routing_table;
76
77/**
78 * Update the prev. hop of the trail. Call made by trail compression where
79 * if you are the first friend now in the trail then you need to update
80 * your prev. hop.
81 * @param trail_id
82 * @return #GNUNET_OK success
83 * #GNUNET_SYSERR in case no matching entry found in routing table.
84 */
85int
86GDS_ROUTING_update_trail_prev_hop (const struct GNUNET_HashCode trail_id,
87 struct GNUNET_PeerIdentity prev_hop)
88{
89 struct RoutingTrail *trail;
90
91 trail = GNUNET_CONTAINER_multihashmap_get (routing_table, &trail_id);
92
93 if (NULL == trail)
94 return GNUNET_SYSERR;
95
96 trail->prev_hop = prev_hop;
97 return GNUNET_OK;
98}
99
100/**
101 * Update the next hop of the trail. Call made by trail compression where
102 * if you are source of the trail and now you have a new first friend, then
103 * you should update the trail.
104 * @param trail_id
105 * @return #GNUNET_OK success
106 * #GNUNET_SYSERR in case no matching entry found in routing table.
107 */
108int
109GDS_ROUTING_update_trail_next_hop (const struct GNUNET_HashCode trail_id,
110 struct GNUNET_PeerIdentity next_hop)
111{
112 struct RoutingTrail *trail;
113
114 trail = GNUNET_CONTAINER_multihashmap_get (routing_table, &trail_id);
115
116 if (NULL == trail)
117
118 return GNUNET_SYSERR;
119
120 trail->next_hop = next_hop;
121 return GNUNET_OK;
122}
123
124/**
125 * Get the next hop for trail corresponding to trail_id
126 * @param trail_id Trail id to be searched.
127 * @return Next_hop if found
128 * NULL If next hop not found.
129 */
130struct GNUNET_PeerIdentity *
131GDS_ROUTING_get_next_hop (const struct GNUNET_HashCode trail_id,
132 enum GDS_ROUTING_trail_direction trail_direction)
133{
134 struct RoutingTrail *trail;
135
136 trail = GNUNET_CONTAINER_multihashmap_get (routing_table, &trail_id);
137 if (NULL == trail)
138 {
139 /* If a friend got disconnected and we removed all the entry from the
140 routing table, then trail will be deleted and my identity will not know
141 and when it tries to reach to that finger it fails. thats why
142 assertion always fails in*/
143 return NULL;
144 }
145 switch (trail_direction)
146 {
147 case GDS_ROUTING_SRC_TO_DEST:
148 return &(trail->next_hop);
149 case GDS_ROUTING_DEST_TO_SRC:
150 return &(trail->prev_hop);
151 }
152 return NULL;
153}
154
155
156/**
157 * Remove trail with trail_id
158 * @param trail_id Trail id to be removed
159 * @return #GNUNET_YES success
160 * #GNUNET_NO if entry not found.
161 */
162int
163GDS_ROUTING_remove_trail (const struct GNUNET_HashCode remove_trail_id)
164{
165 struct RoutingTrail *remove_entry;
166
167 remove_entry = GNUNET_CONTAINER_multihashmap_get (routing_table, &remove_trail_id);
168 if (NULL == remove_entry)
169 return GNUNET_NO;
170
171 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (routing_table,
172 &remove_trail_id,
173 remove_entry))
174 {
175 GNUNET_free (remove_entry);
176 return GNUNET_YES;
177 }
178
179 return GNUNET_NO;
180}
181
182
183/**
184 * Iterate over routing table and remove entries with value as part of any trail.
185 *
186 * @param cls closure
187 * @param key current public key
188 * @param value value in the hash map
189 * @return #GNUNET_YES if we should continue to iterate,
190 * #GNUNET_NO if not.
191 */
192static int remove_matching_trails (void *cls,
193 const struct GNUNET_HashCode *key,
194 void *value)
195{
196 struct RoutingTrail *remove_trail = value;
197 struct GNUNET_PeerIdentity *disconnected_peer = cls;
198 struct GNUNET_HashCode trail_id = *key;
199 struct GNUNET_PeerIdentity my_identity;
200
201 /* If disconnected_peer is next_hop, then send a trail teardown message through
202 * prev_hop in direction from destination to source. */
203 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&remove_trail->next_hop,
204 disconnected_peer))
205 {
206 my_identity = GDS_NEIGHBOURS_get_my_id ();
207 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity,
208 &remove_trail->prev_hop))
209 {
210 GDS_NEIGHBOURS_send_trail_teardown (&trail_id,
211 GDS_ROUTING_DEST_TO_SRC,
212 &remove_trail->prev_hop);
213 }
214 }
215
216 /* If disconnected_peer is prev_hop, then send a trail teardown through
217 * next_hop in direction from Source to Destination. */
218 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&remove_trail->prev_hop,
219 disconnected_peer))
220 {
221 my_identity = GDS_NEIGHBOURS_get_my_id ();
222
223 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity,
224 &remove_trail->next_hop))
225 {
226 GDS_NEIGHBOURS_send_trail_teardown (&trail_id,
227 GDS_ROUTING_SRC_TO_DEST,
228 &remove_trail->next_hop);
229 }
230 }
231
232 GNUNET_assert (GNUNET_YES ==
233 GNUNET_CONTAINER_multihashmap_remove (routing_table,
234 &trail_id,
235 remove_trail));
236 GNUNET_free (remove_trail);
237 return GNUNET_YES;
238}
239
240#if 0
241/**
242 * TEST FUNCTION
243 * Remove after using.
244 */
245void
246GDS_ROUTING_test_print (void)
247{
248 struct GNUNET_CONTAINER_MultiHashMapIterator *iter;
249 struct RoutingTrail *trail;
250 struct GNUNET_PeerIdentity print_peer;
251 struct GNUNET_HashCode key_ret;
252 int i;
253
254 struct GNUNET_PeerIdentity my_identity = GDS_NEIGHBOURS_get_my_id();
255 print_peer = my_identity;
256 FPRINTF (stderr,_("\nSUPU ***PRINTING ROUTING TABLE ***** of =%s"),GNUNET_i2s(&print_peer));
257 iter =GNUNET_CONTAINER_multihashmap_iterator_create (routing_table);
258 for (i = 0; i < GNUNET_CONTAINER_multihashmap_size(routing_table); i++)
259 {
260 if(GNUNET_YES == GNUNET_CONTAINER_multihashmap_iterator_next (iter,
261 &key_ret,
262 (const void **)&trail))
263 {
264 FPRINTF (stderr,_("\nSUPU %s, %s, %d, trail->trail_id = %s"),
265 __FILE__, __func__,__LINE__, GNUNET_h2s(&trail->trail_id));
266 memcpy (&print_peer, &trail->next_hop, sizeof (struct GNUNET_PeerIdentity));
267 FPRINTF (stderr,_("\nSUPU %s, %s, %d, trail->next_hop = %s"),
268 __FILE__, __func__,__LINE__, GNUNET_i2s(&print_peer));
269 memcpy (&print_peer, &trail->prev_hop, sizeof (struct GNUNET_PeerIdentity));
270 FPRINTF (stderr,_("\nSUPU %s, %s, %d, trail->prev_hop = %s"),
271 __FILE__, __func__,__LINE__, GNUNET_i2s(&print_peer));
272 }
273 }
274}
275#endif
276
277/**
278 * Remove every trail where peer is either next_hop or prev_hop. Also send a
279 * trail teardown message in direction of hop which is not disconnected.
280 * @param peer Peer identity. Trail containing this peer should be removed.
281 */
282int
283GDS_ROUTING_remove_trail_by_peer (const struct GNUNET_PeerIdentity *peer)
284{
285 int ret;
286
287
288 /* No entries in my routing table. */
289 if (0 == GNUNET_CONTAINER_multihashmap_size(routing_table))
290 return GNUNET_YES;
291
292 ret = GNUNET_CONTAINER_multihashmap_iterate (routing_table,
293 &remove_matching_trails,
294 (void *)peer);
295 return ret;
296}
297
298
299/**
300 * Add a new entry in routing table
301 * @param new_trail_id
302 * @param prev_hop
303 * @param next_hop
304 * @return #GNUNET_OK success
305 * #GNUNET_SYSERR in case new_trail_id already exists in the network
306 * but with different prev_hop/next_hop
307 */
308int
309GDS_ROUTING_add (struct GNUNET_HashCode new_trail_id,
310 struct GNUNET_PeerIdentity prev_hop,
311 struct GNUNET_PeerIdentity next_hop)
312{
313 struct RoutingTrail *new_entry;
314
315 new_entry = GNUNET_new (struct RoutingTrail);
316 new_entry->trail_id = new_trail_id;
317 new_entry->next_hop = next_hop;
318 new_entry->prev_hop = prev_hop;
319
320
321 return GNUNET_CONTAINER_multihashmap_put (routing_table,
322 &new_trail_id, new_entry,
323 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
324
325}
326
327
328/**
329 * Check if the size of routing table has crossed ROUTING_TABLE_THRESHOLD.
330 * It means that I don't have any more space in my routing table and I can not
331 * be part of any more trails till there is free space in my routing table.
332 * @return #GNUNET_YES, if threshold crossed else #GNUNET_NO.
333 */
334int
335GDS_ROUTING_threshold_reached (void)
336{
337 return (GNUNET_CONTAINER_multihashmap_size(routing_table) >
338 ROUTING_TABLE_THRESHOLD) ? GNUNET_YES:GNUNET_NO;
339}
340
341
342/**
343 * Initialize routing subsystem.
344 */
345void
346GDS_ROUTING_init (void)
347{
348 routing_table = GNUNET_CONTAINER_multihashmap_create (ROUTING_TABLE_THRESHOLD * 4 / 3,
349 GNUNET_NO);
350}
351
352
353/**
354 * Shutdown routing subsystem.
355 */
356void
357GDS_ROUTING_done (void)
358{
359 GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (routing_table));
360 GNUNET_CONTAINER_multihashmap_destroy (routing_table);
361}
362
363/* end of gnunet-service-xdht_routing.c */
diff --git a/src/dht/gnunet-service-wdht_routing.h b/src/dht/gnunet-service-wdht_routing.h
new file mode 100644
index 000000000..5292ec2ce
--- /dev/null
+++ b/src/dht/gnunet-service-wdht_routing.h
@@ -0,0 +1,138 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011 - 2014 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file dht/gnunet-service-xdht_routing.h
23 * @brief GNUnet DHT tracking of requests for routing replies
24 * @author Christian Grothoff
25 */
26#ifndef GNUNET_SERVICE_XDHT_ROUTING_H
27#define GNUNET_SERVICE_XDHT_ROUTING_H
28
29#include "gnunet_util_lib.h"
30#include "gnunet_block_lib.h"
31#include "gnunet_dht_service.h"
32
33/**
34 * To understand the direction in which trial should be read.
35 */
36enum GDS_ROUTING_trail_direction
37{
38 GDS_ROUTING_SRC_TO_DEST,
39 GDS_ROUTING_DEST_TO_SRC
40};
41
42
43/**
44 * Update the prev. hop of the trail. Call made by trail teardown where
45 * if you are the first friend now in the trail then you need to update
46 * your prev. hop.
47 * @param trail_id
48 * @return #GNUNET_OK success
49 * #GNUNET_SYSERR in case no matching entry found in routing table.
50 */
51int
52GDS_ROUTING_update_trail_prev_hop (struct GNUNET_HashCode trail_id,
53 struct GNUNET_PeerIdentity prev_hop);
54
55
56/**
57 * Update the next hop of the trail. Call made by trail compression where
58 * if you are source of the trail and now you have a new first friend, then
59 * you should update the trail.
60 * @param trail_id
61 * @return #GNUNET_OK success
62 * #GNUNET_SYSERR in case no matching entry found in routing table.
63 */
64int
65GDS_ROUTING_update_trail_next_hop (const struct GNUNET_HashCode trail_id,
66 struct GNUNET_PeerIdentity next_hop);
67
68/**
69 * Get the next hop for trail corresponding to trail_id
70 * @param trail_id Trail id to be searched.
71 * @return Next_hop if found
72 * NULL If next hop not found.
73 */
74struct GNUNET_PeerIdentity *
75GDS_ROUTING_get_next_hop (struct GNUNET_HashCode trail_id,
76 enum GDS_ROUTING_trail_direction trail_direction);
77
78
79/**
80 * Remove every trail where peer is either next_hop or prev_hop
81 * @param peer Peer to be searched.
82 */
83int
84GDS_ROUTING_remove_trail_by_peer (const struct GNUNET_PeerIdentity *peer);
85/**
86 * Remove trail with trail_id
87 * @param trail_id Trail id to be removed
88 * @return #GNUNET_YES success
89 * #GNUNET_NO if entry not found.
90 */
91int
92GDS_ROUTING_remove_trail (struct GNUNET_HashCode remove_trail_id);
93
94
95/**
96 * Add a new entry in routing table
97 * @param new_trail_id
98 * @param prev_hop
99 * @param next_hop
100 * @return #GNUNET_OK success
101 * #GNUNET_SYSERR in case new_trail_id already exists in the network
102 * but with different prev_hop/next_hop
103 */
104int
105GDS_ROUTING_add (struct GNUNET_HashCode new_trail_id,
106 struct GNUNET_PeerIdentity prev_hop,
107 struct GNUNET_PeerIdentity next_hop);
108
109
110/**
111 * Check if the size of routing table has crossed threshold.
112 * @return #GNUNET_YES, if threshold crossed
113 * #GNUNET_NO, if size is within threshold
114 */
115int
116GDS_ROUTING_threshold_reached (void);
117
118#if 0
119/**
120 * Test function. Remove afterwards.
121 */
122void
123GDS_ROUTING_test_print (void);
124#endif
125
126/**
127 * Initialize routing subsystem.
128 */
129void
130GDS_ROUTING_init (void);
131
132/**
133 * Shutdown routing subsystem.
134 */
135void
136GDS_ROUTING_done (void);
137
138#endif \ No newline at end of file