aboutsummaryrefslogtreecommitdiff
path: root/src/cadet/gnunet-service-cadet_peer.c
diff options
context:
space:
mode:
authortg(x) <*@tg-x.net>2017-03-22 10:08:01 +0100
committertg(x) <*@tg-x.net>2017-03-22 10:08:01 +0100
commitaa98f144e6db0da5a0a4cad83fe64a80bbab6692 (patch)
tree5a072b4e1b689bf4330b2a412bdadc705d33ff75 /src/cadet/gnunet-service-cadet_peer.c
parentcaeeec6cacaa5354883494cb64b0a38e5c75da5d (diff)
parentb424335cc632a11bd76bad5791cef10e8c985720 (diff)
downloadgnunet-aa98f144e6db0da5a0a4cad83fe64a80bbab6692.tar.gz
gnunet-aa98f144e6db0da5a0a4cad83fe64a80bbab6692.zip
Merge branch 'master' of gnunet.org:gnunet
Diffstat (limited to 'src/cadet/gnunet-service-cadet_peer.c')
-rw-r--r--src/cadet/gnunet-service-cadet_peer.c2928
1 files changed, 1098 insertions, 1830 deletions
diff --git a/src/cadet/gnunet-service-cadet_peer.c b/src/cadet/gnunet-service-cadet_peer.c
index fa3f2be80..71c7c67d0 100644
--- a/src/cadet/gnunet-service-cadet_peer.c
+++ b/src/cadet/gnunet-service-cadet_peer.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2013, 2015 GNUnet e.V. 3 Copyright (C) 2001-2017 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 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 6 it under the terms of the GNU General Public License as published
@@ -17,2193 +17,1461 @@
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA. 18 Boston, MA 02110-1301, USA.
19*/ 19*/
20
20/** 21/**
21 * @file cadet/gnunet-service-cadet_peer.c 22 * @file cadet/gnunet-service-cadet_peer.c
22 * @brief GNUnet CADET service connection handling 23 * @brief Information we track per peer.
23 * @author Bartlomiej Polot 24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
26 *
27 * TODO:
28 * - optimize stopping/restarting DHT search to situations
29 * where we actually need it (i.e. not if we have a direct connection,
30 * or if we already have plenty of good short ones, or maybe even
31 * to take a break if we have some connections and have searched a lot (?))
24 */ 32 */
25#include "platform.h" 33#include "platform.h"
26#include "gnunet_util_lib.h" 34#include "gnunet_util_lib.h"
35#include "gnunet_hello_lib.h"
27#include "gnunet_signatures.h" 36#include "gnunet_signatures.h"
28#include "gnunet_transport_service.h" 37#include "gnunet_transport_service.h"
29#include "gnunet_ats_service.h" 38#include "gnunet_ats_service.h"
30#include "gnunet_core_service.h" 39#include "gnunet_core_service.h"
31#include "gnunet_statistics_service.h" 40#include "gnunet_statistics_service.h"
32#include "cadet_protocol.h" 41#include "cadet_protocol.h"
33#include "gnunet-service-cadet_peer.h"
34#include "gnunet-service-cadet_dht.h"
35#include "gnunet-service-cadet_connection.h" 42#include "gnunet-service-cadet_connection.h"
36#include "gnunet-service-cadet_tunnel.h" 43#include "gnunet-service-cadet_dht.h"
37#include "cadet_path.h" 44#include "gnunet-service-cadet_peer.h"
45#include "gnunet-service-cadet_paths.h"
46#include "gnunet-service-cadet_tunnels.h"
38 47
39#define LOG(level, ...) GNUNET_log_from (level,"cadet-p2p",__VA_ARGS__)
40#define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-p2p",__VA_ARGS__)
41 48
49#define LOG(level, ...) GNUNET_log_from(level,"cadet-per",__VA_ARGS__)
42 50
43/******************************************************************************/
44/******************************** STRUCTS **********************************/
45/******************************************************************************/
46 51
47/** 52/**
48 * Information about a queued message on the peer level. 53 * How long do we wait until tearing down an idle peer?
49 */ 54 */
50struct CadetPeerQueue { 55#define IDLE_PEER_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5)
51
52 struct CadetPeerQueue *next;
53 struct CadetPeerQueue *prev;
54
55 /**
56 * Envelope to cancel message before MQ sends it.
57 */
58 struct GNUNET_MQ_Envelope *env;
59
60 /**
61 * Peer (neighbor) this message is being sent to.
62 */
63 struct CadetPeer *peer;
64
65 /**
66 * Continuation to call to notify higher layers about message sent.
67 */
68 GCP_sent cont;
69
70 /**
71 * Closure for @a cont.
72 */
73 void *cont_cls;
74
75 /**
76 * Task to asynchronously run the drop continuation.
77 */
78 struct GNUNET_SCHEDULER_Task *drop_task;
79
80 /**
81 * Time when message was queued for sending.
82 */
83 struct GNUNET_TIME_Absolute queue_timestamp;
84
85 /**
86 * #GNUNET_YES if message was management traffic (POLL, ACK, ...).
87 */
88 int management_traffic;
89
90 /**
91 * Message type.
92 */
93 uint16_t type;
94
95 /**
96 * Message size.
97 */
98 uint16_t size;
99
100 /**
101 * Type of the message's payload, if it was encrypted data.
102 */
103 uint16_t payload_type;
104
105 /**
106 * ID of the payload (PID, ACK #, ...).
107 */
108 struct CadetEncryptedMessageIdentifier payload_id;
109
110 /**
111 * Connection this message was sent on.
112 */
113 struct CadetConnection *c;
114
115 /**
116 * Direction in @a c this message was send on (#GNUNET_YES = FWD).
117 */
118 int c_fwd;
119};
120
121 56
122/** 57/**
123 * Struct containing all information regarding a given peer 58 * How long do we keep paths around if we no longer care about the peer?
124 */ 59 */
125struct CadetPeer 60#define IDLE_PATH_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2)
126{
127 /**
128 * ID of the peer
129 */
130 GNUNET_PEER_Id id;
131
132 struct CadetPeerQueue *q_head;
133 struct CadetPeerQueue *q_tail;
134
135 /**
136 * Last time we heard from this peer
137 */
138 struct GNUNET_TIME_Absolute last_contact;
139
140 /**
141 * Paths to reach the peer, ordered by ascending hop count
142 */
143 struct CadetPeerPath *path_head;
144
145 /**
146 * Paths to reach the peer, ordered by ascending hop count
147 */
148 struct CadetPeerPath *path_tail;
149
150 /**
151 * Handle to stop the DHT search for paths to this peer
152 */
153 struct GCD_search_handle *search_h;
154
155 /**
156 * Handle to stop the DHT search for paths to this peer
157 */
158 struct GNUNET_SCHEDULER_Task *search_delayed;
159
160 /**
161 * Tunnel to this peer, if any.
162 */
163 struct CadetTunnel *tunnel;
164
165 /**
166 * Connections that go through this peer; indexed by tid.
167 */
168 struct GNUNET_CONTAINER_MultiShortmap *connections;
169
170 /**
171 * Handle for core transmissions.
172 */
173 struct GNUNET_MQ_Handle *core_mq;
174
175 /**
176 * How many messages are in the queue to this peer.
177 */
178 unsigned int queue_n;
179
180 /**
181 * Hello message.
182 */
183 struct GNUNET_HELLO_Message* hello;
184
185 /**
186 * Handle to us offering the HELLO to the transport.
187 */
188 struct GNUNET_TRANSPORT_OfferHelloHandle *hello_offer;
189
190 /**
191 * Handle to our ATS request asking ATS to suggest an address
192 * to TRANSPORT for this peer (to establish a direct link).
193 */
194 struct GNUNET_ATS_ConnectivitySuggestHandle *connectivity_suggestion;
195 61
196};
197
198
199/******************************************************************************/
200/******************************* GLOBALS ***********************************/
201/******************************************************************************/
202
203/**
204 * Global handle to the statistics service.
205 */
206extern struct GNUNET_STATISTICS_Handle *stats;
207 62
208/**
209 * Local peer own ID (full value).
210 */
211extern struct GNUNET_PeerIdentity my_full_id;
212 63
213/**
214 * Local peer own ID (short)
215 */
216extern GNUNET_PEER_Id myid;
217 64
218/** 65/**
219 * Peers known, indexed by PeerIdentity, values of type `struct CadetPeer`. 66 * Data structure used to track whom we have to notify about changes
67 * to our message queue.
220 */ 68 */
221static struct GNUNET_CONTAINER_MultiPeerMap *peers; 69struct GCP_MessageQueueManager
222 70{
223/**
224 * How many peers do we want to remember?
225 */
226static unsigned long long max_peers;
227 71
228/** 72 /**
229 * Percentage of messages that will be dropped (for test purposes only). 73 * Kept in a DLL.
230 */ 74 */
231static unsigned long long drop_percent; 75 struct GCP_MessageQueueManager *next;
232 76
233/** 77 /**
234 * Handle to communicate with CORE. 78 * Kept in a DLL.
235 */ 79 */
236static struct GNUNET_CORE_Handle *core_handle; 80 struct GCP_MessageQueueManager *prev;
237 81
238/** 82 /**
239 * Our configuration; 83 * Function to call with updated message queue object.
240 */ 84 */
241static const struct GNUNET_CONFIGURATION_Handle *cfg; 85 GCP_MessageQueueNotificationCallback cb;
242 86
243/** 87 /**
244 * Handle to communicate with ATS. 88 * Closure for @e cb.
245 */ 89 */
246static struct GNUNET_ATS_ConnectivityHandle *ats_ch; 90 void *cb_cls;
247 91
248/** 92 /**
249 * Shutdown falg. 93 * The peer this is for.
250 */ 94 */
251static int in_shutdown; 95 struct CadetPeer *cp;
252 96
97 /**
98 * Envelope this manager would like to transmit once it is its turn.
99 */
100 struct GNUNET_MQ_Envelope *env;
253 101
254/******************************************************************************/ 102};
255/***************************** CORE HELPERS *********************************/
256/******************************************************************************/
257 103
258 104
259/** 105/**
260 * Iterator to notify all connections of a broken link. Mark connections 106 * Struct containing all information regarding a given peer
261 * to destroy after all traffic has been sent.
262 *
263 * @param cls Closure (disconnected peer).
264 * @param key Current key code (peer id).
265 * @param value Value in the hash map (connection).
266 *
267 * @return #GNUNET_YES to continue to iterate.
268 */ 107 */
269static int 108struct CadetPeer
270notify_broken (void *cls,
271 const struct GNUNET_ShortHashCode *key,
272 void *value)
273{ 109{
274 struct CadetPeer *peer = cls; 110 /**
275 struct CadetConnection *c = value; 111 * ID of the peer
112 */
113 struct GNUNET_PeerIdentity pid;
114
115 /**
116 * Last time we heard from this peer (currently not used!)
117 */
118 struct GNUNET_TIME_Absolute last_contactXXX;
119
120 /**
121 * Array of DLLs of paths traversing the peer, organized by the
122 * offset of the peer on the larger path.
123 */
124 struct CadetPeerPathEntry **path_heads;
125
126 /**
127 * Array of DLL of paths traversing the peer, organized by the
128 * offset of the peer on the larger path.
129 */
130 struct CadetPeerPathEntry **path_tails;
131
132 /**
133 * Notifications to call when @e core_mq changes.
134 */
135 struct GCP_MessageQueueManager *mqm_head;
136
137 /**
138 * Notifications to call when @e core_mq changes.
139 */
140 struct GCP_MessageQueueManager *mqm_tail;
141
142 /**
143 * Pointer to first "ready" entry in @e mqm_head.
144 */
145 struct GCP_MessageQueueManager *mqm_ready_ptr;
146
147 /**
148 * MIN-heap of paths owned by this peer (they also end at this
149 * peer). Ordered by desirability.
150 */
151 struct GNUNET_CONTAINER_Heap *path_heap;
152
153 /**
154 * Handle to stop the DHT search for paths to this peer
155 */
156 struct GCD_search_handle *search_h;
157
158 /**
159 * Task to clean up @e path_heap asynchronously.
160 */
161 struct GNUNET_SCHEDULER_Task *heap_cleanup_task;
162
163 /**
164 * Task to destroy this entry.
165 */
166 struct GNUNET_SCHEDULER_Task *destroy_task;
167
168 /**
169 * Tunnel to this peer, if any.
170 */
171 struct CadetTunnel *t;
172
173 /**
174 * Connections that go through this peer; indexed by tid.
175 */
176 struct GNUNET_CONTAINER_MultiShortmap *connections;
177
178 /**
179 * Handle for core transmissions.
180 */
181 struct GNUNET_MQ_Handle *core_mq;
182
183 /**
184 * Hello message of the peer.
185 */
186 struct GNUNET_HELLO_Message *hello;
187
188 /**
189 * Handle to us offering the HELLO to the transport.
190 */
191 struct GNUNET_TRANSPORT_OfferHelloHandle *hello_offer;
192
193 /**
194 * Handle to our ATS request asking ATS to suggest an address
195 * to TRANSPORT for this peer (to establish a direct link).
196 */
197 struct GNUNET_ATS_ConnectivitySuggestHandle *connectivity_suggestion;
198
199 /**
200 * How many messages are in the queue to this peer.
201 */
202 unsigned int queue_n;
203
204 /**
205 * How many paths do we have to this peer (in all @e path_heads DLLs combined).
206 */
207 unsigned int num_paths;
208
209 /**
210 * Sum over all of the offsets of all of the paths in the @a path_heads DLLs.
211 * Used to speed-up @GCP_get_desirability_of_path() calculation.
212 */
213 unsigned int off_sum;
214
215 /**
216 * Number of message queue managers of this peer that have a message in waiting.
217 *
218 * Used to quickly see if we need to bother scanning the @e msm_head DLL.
219 * TODO: could be replaced by another DLL that would then allow us to avoid
220 * the O(n)-scan of the DLL for ready entries!
221 */
222 unsigned int mqm_ready_counter;
223
224 /**
225 * Current length of the @e path_heads and @path_tails arrays.
226 * The arrays should be grown as needed.
227 */
228 unsigned int path_dll_length;
276 229
277 LOG (GNUNET_ERROR_TYPE_DEBUG, 230};
278 "Notifying %s due to %s disconnect\n",
279 GCC_2s (c), GCP_2s (peer));
280 GCC_neighbor_disconnected (c, peer);
281 return GNUNET_YES;
282}
283 231
284 232
285/** 233/**
286 * Remove the direct path to the peer. 234 * Get the static string for a peer ID.
287 *
288 * @param peer Peer to remove the direct path from.
289 */
290static struct CadetPeerPath *
291pop_direct_path (struct CadetPeer *peer)
292{
293 struct CadetPeerPath *iter;
294
295 for (iter = peer->path_head; NULL != iter; iter = iter->next)
296 {
297 if (2 >= iter->length)
298 {
299 GNUNET_CONTAINER_DLL_remove (peer->path_head,
300 peer->path_tail,
301 iter);
302 return iter;
303 }
304 }
305 return NULL;
306}
307
308/**
309 * Call the continuation after a message has been sent or dropped.
310 *
311 * This funcion removes the message from the queue.
312 * 235 *
313 * @param q Queue handle. 236 * @param cp Peer.
314 * @param sent #GNUNET_YES if was sent to CORE, #GNUNET_NO if dropped. 237 * @return Static string for it's ID.
315 */ 238 */
316static void 239const char *
317call_peer_cont (struct CadetPeerQueue *q, int sent); 240GCP_2s (const struct CadetPeer *cp)
241{
242 static char buf[32];
243
244 GNUNET_snprintf (buf,
245 sizeof (buf),
246 "P(%s)",
247 GNUNET_i2s (&cp->pid));
248 return buf;
249}
250
251
252/**
253 * Calculate how desirable a path is for @a cp if @a cp
254 * is at offset @a off.
255 *
256 * The 'desirability_table.c' program can be used to compute a list of
257 * sample outputs for different scenarios. Basically, we score paths
258 * lower if there are many alternatives, and higher if they are
259 * shorter than average, and very high if they are much shorter than
260 * average and without many alternatives.
261 *
262 * @param cp a peer reachable via a path
263 * @param off offset of @a cp in the path
264 * @return score how useful a path is to reach @a cp,
265 * positive scores mean path is more desirable
266 */
267double
268GCP_get_desirability_of_path (struct CadetPeer *cp,
269 unsigned int off)
270{
271 unsigned int num_alts = cp->num_paths;
272 unsigned int off_sum;
273 double avg_sum;
274 double path_delta;
275 double weight_alts;
276
277 GNUNET_assert (num_alts >= 1); /* 'path' should be in there! */
278 GNUNET_assert (0 != cp->path_dll_length);
279
280 /* We maintain 'off_sum' in 'peer' and thereby
281 avoid the SLOW recalculation each time. Kept here
282 just to document what is going on. */
283#if SLOW
284 off_sum = 0;
285 for (unsigned int j=0;j<cp->path_dll_length;j++)
286 for (struct CadetPeerPathEntry *pe = cp->path_heads[j];
287 NULL != pe;
288 pe = pe->next)
289 off_sum += j;
290 GNUNET_assert (off_sum == cp->off_sum);
291#else
292 off_sum = cp->off_sum;
293#endif
294 avg_sum = off_sum * 1.0 / cp->path_dll_length;
295 path_delta = off - avg_sum;
296 /* path_delta positiv: path off of peer above average (bad path for peer),
297 path_delta negativ: path off of peer below average (good path for peer) */
298 if (path_delta <= - 1.0)
299 weight_alts = - num_alts / path_delta; /* discount alternative paths */
300 else if (path_delta >= 1.0)
301 weight_alts = num_alts * path_delta; /* overcount alternative paths */
302 else
303 weight_alts = num_alts; /* count alternative paths normally */
318 304
319 305
320/******************************************************************************/ 306 /* off+1: long paths are generally harder to find and thus count
321/***************************** CORE CALLBACKS *********************************/ 307 a bit more as they get longer. However, above-average paths
322/******************************************************************************/ 308 still need to count less, hence the squaring of that factor. */
309 return (off + 1.0) / (weight_alts * weight_alts);
310}
323 311
324 312
325/** 313/**
326 * Method called whenever a given peer connects. 314 * This peer is no longer be needed, clean it up now.
327 * 315 *
328 * @param cls Core closure (unused). 316 * @param cls peer to clean up
329 * @param peer Peer identity this notification is about
330 * @param mq Message Queue to this peer.
331 *
332 * @return Internal closure for handlers (CadetPeer struct).
333 */ 317 */
334static void * 318static void
335core_connect_handler (void *cls, 319destroy_peer (void *cls)
336 const struct GNUNET_PeerIdentity *peer, 320{
337 struct GNUNET_MQ_Handle *mq) 321 struct CadetPeer *cp = cls;
338{ 322
339 struct CadetPeer *neighbor; 323 LOG (GNUNET_ERROR_TYPE_DEBUG,
340 struct CadetPeerPath *path; 324 "Destroying state about peer %s\n",
341 char own_id[16]; 325 GCP_2s (cp));
342 326 cp->destroy_task = NULL;
343 GCC_check_connections (); 327 GNUNET_assert (NULL == cp->t);
344 GNUNET_snprintf (own_id, 328 GNUNET_assert (NULL == cp->core_mq);
345 sizeof (own_id), 329 GNUNET_assert (0 == cp->num_paths);
346 "%s", 330 for (unsigned int i=0;i<cp->path_dll_length;i++)
347 GNUNET_i2s (&my_full_id)); 331 GNUNET_assert (NULL == cp->path_heads[i]);
348 332 GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections));
349 /* Save a path to the neighbor */ 333 GNUNET_assert (GNUNET_YES ==
350 neighbor = GCP_get (peer, GNUNET_YES); 334 GNUNET_CONTAINER_multipeermap_remove (peers,
351 if (myid == neighbor->id) 335 &cp->pid,
352 { 336 cp));
353 LOG (GNUNET_ERROR_TYPE_INFO, 337 GNUNET_free_non_null (cp->path_heads);
354 "CONNECTED %s (self)\n", 338 GNUNET_free_non_null (cp->path_tails);
355 own_id); 339 cp->path_dll_length = 0;
356 path = path_new (1); 340 if (NULL != cp->search_h)
357 } 341 {
358 else 342 GCD_search_stop (cp->search_h);
359 { 343 cp->search_h = NULL;
360 LOG (GNUNET_ERROR_TYPE_INFO, 344 }
361 "CONNECTED %s <= %s\n", 345 /* FIXME: clean up search_delayedXXX! */
362 own_id,
363 GNUNET_i2s (peer));
364 path = path_new (2);
365 path->peers[1] = neighbor->id;
366 GNUNET_PEER_change_rc (neighbor->id, 1);
367 GNUNET_assert (NULL == neighbor->core_mq);
368 neighbor->core_mq = mq;
369 }
370 path->peers[0] = myid;
371 GNUNET_PEER_change_rc (myid, 1);
372 GCP_add_path (neighbor, path, GNUNET_YES);
373
374 /* Create the connections hashmap */
375 GNUNET_assert (NULL == neighbor->connections);
376 neighbor->connections = GNUNET_CONTAINER_multishortmap_create (16,
377 GNUNET_YES);
378 GNUNET_STATISTICS_update (stats,
379 "# peers",
380 1,
381 GNUNET_NO);
382
383 if ( (NULL != GCP_get_tunnel (neighbor)) &&
384 (0 > GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, peer)) )
385 {
386 GCP_connect (neighbor);
387 }
388 GCC_check_connections ();
389 346
390 return neighbor; 347 if (NULL != cp->hello_offer)
348 {
349 GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
350 cp->hello_offer = NULL;
351 }
352 if (NULL != cp->connectivity_suggestion)
353 {
354 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
355 cp->connectivity_suggestion = NULL;
356 }
357 GNUNET_CONTAINER_multishortmap_destroy (cp->connections);
358 if (NULL != cp->path_heap)
359 {
360 GNUNET_CONTAINER_heap_destroy (cp->path_heap);
361 cp->path_heap = NULL;
362 }
363 if (NULL != cp->heap_cleanup_task)
364 {
365 GNUNET_SCHEDULER_cancel (cp->heap_cleanup_task);
366 cp->heap_cleanup_task = NULL;
367 }
368 GNUNET_free_non_null (cp->hello);
369 /* Peer should not be freed if paths exist; if there are no paths,
370 there ought to be no connections, and without connections, no
371 notifications. Thus we can assert that mqm_head is empty at this
372 point. */
373 GNUNET_assert (NULL == cp->mqm_head);
374 GNUNET_assert (NULL == cp->mqm_ready_ptr);
375 GNUNET_free (cp);
391} 376}
392 377
393 378
394/** 379/**
395 * Method called whenever a peer disconnects. 380 * This peer is now on more "active" duty, activate processes related to it.
396 * 381 *
397 * @param cls Core closure (unused). 382 * @param cp the more-active peer
398 * @param peer Peer identity this notification is about.
399 * @param internal_cls Internal closure (CadetPeer struct).
400 */ 383 */
401static void 384static void
402core_disconnect_handler (void *cls, 385consider_peer_activate (struct CadetPeer *cp)
403 const struct GNUNET_PeerIdentity *peer,
404 void *internal_cls)
405{ 386{
406 struct CadetPeer *p = internal_cls; 387 uint32_t strength;
407 struct CadetPeerPath *direct_path; 388
408 char own_id[16]; 389 LOG (GNUNET_ERROR_TYPE_DEBUG,
409 390 "Updating peer %s activation state (%u connections)%s%s\n",
410 GCC_check_connections (); 391 GCP_2s (cp),
411 strncpy (own_id, GNUNET_i2s (&my_full_id), 16); 392 GNUNET_CONTAINER_multishortmap_size (cp->connections),
412 own_id[15] = '\0'; 393 (NULL == cp->t) ? "" : " with tunnel",
413 if (myid == p->id) 394 (NULL == cp->core_mq) ? "" : " with CORE link");
414 { 395 if (NULL != cp->destroy_task)
415 LOG (GNUNET_ERROR_TYPE_INFO, 396 {
416 "DISCONNECTED %s (self)\n", 397 /* It's active, do not destory! */
417 own_id); 398 GNUNET_SCHEDULER_cancel (cp->destroy_task);
418 } 399 cp->destroy_task = NULL;
419 else 400 }
401 if ( (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)) &&
402 (NULL == cp->t) )
403 {
404 /* We're just on a path or directly connected; don't bother too much */
405 if (NULL != cp->connectivity_suggestion)
420 { 406 {
421 LOG (GNUNET_ERROR_TYPE_INFO, 407 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
422 "DISCONNECTED %s <= %s\n", 408 cp->connectivity_suggestion = NULL;
423 own_id, GNUNET_i2s (peer));
424 p->core_mq = NULL;
425 } 409 }
426 direct_path = pop_direct_path (p); 410 if (NULL != cp->search_h)
427 if (NULL != p->connections)
428 { 411 {
429 GNUNET_CONTAINER_multishortmap_iterate (p->connections, 412 GCD_search_stop (cp->search_h);
430 &notify_broken, 413 cp->search_h = NULL;
431 p);
432 GNUNET_CONTAINER_multishortmap_destroy (p->connections);
433 p->connections = NULL;
434 } 414 }
435 GNUNET_STATISTICS_update (stats, 415 return;
436 "# peers", 416 }
437 -1, 417 if (NULL == cp->core_mq)
438 GNUNET_NO); 418 {
439 path_destroy (direct_path); 419 /* Lacks direct connection, try to create one by querying the DHT */
440 GCC_check_connections (); 420 if ( (NULL == cp->search_h) &&
441} 421 (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) )
442 422 cp->search_h
443 423 = GCD_search (&cp->pid);
444/******************************************************************************/ 424 }
445/******************************************************************************/ 425 else
446/******************************************************************************/ 426 {
447/******************************************************************************/ 427 /* Have direct connection, stop DHT search if active */
448/******************************************************************************/ 428 if (NULL != cp->search_h)
449
450/**
451 * Check if the create_connection message has the appropriate size.
452 *
453 * @param cls Closure (unused).
454 * @param msg Message to check.
455 *
456 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
457 */
458static int
459check_create (void *cls, const struct GNUNET_CADET_ConnectionCreateMessage *msg)
460{
461 uint16_t size;
462
463 size = ntohs (msg->header.size);
464 if (size < sizeof (*msg))
465 { 429 {
466 GNUNET_break_op (0); 430 GCD_search_stop (cp->search_h);
467 return GNUNET_NO; 431 cp->search_h = NULL;
468 } 432 }
469 return GNUNET_YES; 433 }
470}
471
472/**
473 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE
474 *
475 * @param cls Closure (CadetPeer for neighbor that sent the message).
476 * @param msg Message itself.
477 */
478static void
479handle_create (void *cls, const struct GNUNET_CADET_ConnectionCreateMessage *msg)
480{
481 struct CadetPeer *peer = cls;
482 GCC_handle_create (peer, msg);
483}
484
485
486/**
487 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK
488 *
489 * @param cls Closure (CadetPeer for neighbor that sent the message).
490 * @param msg Message itself.
491 */
492static void
493handle_confirm (void *cls, const struct GNUNET_CADET_ConnectionCreateAckMessage *msg)
494{
495 struct CadetPeer *peer = cls;
496 GCC_handle_confirm (peer, msg);
497}
498
499 434
500/** 435 /* If we have a tunnel, our urge for connections is much bigger */
501 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN 436 strength = (NULL != cp->t) ? 32 : 1;
502 * 437 if (NULL != cp->connectivity_suggestion)
503 * @param cls Closure (CadetPeer for neighbor that sent the message). 438 GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion);
504 * @param msg Message itself. 439 cp->connectivity_suggestion
505 */ 440 = GNUNET_ATS_connectivity_suggest (ats_ch,
506static void 441 &cp->pid,
507handle_broken (void *cls, const struct GNUNET_CADET_ConnectionBrokenMessage *msg) 442 strength);
508{
509 struct CadetPeer *peer = cls;
510 GCC_handle_broken (peer, msg);
511} 443}
512 444
513 445
514/** 446/**
515 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY 447 * This peer may no longer be needed, consider cleaning it up.
516 * 448 *
517 * @param cls Closure (CadetPeer for neighbor that sent the message). 449 * @param cp peer to clean up
518 * @param msg Message itself.
519 */ 450 */
520static void 451static void
521handle_destroy (void *cls, const struct GNUNET_CADET_ConnectionDestroyMessage *msg) 452consider_peer_destroy (struct CadetPeer *cp);
522{
523 struct CadetPeer *peer = cls;
524 GCC_handle_destroy (peer, msg);
525}
526 453
527 454
528/** 455/**
529 * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK 456 * We really no longere care about a peer, stop hogging memory with paths to it.
457 * Afterwards, see if there is more to be cleaned up about this peer.
530 * 458 *
531 * @param cls Closure (CadetPeer for neighbor that sent the message). 459 * @param cls a `struct CadetPeer`.
532 * @param msg Message itself.
533 */ 460 */
534static void 461static void
535handle_ack (void *cls, const struct GNUNET_CADET_ConnectionEncryptedAckMessage *msg) 462drop_paths (void *cls)
536{ 463{
537 struct CadetPeer *peer = cls; 464 struct CadetPeer *cp = cls;
538 GCC_handle_ack (peer, msg); 465 struct CadetPeerPath *path;
539}
540 466
541 467 cp->destroy_task = NULL;
542/** 468 while (NULL != (path = GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
543 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL 469 GCPP_release (path);
544 * 470 consider_peer_destroy (cp);
545 * @param cls Closure (CadetPeer for neighbor that sent the message).
546 * @param msg Message itself.
547 */
548static void
549handle_poll (void *cls, const struct GNUNET_CADET_ConnectionHopByHopPollMessage *msg)
550{
551 struct CadetPeer *peer = cls;
552 GCC_handle_poll (peer, msg);
553} 471}
554 472
555 473
556/** 474/**
557 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX 475 * This peer may no longer be needed, consider cleaning it up.
558 * 476 *
559 * @param cls Closure (CadetPeer for neighbor that sent the message). 477 * @param cp peer to clean up
560 * @param msg Message itself.
561 */ 478 */
562static void 479static void
563handle_kx (void *cls, const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg) 480consider_peer_destroy (struct CadetPeer *cp)
564{
565 struct CadetPeer *peer = cls;
566 GCC_handle_kx (peer, msg);
567}
568
569
570/**
571 * Check if the encrypted message has the appropriate size.
572 *
573 * @param cls Closure (unused).
574 * @param msg Message to check.
575 *
576 * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
577 */
578static int
579check_encrypted (void *cls, const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
580{ 481{
581 uint16_t size; 482 struct GNUNET_TIME_Relative exp;
582 uint16_t minimum_size;
583
584 size = ntohs (msg->header.size);
585 minimum_size = sizeof (struct GNUNET_CADET_TunnelEncryptedMessage)
586 + sizeof (struct GNUNET_MessageHeader);
587
588 if (size < minimum_size)
589 {
590 GNUNET_break_op (0);
591 return GNUNET_NO;
592 }
593 return GNUNET_YES;
594}
595 483
596/** 484 if (NULL != cp->destroy_task)
597 * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED. 485 {
598 * 486 GNUNET_SCHEDULER_cancel (cp->destroy_task);
599 * @param cls Closure (CadetPeer for neighbor that sent the message). 487 cp->destroy_task = NULL;
600 * @param msg Message itself. 488 }
601 */ 489 if (NULL != cp->t)
602static void 490 return; /* still relevant! */
603handle_encrypted (void *cls, const struct GNUNET_CADET_TunnelEncryptedMessage *msg) 491 if (NULL != cp->core_mq)
604{ 492 return; /* still relevant! */
605 struct CadetPeer *peer = cls; 493 if (0 != GNUNET_CONTAINER_multishortmap_size (cp->connections))
606 GCC_handle_encrypted (peer, msg); 494 return; /* still relevant! */
607} 495 if ( (NULL != cp->path_heap) &&
608 496 (0 < GNUNET_CONTAINER_heap_get_size (cp->path_heap)) )
609 497 {
610/** 498 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PATH_TIMEOUT,
611 * To be called on core init/fail. 499 &drop_paths,
612 * 500 cp);
613 * @param cls Closure (config) 501 return;
614 * @param identity The public identity of this peer. 502 }
615 */ 503 if (0 != cp->num_paths)
616static void 504 return; /* still relevant! */
617core_init_notify (void *cls, 505 if (NULL != cp->hello)
618 const struct GNUNET_PeerIdentity *identity); 506 {
619 507 /* relevant only until HELLO expires */
620 508 exp = GNUNET_TIME_absolute_get_remaining (GNUNET_HELLO_get_last_expiration (cp->hello));
621static void 509 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (exp,
622connect_to_core (const struct GNUNET_CONFIGURATION_Handle *c) 510 &destroy_peer,
623{ 511 cp);
624 struct GNUNET_MQ_MessageHandler core_handlers[] = { 512 return;
625 GNUNET_MQ_hd_var_size (create, 513 }
626 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE, 514 cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PEER_TIMEOUT,
627 struct GNUNET_CADET_ConnectionCreateMessage, 515 &destroy_peer,
628 NULL), 516 cp);
629 GNUNET_MQ_hd_fixed_size (confirm,
630 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK,
631 struct GNUNET_CADET_ConnectionCreateAckMessage,
632 NULL),
633 GNUNET_MQ_hd_fixed_size (broken,
634 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN,
635 struct GNUNET_CADET_ConnectionBrokenMessage,
636 NULL),
637 GNUNET_MQ_hd_fixed_size (destroy,
638 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY,
639 struct GNUNET_CADET_ConnectionDestroyMessage,
640 NULL),
641 GNUNET_MQ_hd_fixed_size (ack,
642 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK,
643 struct GNUNET_CADET_ConnectionEncryptedAckMessage,
644 NULL),
645 GNUNET_MQ_hd_fixed_size (poll,
646 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL,
647 struct GNUNET_CADET_ConnectionHopByHopPollMessage,
648 NULL),
649 GNUNET_MQ_hd_fixed_size (kx,
650 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX,
651 struct GNUNET_CADET_TunnelKeyExchangeMessage,
652 NULL),
653 GNUNET_MQ_hd_var_size (encrypted,
654 GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED,
655 struct GNUNET_CADET_TunnelEncryptedMessage,
656 NULL),
657 GNUNET_MQ_handler_end ()
658 };
659 core_handle = GNUNET_CORE_connect (c, NULL,
660 &core_init_notify,
661 &core_connect_handler,
662 &core_disconnect_handler,
663 core_handlers);
664}
665
666/******************************************************************************/
667/******************************************************************************/
668/******************************************************************************/
669/******************************************************************************/
670/******************************************************************************/
671
672/**
673 * To be called on core init/fail.
674 *
675 * @param cls Closure (config)
676 * @param identity The public identity of this peer.
677 */
678static void
679core_init_notify (void *cls,
680 const struct GNUNET_PeerIdentity *core_identity)
681{
682 const struct GNUNET_CONFIGURATION_Handle *c = cls;
683
684 LOG (GNUNET_ERROR_TYPE_DEBUG, "Core init\n");
685 if (0 != memcmp (core_identity, &my_full_id, sizeof (my_full_id)))
686 {
687 LOG (GNUNET_ERROR_TYPE_ERROR, _("Wrong CORE service\n"));
688 LOG (GNUNET_ERROR_TYPE_ERROR, " core id %s\n", GNUNET_i2s (core_identity));
689 LOG (GNUNET_ERROR_TYPE_ERROR, " my id %s\n", GNUNET_i2s (&my_full_id));
690 GNUNET_CORE_disconnect (core_handle);
691 connect_to_core (c);
692 return;
693 }
694 GML_start ();
695} 517}
696 518
697 519
698/******************************************************************************/
699/******************************** STATIC ***********************************/
700/******************************************************************************/
701
702
703/** 520/**
704 * Get priority for a queued message. 521 * Set the message queue to @a mq for peer @a cp and notify watchers.
705 *
706 * @param q Queued message
707 *
708 * @return CORE priority to use.
709 * 522 *
710 * FIXME make static 523 * @param cp peer to modify
711 * FIXME use when sending 524 * @param mq message queue to set (can be NULL)
712 */ 525 */
713enum GNUNET_CORE_Priority 526void
714get_priority (struct CadetPeerQueue *q) 527GCP_set_mq (struct CadetPeer *cp,
715{ 528 struct GNUNET_MQ_Handle *mq)
716 enum GNUNET_CORE_Priority low; 529{
717 enum GNUNET_CORE_Priority high; 530 LOG (GNUNET_ERROR_TYPE_DEBUG,
718 531 "Message queue for peer %s is now %p\n",
719 if (NULL == q) 532 GCP_2s (cp),
720 { 533 mq);
721 GNUNET_break (0); 534 cp->core_mq = mq;
722 return GNUNET_CORE_PRIO_BACKGROUND; 535 for (struct GCP_MessageQueueManager *mqm = cp->mqm_head, *next;
723 } 536 NULL != mqm;
724 537 mqm = next)
725 /* Relayed traffic has lower priority, our own traffic has higher */ 538 {
726 if (NULL == q->c || GNUNET_NO == GCC_is_origin (q->c, q->c_fwd)) 539 /* Save next pointer in case mqm gets freed by the callback */
540 next = mqm->next;
541 if (NULL == mq)
727 { 542 {
728 low = GNUNET_CORE_PRIO_BEST_EFFORT; 543 if (NULL != mqm->env)
729 high = GNUNET_CORE_PRIO_URGENT; 544 {
545 GNUNET_MQ_discard (mqm->env);
546 mqm->env = NULL;
547 mqm->cb (mqm->cb_cls,
548 GNUNET_SYSERR);
549 }
550 else
551 {
552 mqm->cb (mqm->cb_cls,
553 GNUNET_NO);
554 }
730 } 555 }
731 else 556 else
732 { 557 {
733 low = GNUNET_CORE_PRIO_URGENT; 558 GNUNET_assert (NULL == mqm->env);
734 high = GNUNET_CORE_PRIO_CRITICAL_CONTROL; 559 mqm->cb (mqm->cb_cls,
560 GNUNET_YES);
735 } 561 }
562 }
563 if ( (NULL != mq) ||
564 (NULL != cp->t) )
565 consider_peer_activate (cp);
566 else
567 consider_peer_destroy (cp);
736 568
737 /* Bulky payload has lower priority, control traffic has higher. */ 569 if ( (NULL != mq) &&
738 if (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED == q->type) 570 (NULL != cp->t) )
739 return low; 571 {
740 return high; 572 /* have a new, direct path to the target, notify tunnel */
741} 573 struct CadetPeerPath *path;
742
743
744/**
745 * Cancel all messages queued to CORE MQ towards this peer.
746 *
747 * @param peer Peer towards which to cancel all messages.
748 */
749static void
750cancel_queued_messages (struct CadetPeer *peer)
751{
752 while (NULL != peer->q_head)
753 {
754 struct CadetPeerQueue *q;
755
756 q = peer->q_head;
757 call_peer_cont (q, GNUNET_NO);
758 GNUNET_free (q);
759 }
760}
761
762
763/**
764 * Destroy the peer_info and free any allocated resources linked to it
765 *
766 * @param peer The peer_info to destroy.
767 * @return #GNUNET_OK on success
768 */
769static int
770peer_destroy (struct CadetPeer *peer)
771{
772 struct GNUNET_PeerIdentity id;
773 struct CadetPeerPath *p;
774 struct CadetPeerPath *nextp;
775
776 GNUNET_PEER_resolve (peer->id, &id);
777 GNUNET_PEER_change_rc (peer->id, -1);
778
779 LOG (GNUNET_ERROR_TYPE_INFO,
780 "destroying peer %s\n",
781 GNUNET_i2s (&id));
782
783 if (GNUNET_YES !=
784 GNUNET_CONTAINER_multipeermap_remove (peers, &id, peer))
785 {
786 GNUNET_break (0);
787 LOG (GNUNET_ERROR_TYPE_WARNING, " peer not in peermap!!\n");
788 }
789 GCP_stop_search (peer);
790 p = peer->path_head;
791 while (NULL != p)
792 {
793 nextp = p->next;
794 GNUNET_CONTAINER_DLL_remove (peer->path_head,
795 peer->path_tail,
796 p);
797 path_destroy (p);
798 p = nextp;
799 }
800 if (NULL != peer->tunnel)
801 GCT_destroy_empty (peer->tunnel);
802 if (NULL != peer->connections)
803 {
804 GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (peer->connections));
805 GNUNET_CONTAINER_multishortmap_destroy (peer->connections);
806 peer->connections = NULL;
807 }
808 if (NULL != peer->hello_offer)
809 {
810 GNUNET_TRANSPORT_offer_hello_cancel (peer->hello_offer);
811 peer->hello_offer = NULL;
812 }
813 if (NULL != peer->connectivity_suggestion)
814 {
815 GNUNET_ATS_connectivity_suggest_cancel (peer->connectivity_suggestion);
816 peer->connectivity_suggestion = NULL;
817 }
818 cancel_queued_messages (peer);
819 574
820 GNUNET_free_non_null (peer->hello); 575 path = GCPP_get_path_from_route (1,
821 GNUNET_free (peer); 576 &cp->pid);
822 return GNUNET_OK; 577 GCT_consider_path (cp->t,
578 path,
579 0);
580 }
823} 581}
824 582
825 583
826/** 584/**
827 * Iterator over peer hash map entries to destroy the peer during in_shutdown. 585 * Debug function should NEVER return true in production code, useful to
586 * simulate losses for testcases.
828 * 587 *
829 * @param cls closure 588 * @return #GNUNET_YES or #GNUNET_NO with the decision to drop.
830 * @param key current key code
831 * @param value value in the hash map
832 * @return #GNUNET_YES if we should continue to iterate,
833 * #GNUNET_NO if not.
834 */ 589 */
835static int 590static int
836shutdown_peer (void *cls, 591should_I_drop (void)
837 const struct GNUNET_PeerIdentity *key,
838 void *value)
839{ 592{
840 struct CadetPeer *p = value; 593 if (0 == drop_percent)
841 struct CadetTunnel *t = p->tunnel; 594 return GNUNET_NO;
842 595 if (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
843 LOG (GNUNET_ERROR_TYPE_DEBUG, " shutting down %s\n", GCP_2s (p)); 596 101) < drop_percent)
844 if (NULL != t)
845 GCT_destroy (t);
846 p->tunnel = NULL;
847 peer_destroy (p);
848 return GNUNET_YES; 597 return GNUNET_YES;
598 return GNUNET_NO;
849} 599}
850 600
851 601
852/** 602/**
853 * Check if peer is searching for a path (either active or delayed search). 603 * Function called when CORE took one of the messages from
854 * 604 * a message queue manager and transmitted it.
855 * @param peer Peer to check
856 * @return #GNUNET_YES if there is a search active.
857 * #GNUNET_NO otherwise.
858 */
859static int
860is_searching (const struct CadetPeer *peer)
861{
862 return ( (NULL == peer->search_h) &&
863 (NULL == peer->search_delayed) ) ?
864 GNUNET_NO : GNUNET_YES;
865}
866
867
868/**
869 * @brief Start a search for a peer.
870 * 605 *
871 * @param cls Closure (Peer to search for). 606 * @param cls the `struct CadetPeeer` where we made progress
872 */ 607 */
873static void 608static void
874delayed_search (void *cls) 609mqm_send_done (void *cls);
875{
876 struct CadetPeer *peer = cls;
877
878 peer->search_delayed = NULL;
879 GCC_check_connections ();
880 GCP_start_search (peer);
881 GCC_check_connections ();
882}
883 610
884 611
885/** 612/**
886 * Returns if peer is used (has a tunnel or is neighbor). 613 * Transmit current envelope from this @a mqm.
887 * 614 *
888 * @param peer Peer to check. 615 * @param mqm mqm to transmit message for now
889 * @return #GNUNET_YES if peer is in use.
890 */ 616 */
891static int 617static void
892peer_is_used (struct CadetPeer *peer) 618mqm_execute (struct GCP_MessageQueueManager *mqm)
893{
894 struct CadetPeerPath *p;
895
896 if (NULL != peer->tunnel)
897 return GNUNET_YES;
898
899 for (p = peer->path_head; NULL != p; p = p->next)
900 {
901 if (p->length < 3)
902 return GNUNET_YES;
903 }
904 return GNUNET_NO;
905}
906
907
908/**
909 * Iterator over all the peers to get the oldest timestamp.
910 *
911 * @param cls Closure (unsued).
912 * @param key ID of the peer.
913 * @param value Peer_Info of the peer.
914 */
915static int
916peer_get_oldest (void *cls,
917 const struct GNUNET_PeerIdentity *key,
918 void *value)
919{ 619{
920 struct CadetPeer *p = value; 620 struct CadetPeer *cp = mqm->cp;
921 struct GNUNET_TIME_Absolute *abs = cls;
922
923 /* Don't count active peers */
924 if (GNUNET_YES == peer_is_used (p))
925 return GNUNET_YES;
926 621
927 if (abs->abs_value_us < p->last_contact.abs_value_us) 622 /* Move ready pointer to the next entry that might be ready. */
928 abs->abs_value_us = p->last_contact.abs_value_us; 623 if ( (mqm == cp->mqm_ready_ptr) &&
929 624 (NULL != mqm->next) )
930 return GNUNET_YES; 625 cp->mqm_ready_ptr = mqm->next;
626 /* Move entry to the end of the DLL, to be fair. */
627 if (mqm != cp->mqm_tail)
628 {
629 GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
630 cp->mqm_tail,
631 mqm);
632 GNUNET_CONTAINER_DLL_insert_tail (cp->mqm_head,
633 cp->mqm_tail,
634 mqm);
635 }
636 cp->mqm_ready_counter--;
637 if (GNUNET_YES == should_I_drop ())
638 {
639 LOG (GNUNET_ERROR_TYPE_DEBUG,
640 "DROPPING message to peer %s from MQM %p\n",
641 GCP_2s (cp),
642 mqm);
643 GNUNET_MQ_discard (mqm->env);
644 mqm->env = NULL;
645 mqm_send_done (cp);
646 }
647 else
648 {
649 LOG (GNUNET_ERROR_TYPE_DEBUG,
650 "Sending to peer %s from MQM %p\n",
651 GCP_2s (cp),
652 mqm);
653 GNUNET_MQ_send (cp->core_mq,
654 mqm->env);
655 mqm->env = NULL;
656 }
657 mqm->cb (mqm->cb_cls,
658 GNUNET_YES);
931} 659}
932 660
933 661
934/** 662/**
935 * Iterator over all the peers to remove the oldest entry. 663 * Find the next ready message in the queue (starting
664 * the search from the `cp->mqm_ready_ptr`) and if possible
665 * execute the transmission.
936 * 666 *
937 * @param cls Closure (unsued). 667 * @param cp peer to try to send the next ready message to
938 * @param key ID of the peer.
939 * @param value Peer_Info of the peer.
940 */
941static int
942peer_timeout (void *cls,
943 const struct GNUNET_PeerIdentity *key,
944 void *value)
945{
946 struct CadetPeer *p = value;
947 struct GNUNET_TIME_Absolute *abs = cls;
948
949 LOG (GNUNET_ERROR_TYPE_WARNING,
950 "peer %s timeout\n", GNUNET_i2s (key));
951
952 if (p->last_contact.abs_value_us == abs->abs_value_us &&
953 GNUNET_NO == peer_is_used (p))
954 {
955 peer_destroy (p);
956 return GNUNET_NO;
957 }
958 return GNUNET_YES;
959}
960
961
962/**
963 * Delete oldest unused peer.
964 */ 668 */
965static void 669static void
966peer_delete_oldest (void) 670send_next_ready (struct CadetPeer *cp)
967{ 671{
968 struct GNUNET_TIME_Absolute abs; 672 struct GCP_MessageQueueManager *mqm;
969
970 abs = GNUNET_TIME_UNIT_FOREVER_ABS;
971
972 GNUNET_CONTAINER_multipeermap_iterate (peers,
973 &peer_get_oldest,
974 &abs);
975 GNUNET_CONTAINER_multipeermap_iterate (peers,
976 &peer_timeout,
977 &abs);
978}
979
980 673
981/** 674 if (0 == cp->mqm_ready_counter)
982 * Choose the best (yet unused) path towards a peer, 675 return;
983 * considering the tunnel properties. 676 while ( (NULL != (mqm = cp->mqm_ready_ptr)) &&
984 * 677 (NULL == mqm->env) )
985 * @param peer The destination peer. 678 cp->mqm_ready_ptr = mqm->next;
986 * @return Best current known path towards the peer, if any. 679 if (NULL == mqm)
987 */ 680 return; /* nothing to do */
988static struct CadetPeerPath * 681 mqm_execute (mqm);
989peer_get_best_path (const struct CadetPeer *peer)
990{
991 struct CadetPeerPath *best_p;
992 struct CadetPeerPath *p;
993 unsigned int best_cost;
994 unsigned int cost;
995
996 best_cost = UINT_MAX;
997 best_p = NULL;
998 for (p = peer->path_head; NULL != p; p = p->next)
999 {
1000 if (GNUNET_NO == path_is_valid (p))
1001 continue; /* Don't use invalid paths. */
1002 if (GNUNET_YES == GCT_is_path_used (peer->tunnel, p))
1003 continue; /* If path is already in use, skip it. */
1004
1005 if ((cost = GCT_get_path_cost (peer->tunnel, p)) < best_cost)
1006 {
1007 best_cost = cost;
1008 best_p = p;
1009 }
1010 }
1011 return best_p;
1012} 682}
1013 683
1014 684
1015/** 685/**
1016 * Function to process paths received for a new peer addition. The recorded 686 * Function called when CORE took one of the messages from
1017 * paths form the initial tunnel, which can be optimized later. 687 * a message queue manager and transmitted it.
1018 * Called on each result obtained for the DHT search.
1019 * 688 *
1020 * @param cls Closure (peer towards a path has been found). 689 * @param cls the `struct CadetPeeer` where we made progress
1021 * @param path Path created from the DHT query. Will be freed afterwards.
1022 */ 690 */
1023static void 691static void
1024search_handler (void *cls, const struct CadetPeerPath *path) 692mqm_send_done (void *cls)
1025{ 693{
1026 struct CadetPeer *peer = cls; 694 struct CadetPeer *cp = cls;
1027 unsigned int connection_count;
1028
1029 GCC_check_connections ();
1030 GCP_add_path_to_all (path, GNUNET_NO);
1031
1032 /* Count connections */
1033 connection_count = GCT_count_connections (peer->tunnel);
1034 695
1035 /* If we already have our minimum (or more) connections, it's enough */ 696 LOG (GNUNET_ERROR_TYPE_DEBUG,
1036 if (CONNECTIONS_PER_TUNNEL <= connection_count) 697 "Sending to peer %s completed\n",
1037 { 698 GCP_2s (cp));
1038 GCC_check_connections (); 699 send_next_ready (cp);
1039 return;
1040 }
1041
1042 if (CADET_TUNNEL_SEARCHING == GCT_get_cstate (peer->tunnel))
1043 {
1044 LOG (GNUNET_ERROR_TYPE_DEBUG, " ... connect!\n");
1045 GCP_connect (peer);
1046 }
1047 GCC_check_connections ();
1048}
1049
1050
1051/**
1052 * Test if a message type is connection management traffic
1053 * or regular payload traffic.
1054 *
1055 * @param type Message type.
1056 *
1057 * @return #GNUNET_YES if connection management, #GNUNET_NO otherwise.
1058 */
1059static int
1060is_connection_management (uint16_t type)
1061{
1062 return type == GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK ||
1063 type == GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL;
1064} 700}
1065 701
1066 702
1067/** 703/**
1068 * Debug function should NEVER return true in production code, useful to 704 * Send the message in @a env to @a cp.
1069 * simulate losses for testcases.
1070 * 705 *
1071 * @return #GNUNET_YES or #GNUNET_NO with the decision to drop. 706 * @param mqm the message queue manager to use for transmission
707 * @param env envelope with the message to send; must NOT
708 * yet have a #GNUNET_MQ_notify_sent() callback attached to it
1072 */ 709 */
1073static int 710void
1074should_I_drop (void) 711GCP_send (struct GCP_MessageQueueManager *mqm,
712 struct GNUNET_MQ_Envelope *env)
1075{ 713{
1076 if (0 == drop_percent) 714 struct CadetPeer *cp = mqm->cp;
1077 return GNUNET_NO;
1078 715
1079 if (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 101) < drop_percent) 716 GNUNET_assert (NULL != env);
1080 return GNUNET_YES; 717 LOG (GNUNET_ERROR_TYPE_DEBUG,
1081 718 "Queueing message to peer %s in MQM %p\n",
1082 return GNUNET_NO; 719 GCP_2s (cp),
720 mqm);
721 GNUNET_assert (NULL != cp->core_mq);
722 GNUNET_assert (NULL == mqm->env);
723 GNUNET_MQ_notify_sent (env,
724 &mqm_send_done,
725 cp);
726 mqm->env = env;
727 cp->mqm_ready_counter++;
728 if (mqm != cp->mqm_ready_ptr)
729 cp->mqm_ready_ptr = cp->mqm_head;
730 if (1 == cp->mqm_ready_counter)
731 cp->mqm_ready_ptr = mqm;
732 if (0 != GNUNET_MQ_get_length (cp->core_mq))
733 return;
734 send_next_ready (cp);
1083} 735}
1084 736
1085 737
1086/******************************************************************************/
1087/******************************** API ***********************************/
1088/******************************************************************************/
1089
1090/** 738/**
1091 * Call the continuation after a message has been sent or dropped. 739 * Function called to destroy a peer now.
1092 * 740 *
1093 * This funcion removes the message from the queue. 741 * @param cls NULL
1094 * 742 * @param pid identity of the peer (unused)
1095 * @param q Queue handle. 743 * @param value the `struct CadetPeer` to clean up
1096 * @param sent #GNUNET_YES if was sent to CORE, #GNUNET_NO if dropped. 744 * @return #GNUNET_OK (continue to iterate)
1097 */ 745 */
1098static void 746static int
1099call_peer_cont (struct CadetPeerQueue *q, int sent) 747destroy_iterator_cb (void *cls,
1100{ 748 const struct GNUNET_PeerIdentity *pid,
1101 LOG (GNUNET_ERROR_TYPE_DEBUG, " core mq just sent %s\n", GC_m2s (q->type)); 749 void *value)
1102 if (NULL != q->cont)
1103 {
1104 struct GNUNET_TIME_Relative wait_time;
1105
1106 wait_time = GNUNET_TIME_absolute_get_duration (q->queue_timestamp);
1107 LOG (GNUNET_ERROR_TYPE_DEBUG,
1108 " calling callback on %s after %s\n",
1109 GCC_2s (q->c),
1110 GNUNET_STRINGS_relative_time_to_string (wait_time, GNUNET_NO));
1111 q->cont (q->cont_cls,
1112 q->c, q->c_fwd, sent,
1113 q->type,
1114 q->payload_type,
1115 q->payload_id,
1116 q->size, wait_time);
1117 q->cont = NULL;
1118 }
1119 GNUNET_CONTAINER_DLL_remove (q->peer->q_head, q->peer->q_tail, q);
1120}
1121
1122
1123/**
1124 * Function called by MQ when a message is sent to CORE.
1125 *
1126 * @param cls Closure (queue handle).
1127 */
1128static void
1129mq_sent (void *cls)
1130{ 750{
1131 struct CadetPeerQueue *q = cls; 751 struct CadetPeer *cp = value;
1132 752
1133 if (GNUNET_NO == q->management_traffic) 753 if (NULL != cp->destroy_task)
1134 { 754 {
1135 q->peer->queue_n--; 755 GNUNET_SCHEDULER_cancel (cp->destroy_task);
1136 } 756 cp->destroy_task = NULL;
1137 call_peer_cont (q, GNUNET_YES); 757 }
1138 GNUNET_free (q); 758 destroy_peer (cp);
759 return GNUNET_OK;
1139} 760}
1140 761
1141 762
1142/** 763/**
1143 * Finish the drop operation. 764 * Clean up all entries about all peers.
1144 * 765 * Must only be called after all tunnels, CORE-connections and
1145 * @param cls queue entry to finish drop for 766 * connections are down.
1146 */ 767 */
1147static void 768void
1148drop_cb (void *cls) 769GCP_destroy_all_peers ()
1149{ 770{
1150 struct CadetPeerQueue *q = cls; 771 LOG (GNUNET_ERROR_TYPE_DEBUG,
1151 772 "Destroying all peers now\n");
1152 GNUNET_MQ_discard (q->env); 773 GNUNET_CONTAINER_multipeermap_iterate (peers,
1153 call_peer_cont (q, GNUNET_YES); 774 &destroy_iterator_cb,
1154 GNUNET_free (q); 775 NULL);
1155} 776}
1156 777
1157 778
1158/** 779/**
1159 * @brief Send a message to another peer (using CORE). 780 * Drop all paths owned by this peer, and do not
781 * allow new ones to be added: We are shutting down.
1160 * 782 *
1161 * @param peer Peer towards which to queue the message. 783 * @param cp peer to drop paths to
1162 * @param message Message to send.
1163 * @param payload_type Type of the message's payload, for debug messages.
1164 * 0 if the message is a retransmission (unknown payload).
1165 * UINT16_MAX if the message does not have payload.
1166 * @param payload_id ID of the payload (MID, ACK #, etc)
1167 * @param c Connection this message belongs to (can be NULL).
1168 * @param fwd Is this a message going root->dest? (FWD ACK are NOT FWD!)
1169 * @param cont Continuation to be called once CORE has sent the message.
1170 * @param cont_cls Closure for @c cont.
1171 *
1172 * @return A handle to the message in the queue or NULL (if dropped).
1173 */ 784 */
1174struct CadetPeerQueue * 785void
1175GCP_send (struct CadetPeer *peer, 786GCP_drop_owned_paths (struct CadetPeer *cp)
1176 const struct GNUNET_MessageHeader *message,
1177 uint16_t payload_type,
1178 struct CadetEncryptedMessageIdentifier payload_id,
1179 struct CadetConnection *c,
1180 int fwd,
1181 GCP_sent cont,
1182 void *cont_cls)
1183{ 787{
1184 struct CadetPeerQueue *q; 788 struct CadetPeerPath *path;
1185 uint16_t type;
1186 uint16_t size;
1187
1188 GCC_check_connections ();
1189 type = ntohs (message->type);
1190 size = ntohs (message->size);
1191 LOG (GNUNET_ERROR_TYPE_DEBUG,
1192 "que %s (%s %4u) on conn %s (%p) %s towards %s (size %u)\n",
1193 GC_m2s (type), GC_m2s (payload_type),
1194 ntohl (payload_id.pid),
1195 GCC_2s (c), c, GC_f2s (fwd), GCP_2s (peer), size);
1196
1197 if (NULL == peer->connections)
1198 {
1199 /* We are not connected to this peer, ignore request. */
1200 GNUNET_break (0);
1201 LOG (GNUNET_ERROR_TYPE_INFO, "%s not a neighbor\n", GCP_2s (peer));
1202 GNUNET_STATISTICS_update (stats, "# messages dropped due to wrong hop", 1,
1203 GNUNET_NO);
1204 return NULL;
1205 }
1206 789
1207 q = GNUNET_new (struct CadetPeerQueue); 790 LOG (GNUNET_ERROR_TYPE_DEBUG,
1208 q->env = GNUNET_MQ_msg_copy (message); 791 "Destroying all paths to %s\n",
1209 q->peer = peer; 792 GCP_2s (cp));
1210 q->cont = cont; 793 while (NULL != (path =
1211 q->cont_cls = cont_cls; 794 GNUNET_CONTAINER_heap_remove_root (cp->path_heap)))
1212 q->queue_timestamp = GNUNET_TIME_absolute_get (); 795 GCPP_release (path);
1213 q->management_traffic = is_connection_management (type); 796 GNUNET_CONTAINER_heap_destroy (cp->path_heap);
1214 q->type = type; 797 cp->path_heap = NULL;
1215 q->size = size;
1216 q->payload_type = payload_type;
1217 q->payload_id = payload_id;
1218 q->c = c;
1219 q->c_fwd = fwd;
1220 GNUNET_MQ_notify_sent (q->env, &mq_sent, q);
1221 GNUNET_CONTAINER_DLL_insert (peer->q_head, peer->q_tail, q);
1222
1223 if (GNUNET_YES == q->management_traffic)
1224 {
1225 GNUNET_MQ_send (peer->core_mq, q->env); // FIXME implement "_urgent", use
1226 }
1227 else
1228 {
1229 if (GNUNET_YES == should_I_drop ())
1230 {
1231 LOG (GNUNET_ERROR_TYPE_WARNING,
1232 "DD %s (%s %u) on conn %s %s (random drop for testing)\n",
1233 GC_m2s (q->type),
1234 GC_m2s (q->payload_type),
1235 ntohl (q->payload_id.pid),
1236 GCC_2s (c),
1237 GC_f2s (q->c_fwd));
1238 q->drop_task = GNUNET_SCHEDULER_add_now (&drop_cb,
1239 q);
1240 return q;
1241 }
1242 GNUNET_MQ_send (peer->core_mq, q->env);
1243 peer->queue_n++;
1244 }
1245
1246 GCC_check_connections ();
1247 return q;
1248} 798}
1249 799
1250 800
1251/** 801/**
1252 * Cancel sending a message. Message must have been sent with 802 * Add an entry to the DLL of all of the paths that this peer is on.
1253 * #GCP_send before. May not be called after the notify sent
1254 * callback has been called.
1255 *
1256 * It DOES call the continuation given to #GCP_send.
1257 * 803 *
1258 * @param q Queue handle to cancel 804 * @param cp peer to modify
805 * @param entry an entry on a path
806 * @param off offset of this peer on the path
1259 */ 807 */
1260void 808void
1261GCP_send_cancel (struct CadetPeerQueue *q) 809GCP_path_entry_add (struct CadetPeer *cp,
1262{ 810 struct CadetPeerPathEntry *entry,
1263 if (NULL != q->drop_task) 811 unsigned int off)
812{
813 GNUNET_assert (cp == GCPP_get_peer_at_offset (entry->path,
814 off));
815 LOG (GNUNET_ERROR_TYPE_DEBUG,
816 "Discovered that peer %s is on path %s at offset %u\n",
817 GCP_2s (cp),
818 GCPP_2s (entry->path),
819 off);
820 if (off >= cp->path_dll_length)
1264 { 821 {
1265 GNUNET_SCHEDULER_cancel (q->drop_task); 822 unsigned int len = cp->path_dll_length;
1266 q->drop_task = NULL; 823
1267 GNUNET_MQ_discard (q->env); 824 GNUNET_array_grow (cp->path_heads,
825 len,
826 off + 4);
827 GNUNET_array_grow (cp->path_tails,
828 cp->path_dll_length,
829 off + 4);
1268 } 830 }
1269 else 831 GNUNET_CONTAINER_DLL_insert (cp->path_heads[off],
832 cp->path_tails[off],
833 entry);
834 cp->off_sum += off;
835 cp->num_paths++;
836
837 /* If we have a tunnel to this peer, tell the tunnel that there is a
838 new path available. */
839 if (NULL != cp->t)
840 GCT_consider_path (cp->t,
841 entry->path,
842 off);
843
844 if ( (NULL != cp->search_h) &&
845 (DESIRED_CONNECTIONS_PER_TUNNEL <= cp->num_paths) )
1270 { 846 {
1271 GNUNET_MQ_send_cancel (q->env); 847 /* Now I have enough paths, stop search */
848 GCD_search_stop (cp->search_h);
849 cp->search_h = NULL;
850 }
851 if (NULL != cp->destroy_task)
852 {
853 /* paths changed, this resets the destroy timeout counter
854 and aborts a destroy task that may no longer be valid
855 to have (as we now have more paths via this peer). */
856 consider_peer_destroy (cp);
1272 } 857 }
1273 call_peer_cont (q, GNUNET_NO);
1274 GNUNET_free (q);
1275} 858}
1276 859
1277 860
1278/** 861/**
1279 * Initialize the peer subsystem. 862 * Remove an entry from the DLL of all of the paths that this peer is on.
1280 * 863 *
1281 * @param c Configuration. 864 * @param cp peer to modify
1282 */ 865 * @param entry an entry on a path
1283void 866 * @param off offset of this peer on the path
1284GCP_init (const struct GNUNET_CONFIGURATION_Handle *c)
1285{
1286 cfg = c;
1287 LOG (GNUNET_ERROR_TYPE_DEBUG,
1288 "GCP_init\n");
1289 in_shutdown = GNUNET_NO;
1290 peers = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
1291 if (GNUNET_OK !=
1292 GNUNET_CONFIGURATION_get_value_number (c, "CADET", "MAX_PEERS",
1293 &max_peers))
1294 {
1295 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
1296 "CADET", "MAX_PEERS", "USING DEFAULT");
1297 max_peers = 1000;
1298 }
1299
1300 if (GNUNET_OK !=
1301 GNUNET_CONFIGURATION_get_value_number (c, "CADET", "DROP_PERCENT",
1302 &drop_percent))
1303 {
1304 drop_percent = 0;
1305 }
1306 else
1307 {
1308 LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n");
1309 LOG (GNUNET_ERROR_TYPE_WARNING, "Cadet is running with DROP enabled.\n");
1310 LOG (GNUNET_ERROR_TYPE_WARNING, "This is NOT a good idea!\n");
1311 LOG (GNUNET_ERROR_TYPE_WARNING, "Remove DROP_PERCENT from config file.\n");
1312 LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n");
1313 }
1314 ats_ch = GNUNET_ATS_connectivity_init (c);
1315 connect_to_core (c);
1316 if (NULL == core_handle)
1317 {
1318 GNUNET_break (0);
1319 GNUNET_SCHEDULER_shutdown ();
1320 }
1321}
1322
1323
1324/**
1325 * Shut down the peer subsystem.
1326 */ 867 */
1327void 868void
1328GCP_shutdown (void) 869GCP_path_entry_remove (struct CadetPeer *cp,
1329{ 870 struct CadetPeerPathEntry *entry,
1330 LOG (GNUNET_ERROR_TYPE_DEBUG, 871 unsigned int off)
1331 "Shutting down peer subsystem\n"); 872{
1332 in_shutdown = GNUNET_YES; 873 LOG (GNUNET_ERROR_TYPE_DEBUG,
1333 if (NULL != core_handle) 874 "Removing knowledge about peer %s beging on path %s at offset %u\n",
1334 { 875 GCP_2s (cp),
1335 GNUNET_CORE_disconnect (core_handle); 876 GCPP_2s (entry->path),
1336 core_handle = NULL; 877 off);
1337 } 878 GNUNET_CONTAINER_DLL_remove (cp->path_heads[off],
1338 GNUNET_PEER_change_rc (myid, -1); 879 cp->path_tails[off],
1339 /* With MQ API, CORE calls the disconnect handler for every peer 880 entry);
1340 * after calling GNUNET_CORE_disconnect, shutdown must occur *after* that. 881 GNUNET_assert (0 < cp->num_paths);
1341 */ 882 cp->off_sum -= off;
1342 GNUNET_CONTAINER_multipeermap_iterate (peers, 883 cp->num_paths--;
1343 &shutdown_peer, 884 if ( (NULL == cp->core_mq) &&
1344 NULL); 885 (NULL != cp->t) &&
1345 if (NULL != ats_ch) 886 (NULL == cp->search_h) &&
1346 { 887 (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) )
1347 GNUNET_ATS_connectivity_done (ats_ch); 888 cp->search_h
1348 ats_ch = NULL; 889 = GCD_search (&cp->pid);
1349 } 890 if (NULL == cp->destroy_task)
1350 GNUNET_CONTAINER_multipeermap_destroy (peers); 891 {
1351 peers = NULL; 892 /* paths changed, we might now be ready for destruction, check again */
1352} 893 consider_peer_destroy (cp);
1353 894 }
1354
1355/**
1356 * Retrieve the CadetPeer stucture associated with the peer. Optionally create
1357 * one and insert it in the appropriate structures if the peer is not known yet.
1358 *
1359 * @param peer_id Full identity of the peer.
1360 * @param create #GNUNET_YES if a new peer should be created if unknown.
1361 * #GNUNET_NO otherwise.
1362 *
1363 * @return Existing or newly created peer structure.
1364 * NULL if unknown and not requested @a create
1365 */
1366struct CadetPeer *
1367GCP_get (const struct GNUNET_PeerIdentity *peer_id, int create)
1368{
1369 struct CadetPeer *peer;
1370
1371 peer = GNUNET_CONTAINER_multipeermap_get (peers, peer_id);
1372 if (NULL == peer)
1373 {
1374 peer = GNUNET_new (struct CadetPeer);
1375 if (GNUNET_CONTAINER_multipeermap_size (peers) > max_peers)
1376 {
1377 peer_delete_oldest ();
1378 }
1379 GNUNET_assert (GNUNET_OK ==
1380 GNUNET_CONTAINER_multipeermap_put (peers,
1381 peer_id,
1382 peer,
1383 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1384 peer->id = GNUNET_PEER_intern (peer_id);
1385 }
1386 peer->last_contact = GNUNET_TIME_absolute_get ();
1387
1388 return peer;
1389}
1390
1391
1392/**
1393 * Retrieve the CadetPeer stucture associated with the
1394 * peer. Optionally create one and insert it in the appropriate
1395 * structures if the peer is not known yet.
1396 *
1397 * @param peer Short identity of the peer.
1398 * @param create #GNUNET_YES if a new peer should be created if unknown.
1399 * #GNUNET_NO otherwise.
1400 *
1401 * @return Existing or newly created peer structure.
1402 * NULL if unknown and not requested @a create
1403 */
1404struct CadetPeer *
1405GCP_get_short (const GNUNET_PEER_Id peer, int create)
1406{
1407 return GCP_get (GNUNET_PEER_resolve2 (peer), create);
1408} 895}
1409 896
1410 897
1411/** 898/**
1412 * Function called once #GNUNET_TRANSPORT_offer_hello() is done. 899 * Prune down the number of paths to this peer, we seem to
1413 * Marks the operation as finished. 900 * have way too many.
1414 * 901 *
1415 * @param cls Closure (our `struct CadetPeer`). 902 * @param cls the `struct CadetPeer` to maintain the path heap for
1416 */ 903 */
1417static void 904static void
1418hello_offer_done (void *cls) 905path_heap_cleanup (void *cls)
1419{ 906{
1420 struct CadetPeer *peer = cls; 907 struct CadetPeer *cp = cls;
908 struct CadetPeerPath *root;
1421 909
1422 peer->hello_offer = NULL; 910 cp->heap_cleanup_task = NULL;
911 while (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >=
912 2 * DESIRED_CONNECTIONS_PER_TUNNEL)
913 {
914 /* Now we have way too many, drop least desirable UNLESS it is in use!
915 (Note that this intentionally keeps highly desireable, but currently
916 unused paths around in the hope that we might be able to switch, even
917 if the number of paths exceeds the threshold.) */
918 root = GNUNET_CONTAINER_heap_peek (cp->path_heap);
919 GNUNET_assert (NULL != root);
920 if (NULL !=
921 GCPP_get_connection (root,
922 cp,
923 GCPP_get_length (root) - 1))
924 break; /* can't fix */
925 /* Got plenty of paths to this destination, and this is a low-quality
926 one that we don't care about. Allow it to die. */
927 GNUNET_assert (root ==
928 GNUNET_CONTAINER_heap_remove_root (cp->path_heap));
929 GCPP_release (root);
930 }
1423} 931}
1424 932
1425 933
1426/** 934/**
1427 * Try to establish a new connection to this peer (in its tunnel). 935 * Try adding a @a path to this @a peer. If the peer already
1428 * If the peer doesn't have any path to it yet, try to get one. 936 * has plenty of paths, return NULL.
1429 * If the peer already has some path, send a CREATE CONNECTION towards it.
1430 * 937 *
1431 * @param peer Peer to connect to. 938 * @param cp peer to which the @a path leads to
939 * @param path a path looking for an owner; may not be fully initialized yet!
940 * @param off offset of @a cp in @a path
941 * @param force force attaching the path
942 * @return NULL if this peer does not care to become a new owner,
943 * otherwise the node in the peer's path heap for the @a path.
1432 */ 944 */
1433void 945struct GNUNET_CONTAINER_HeapNode *
1434GCP_connect (struct CadetPeer *peer) 946GCP_attach_path (struct CadetPeer *cp,
947 struct CadetPeerPath *path,
948 unsigned int off,
949 int force)
1435{ 950{
1436 struct CadetTunnel *t; 951 GNUNET_CONTAINER_HeapCostType desirability;
1437 struct CadetPeerPath *path; 952 struct CadetPeerPath *root;
1438 struct CadetConnection *c; 953 GNUNET_CONTAINER_HeapCostType root_desirability;
1439 int rerun_search; 954 struct GNUNET_CONTAINER_HeapNode *hn;
1440
1441 GCC_check_connections ();
1442 LOG (GNUNET_ERROR_TYPE_DEBUG,
1443 "peer_connect towards %s\n",
1444 GCP_2s (peer));
1445 /* If we have a current hello, try to connect using it. */
1446 GCP_try_connect (peer);
1447 955
1448 t = peer->tunnel; 956 GNUNET_assert (off == GCPP_get_length (path) - 1);
1449 c = NULL; 957 GNUNET_assert (cp == GCPP_get_peer_at_offset (path,
1450 rerun_search = GNUNET_NO; 958 off));
1451 959 if (NULL == cp->path_heap)
1452 if (NULL != peer->path_head) 960 {
961 /* #GCP_drop_owned_paths() was already called, we cannot take new ones! */
962 GNUNET_assert (GNUNET_NO == force);
963 return NULL;
964 }
965 desirability = GCPP_get_desirability (path);
966 if (GNUNET_NO == force)
967 {
968 /* FIXME: desirability is not yet initialized; tricky! */
969 if (GNUNET_NO ==
970 GNUNET_CONTAINER_heap_peek2 (cp->path_heap,
971 (void **) &root,
972 &root_desirability))
1453 { 973 {
1454 LOG (GNUNET_ERROR_TYPE_DEBUG, " some path exists\n"); 974 root = NULL;
1455 path = peer_get_best_path (peer); 975 root_desirability = 0;
1456 if (NULL != path)
1457 {
1458 char *s;
1459
1460 s = path_2s (path);
1461 LOG (GNUNET_ERROR_TYPE_DEBUG, " path to use: %s\n", s);
1462 GNUNET_free (s);
1463
1464 c = GCT_use_path (t, path);
1465 if (NULL == c)
1466 {
1467 /* This case can happen when the path includes a first hop that is
1468 * not yet known to be connected.
1469 *
1470 * This happens quite often during testing when running cadet
1471 * under valgrind: core connect notifications come very late
1472 * and the DHT result has already come and created a valid
1473 * path. In this case, the peer->connections
1474 * hashmaps will be NULL and tunnel_use_path will not be able
1475 * to create a connection from that path.
1476 *
1477 * Re-running the DHT GET should give core time to callback.
1478 *
1479 * GCT_use_path -> GCC_new -> register_neighbors takes care of
1480 * updating statistics about this issue.
1481 */
1482 rerun_search = GNUNET_YES;
1483 }
1484 else
1485 {
1486 GCC_send_create (c);
1487 return;
1488 }
1489 }
1490 else
1491 {
1492 LOG (GNUNET_ERROR_TYPE_DEBUG, " but is NULL, all paths are in use\n");
1493 }
1494 } 976 }
1495 977
1496 if (GNUNET_YES == rerun_search) 978 if ( (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) &&
979 (desirability < root_desirability) )
1497 { 980 {
1498 struct GNUNET_TIME_Relative delay; 981 LOG (GNUNET_ERROR_TYPE_DEBUG,
1499 982 "Decided to not attach path %p to peer %s due to undesirability\n",
1500 GCP_stop_search (peer); 983 GCPP_2s (path),
1501 delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100); 984 GCP_2s (cp));
1502 peer->search_delayed = GNUNET_SCHEDULER_add_delayed (delay, 985 return NULL;
1503 &delayed_search,
1504 peer);
1505 GCC_check_connections ();
1506 return;
1507 } 986 }
987 }
1508 988
1509 if (GNUNET_NO == is_searching (peer)) 989 LOG (GNUNET_ERROR_TYPE_DEBUG,
1510 GCP_start_search (peer); 990 "Attaching path %s to peer %s (%s)\n",
1511 GCC_check_connections (); 991 GCPP_2s (path),
1512} 992 GCP_2s (cp),
1513 993 (GNUNET_NO == force) ? "desirable" : "forced");
1514
1515/**
1516 * Chech whether there is a direct (core level) connection to peer.
1517 *
1518 * @param peer Peer to check.
1519 *
1520 * @return #GNUNET_YES if there is a direct connection.
1521 */
1522int
1523GCP_is_neighbor (const struct CadetPeer *peer)
1524{
1525 struct CadetPeerPath *path;
1526
1527 if (NULL == peer->connections)
1528 return GNUNET_NO;
1529 994
1530 for (path = peer->path_head; NULL != path; path = path->next) 995 /* Yes, we'd like to add this path, add to our heap */
1531 { 996 hn = GNUNET_CONTAINER_heap_insert (cp->path_heap,
1532 if (3 > path->length) 997 path,
1533 return GNUNET_YES; 998 desirability);
1534 }
1535 999
1536 /* Is not a neighbor but connections is not NULL, probably disconnecting */ 1000 /* Consider maybe dropping other paths because of the new one */
1537 return GNUNET_NO; 1001 if ( (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >=
1002 2 * DESIRED_CONNECTIONS_PER_TUNNEL) &&
1003 (NULL != cp->heap_cleanup_task) )
1004 cp->heap_cleanup_task = GNUNET_SCHEDULER_add_now (&path_heap_cleanup,
1005 cp);
1006 return hn;
1538} 1007}
1539 1008
1540 1009
1541/** 1010/**
1542 * Create and initialize a new tunnel towards a peer, in case it has none. 1011 * This peer can no longer own @a path as the path
1543 * In case the peer already has a tunnel, nothing is done. 1012 * has been extended and a peer further down the line
1013 * is now the new owner.
1544 * 1014 *
1545 * Does not generate any traffic, just creates the local data structures. 1015 * @param cp old owner of the @a path
1546 * 1016 * @param path path where the ownership is lost
1547 * @param peer Peer towards which to create the tunnel. 1017 * @param hn note in @a cp's path heap that must be deleted
1548 */ 1018 */
1549void 1019void
1550GCP_add_tunnel (struct CadetPeer *peer) 1020GCP_detach_path (struct CadetPeer *cp,
1021 struct CadetPeerPath *path,
1022 struct GNUNET_CONTAINER_HeapNode *hn)
1551{ 1023{
1552 GCC_check_connections (); 1024 LOG (GNUNET_ERROR_TYPE_DEBUG,
1553 if (NULL != peer->tunnel) 1025 "Detatching path %s from peer %s\n",
1554 return; 1026 GCPP_2s (path),
1555 peer->tunnel = GCT_new (peer); 1027 GCP_2s (cp));
1556 GCC_check_connections (); 1028 GNUNET_assert (path ==
1029 GNUNET_CONTAINER_heap_remove_node (hn));
1557} 1030}
1558 1031
1559 1032
1560/** 1033/**
1561 * Add a connection to a neighboring peer. 1034 * Add a @a connection to this @a cp.
1562 *
1563 * Store that the peer is the first hop of the connection in one
1564 * direction and that on peer disconnect the connection must be
1565 * notified and destroyed, for it will no longer be valid.
1566 * 1035 *
1567 * @param peer Peer to add connection to. 1036 * @param cp peer via which the @a connection goes
1568 * @param c Connection to add. 1037 * @param cc the connection to add
1569 * @param pred #GNUNET_YES if we are predecessor, #GNUNET_NO if we are successor
1570 */ 1038 */
1571void 1039void
1572GCP_add_connection (struct CadetPeer *peer, 1040GCP_add_connection (struct CadetPeer *cp,
1573 struct CadetConnection *c, 1041 struct CadetConnection *cc)
1574 int pred) 1042{
1575{ 1043 LOG (GNUNET_ERROR_TYPE_DEBUG,
1576 LOG (GNUNET_ERROR_TYPE_DEBUG, 1044 "Adding connection %s to peer %s\n",
1577 "adding connection %s\n", 1045 GCC_2s (cc),
1578 GCC_2s (c)); 1046 GCP_2s (cp));
1579 LOG (GNUNET_ERROR_TYPE_DEBUG, 1047 GNUNET_assert (GNUNET_OK ==
1580 "to peer %s\n", 1048 GNUNET_CONTAINER_multishortmap_put (cp->connections,
1581 GCP_2s (peer)); 1049 &GCC_get_id (cc)->connection_of_tunnel,
1582 GNUNET_assert (NULL != peer->connections); 1050 cc,
1583 GNUNET_assert (GNUNET_OK == 1051 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1584 GNUNET_CONTAINER_multishortmap_put (peer->connections, 1052 if (NULL != cp->destroy_task)
1585 &GCC_get_id (c)->connection_of_tunnel, 1053 {
1586 c, 1054 GNUNET_SCHEDULER_cancel (cp->destroy_task);
1587 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); 1055 cp->destroy_task = NULL;
1588 LOG (GNUNET_ERROR_TYPE_DEBUG, 1056 }
1589 "Peer %s has now %u connections.\n",
1590 GCP_2s (peer),
1591 GNUNET_CONTAINER_multishortmap_size (peer->connections));
1592}
1593
1594
1595/**
1596 * Add the path to the peer and update the path used to reach it in case this
1597 * is the shortest.
1598 *
1599 * @param peer Destination peer to add the path to.
1600 * @param path New path to add. Last peer must be @c peer.
1601 * Path will be either used of freed if already known.
1602 * @param trusted Do we trust that this path is real?
1603 *
1604 * @return path if path was taken, pointer to existing duplicate if exists
1605 * NULL on error.
1606 */
1607struct CadetPeerPath *
1608GCP_add_path (struct CadetPeer *peer,
1609 struct CadetPeerPath *path,
1610 int trusted)
1611{
1612 struct CadetPeerPath *aux;
1613 unsigned int l;
1614 unsigned int l2;
1615
1616 GCC_check_connections ();
1617 LOG (GNUNET_ERROR_TYPE_DEBUG,
1618 "adding path [%u] to peer %s\n",
1619 path->length, GCP_2s (peer));
1620
1621 if (NULL == peer || NULL == path
1622 || path->peers[path->length - 1] != peer->id)
1623 {
1624 GNUNET_break (0);
1625 path_destroy (path);
1626 return NULL;
1627 }
1628
1629 for (l = 1; l < path->length; l++)
1630 {
1631 if (path->peers[l] == myid)
1632 {
1633 LOG (GNUNET_ERROR_TYPE_DEBUG, " shortening path by %u\n", l);
1634 for (l2 = 0; l2 < path->length - l; l2++)
1635 {
1636 path->peers[l2] = path->peers[l + l2];
1637 }
1638 path->length -= l;
1639 l = 1;
1640 path->peers = GNUNET_realloc (path->peers,
1641 path->length * sizeof (GNUNET_PEER_Id));
1642 }
1643 }
1644
1645 LOG (GNUNET_ERROR_TYPE_DEBUG, " final length: %u\n", path->length);
1646
1647 if (2 >= path->length && GNUNET_NO == trusted)
1648 {
1649 /* Only allow CORE to tell us about direct paths */
1650 path_destroy (path);
1651 return NULL;
1652 }
1653
1654 l = path_get_length (path);
1655 if (0 == l)
1656 {
1657 path_destroy (path);
1658 return NULL;
1659 }
1660
1661 GNUNET_assert (peer->id == path->peers[path->length - 1]);
1662 for (aux = peer->path_head; aux != NULL; aux = aux->next)
1663 {
1664 l2 = path_get_length (aux);
1665 if (l2 > l)
1666 {
1667 LOG (GNUNET_ERROR_TYPE_DEBUG, " added\n");
1668 GNUNET_CONTAINER_DLL_insert_before (peer->path_head,
1669 peer->path_tail, aux, path);
1670 goto finish;
1671 }
1672 else
1673 {
1674 if (l2 == l && memcmp (path->peers, aux->peers, l) == 0)
1675 {
1676 LOG (GNUNET_ERROR_TYPE_DEBUG, " already known\n");
1677 path_destroy (path);
1678 return aux;
1679 }
1680 }
1681 }
1682 GNUNET_CONTAINER_DLL_insert_tail (peer->path_head,
1683 peer->path_tail,
1684 path);
1685 LOG (GNUNET_ERROR_TYPE_DEBUG, " added last\n");
1686
1687finish:
1688 if (NULL != peer->tunnel
1689 && CONNECTIONS_PER_TUNNEL > GCT_count_connections (peer->tunnel)
1690 && 2 < path->length) /* Direct paths are handled by core_connect */
1691 {
1692 GCP_connect (peer);
1693 }
1694 GCC_check_connections ();
1695 return path;
1696} 1057}
1697 1058
1698 1059
1699/** 1060/**
1700 * Add the path to the origin peer and update the path used to reach it in case 1061 * Remove a @a connection that went via this @a cp.
1701 * this is the shortest.
1702 * The path is given in peer_info -> destination, therefore we turn the path
1703 * upside down first.
1704 *
1705 * @param peer Peer to add the path to, being the origin of the path.
1706 * @param path New path to add after being inversed.
1707 * Path will be either used or freed.
1708 * @param trusted Do we trust that this path is real?
1709 * 1062 *
1710 * @return path if path was taken, pointer to existing duplicate if exists 1063 * @param cp peer via which the @a connection went
1711 * NULL on error. 1064 * @param cc the connection to remove
1712 */ 1065 */
1713struct CadetPeerPath * 1066void
1714GCP_add_path_to_origin (struct CadetPeer *peer, 1067GCP_remove_connection (struct CadetPeer *cp,
1715 struct CadetPeerPath *path, 1068 struct CadetConnection *cc)
1716 int trusted)
1717{ 1069{
1718 if (NULL == path) 1070 LOG (GNUNET_ERROR_TYPE_DEBUG,
1719 return NULL; 1071 "Removing connection %s from peer %s\n",
1720 path_invert (path); 1072 GCC_2s (cc),
1721 return GCP_add_path (peer, path, trusted); 1073 GCP_2s (cp));
1074 GNUNET_assert (GNUNET_YES ==
1075 GNUNET_CONTAINER_multishortmap_remove (cp->connections,
1076 &GCC_get_id (cc)->connection_of_tunnel,
1077 cc));
1078 consider_peer_destroy (cp);
1722} 1079}
1723 1080
1724 1081
1725/** 1082/**
1726 * Adds a path to the info of all the peers in the path 1083 * Retrieve the CadetPeer stucture associated with the
1084 * peer. Optionally create one and insert it in the appropriate
1085 * structures if the peer is not known yet.
1727 * 1086 *
1728 * @param p Path to process. 1087 * @param peer_id Full identity of the peer.
1729 * @param confirmed Whether we know if the path works or not. 1088 * @param create #GNUNET_YES if a new peer should be created if unknown.
1089 * #GNUNET_NO to return NULL if peer is unknown.
1090 * @return Existing or newly created peer structure.
1091 * NULL if unknown and not requested @a create
1730 */ 1092 */
1731void 1093struct CadetPeer *
1732GCP_add_path_to_all (const struct CadetPeerPath *p, int confirmed) 1094GCP_get (const struct GNUNET_PeerIdentity *peer_id,
1095 int create)
1733{ 1096{
1734 unsigned int i; 1097 struct CadetPeer *cp;
1735 1098
1736 /* TODO: invert and add to origin */ 1099 cp = GNUNET_CONTAINER_multipeermap_get (peers,
1737 /* TODO: replace all "GCP_add_path" with this, make the other one static */ 1100 peer_id);
1738 GCC_check_connections (); 1101 if (NULL != cp)
1739 for (i = 0; i < p->length && p->peers[i] != myid; i++) /* skip'em */ ; 1102 return cp;
1740 for (i++; i < p->length; i++) 1103 if (GNUNET_NO == create)
1741 { 1104 return NULL;
1742 struct CadetPeer *peer; 1105 cp = GNUNET_new (struct CadetPeer);
1743 struct CadetPeerPath *copy; 1106 cp->pid = *peer_id;
1744 1107 cp->connections = GNUNET_CONTAINER_multishortmap_create (32,
1745 peer = GCP_get_short (p->peers[i], GNUNET_YES); 1108 GNUNET_YES);
1746 copy = path_duplicate (p); 1109 cp->path_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1747 copy->length = i + 1; 1110 GNUNET_assert (GNUNET_YES ==
1748 GCP_add_path (peer, copy, 3 > p->length ? GNUNET_NO : confirmed); 1111 GNUNET_CONTAINER_multipeermap_put (peers,
1749 } 1112 &cp->pid,
1750 GCC_check_connections (); 1113 cp,
1114 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1115 LOG (GNUNET_ERROR_TYPE_DEBUG,
1116 "Creating peer %s\n",
1117 GCP_2s (cp));
1118 return cp;
1751} 1119}
1752 1120
1753 1121
1754/** 1122/**
1755 * Remove any path to the peer that has the exact same peers as the one given. 1123 * Obtain the peer identity for a `struct CadetPeer`.
1756 * 1124 *
1757 * @param peer Peer to remove the path from. 1125 * @param cp our peer handle
1758 * @param path Path to remove. Is always destroyed . 1126 * @return the peer identity
1759 */ 1127 */
1760void 1128const struct GNUNET_PeerIdentity *
1761GCP_remove_path (struct CadetPeer *peer, 1129GCP_get_id (struct CadetPeer *cp)
1762 struct CadetPeerPath *path)
1763{ 1130{
1764 struct CadetPeerPath *iter; 1131 return &cp->pid;
1765 struct CadetPeerPath *next;
1766
1767 GCC_check_connections ();
1768 GNUNET_assert (myid == path->peers[0]);
1769 GNUNET_assert (peer->id == path->peers[path->length - 1]);
1770
1771 LOG (GNUNET_ERROR_TYPE_INFO,
1772 "Removing path %p (%u) from %s\n",
1773 path, path->length, GCP_2s (peer));
1774
1775 for (iter = peer->path_head; NULL != iter; iter = next)
1776 {
1777 next = iter->next;
1778 if (0 == path_cmp (path, iter))
1779 {
1780 GNUNET_CONTAINER_DLL_remove (peer->path_head,
1781 peer->path_tail,
1782 iter);
1783 if (iter != path)
1784 path_destroy (iter);
1785 }
1786 }
1787 path_destroy (path);
1788 GCC_check_connections ();
1789} 1132}
1790 1133
1791 1134
1792/** 1135/**
1793 * Check that we are aware of a connection from a neighboring peer. 1136 * Iterate over all known peers.
1794 * 1137 *
1795 * @param peer Peer to the connection is with 1138 * @param iter Iterator.
1796 * @param c Connection that should be in the map with this peer. 1139 * @param cls Closure for @c iter.
1797 */ 1140 */
1798void 1141void
1799GCP_check_connection (const struct CadetPeer *peer, 1142GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
1800 const struct CadetConnection *c) 1143 void *cls)
1801{ 1144{
1802 GNUNET_assert (NULL != peer); 1145 GNUNET_CONTAINER_multipeermap_iterate (peers,
1803 GNUNET_assert (NULL != peer->connections); 1146 iter,
1804 return; // ???? 1147 cls);
1805 GNUNET_assert (GNUNET_YES ==
1806 GNUNET_CONTAINER_multishortmap_contains_value (peer->connections,
1807 &GCC_get_id (c)->connection_of_tunnel,
1808 c));
1809} 1148}
1810 1149
1811 1150
1812/** 1151/**
1813 * Remove a connection from a neighboring peer. 1152 * Count the number of known paths toward the peer.
1814 * 1153 *
1815 * @param peer Peer to remove connection from. 1154 * @param cp Peer to get path info.
1816 * @param c Connection to remove. 1155 * @return Number of known paths.
1817 */ 1156 */
1818void 1157unsigned int
1819GCP_remove_connection (struct CadetPeer *peer, 1158GCP_count_paths (const struct CadetPeer *cp)
1820 const struct CadetConnection *c)
1821{ 1159{
1822 LOG (GNUNET_ERROR_TYPE_DEBUG, 1160 return cp->num_paths;
1823 "Removing connection %s\n",
1824 GCC_2s (c));
1825 LOG (GNUNET_ERROR_TYPE_DEBUG,
1826 "from peer %s\n",
1827 GCP_2s (peer));
1828 if ( (NULL == peer) ||
1829 (NULL == peer->connections) )
1830 return;
1831 GNUNET_assert (GNUNET_YES ==
1832 GNUNET_CONTAINER_multishortmap_remove (peer->connections,
1833 &GCC_get_id (c)->connection_of_tunnel,
1834 c));
1835 LOG (GNUNET_ERROR_TYPE_DEBUG,
1836 "Peer %s remains with %u connections.\n",
1837 GCP_2s (peer),
1838 GNUNET_CONTAINER_multishortmap_size (peer->connections));
1839} 1161}
1840 1162
1841 1163
1842/** 1164/**
1843 * Start the DHT search for new paths towards the peer: we don't have 1165 * Iterate over the paths to a peer.
1844 * enough good connections.
1845 * 1166 *
1846 * @param peer Destination peer. 1167 * @param cp Peer to get path info.
1168 * @param callback Function to call for every path.
1169 * @param callback_cls Closure for @a callback.
1170 * @return Number of iterated paths.
1847 */ 1171 */
1848void 1172unsigned int
1849GCP_start_search (struct CadetPeer *peer) 1173GCP_iterate_paths (struct CadetPeer *cp,
1174 GCP_PathIterator callback,
1175 void *callback_cls)
1850{ 1176{
1851 const struct GNUNET_PeerIdentity *id; 1177 unsigned int ret = 0;
1852 struct CadetTunnel *t = peer->tunnel;
1853
1854 GCC_check_connections ();
1855 if (NULL != peer->search_h)
1856 {
1857 GNUNET_break (0);
1858 return;
1859 }
1860
1861 if (NULL != peer->search_delayed)
1862 GCP_stop_search (peer);
1863
1864 id = GNUNET_PEER_resolve2 (peer->id);
1865 peer->search_h = GCD_search (id, &search_handler, peer);
1866
1867 if (NULL == t)
1868 {
1869 /* Why would we search for a peer with no tunnel towards it? */
1870 GNUNET_break (0);
1871 return;
1872 }
1873
1874 if (CADET_TUNNEL_NEW == GCT_get_cstate (t)
1875 || 0 == GCT_count_any_connections (t))
1876 {
1877 GCT_change_cstate (t, CADET_TUNNEL_SEARCHING);
1878 }
1879 GCC_check_connections ();
1880}
1881 1178
1179 LOG (GNUNET_ERROR_TYPE_DEBUG,
1180 "Iterating over paths to peer %s%s\n",
1181 GCP_2s (cp),
1182 (NULL == cp->core_mq) ? "" : " including direct link");
1183 if (NULL != cp->core_mq)
1184 {
1185 struct CadetPeerPath *path;
1882 1186
1883/** 1187 path = GCPP_get_path_from_route (1,
1884 * Stop the DHT search for new paths towards the peer: we already have 1188 &cp->pid);
1885 * enough good connections. 1189 ret++;
1886 * 1190 if (GNUNET_NO ==
1887 * @param peer Destination peer. 1191 callback (callback_cls,
1888 */ 1192 path,
1889void 1193 0))
1890GCP_stop_search (struct CadetPeer *peer) 1194 return ret;
1891{ 1195 }
1892 GCC_check_connections (); 1196 for (unsigned int i=0;i<cp->path_dll_length;i++)
1893 if (NULL != peer->search_h) 1197 {
1894 { 1198 for (struct CadetPeerPathEntry *pe = cp->path_heads[i];
1895 GCD_search_stop (peer->search_h); 1199 NULL != pe;
1896 peer->search_h = NULL; 1200 pe = pe->next)
1897 }
1898 if (NULL != peer->search_delayed)
1899 { 1201 {
1900 GNUNET_SCHEDULER_cancel (peer->search_delayed); 1202 ret++;
1901 peer->search_delayed = NULL; 1203 if (GNUNET_NO ==
1204 callback (callback_cls,
1205 pe->path,
1206 i))
1207 return ret;
1902 } 1208 }
1903 GCC_check_connections (); 1209 }
1904} 1210 return ret;
1905
1906
1907/**
1908 * Get the Full ID of a peer.
1909 *
1910 * @param peer Peer to get from.
1911 *
1912 * @return Full ID of peer.
1913 */
1914const struct GNUNET_PeerIdentity *
1915GCP_get_id (const struct CadetPeer *peer)
1916{
1917 return GNUNET_PEER_resolve2 (peer->id);
1918} 1211}
1919 1212
1920 1213
1921/** 1214/**
1922 * Get the Short ID of a peer. 1215 * Iterate over the paths to @a cp where
1923 * 1216 * @a cp is at distance @a dist from us.
1924 * @param peer Peer to get from.
1925 * 1217 *
1926 * @return Short ID of peer. 1218 * @param cp Peer to get path info.
1219 * @param dist desired distance of @a cp to us on the path
1220 * @param callback Function to call for every path.
1221 * @param callback_cls Closure for @a callback.
1222 * @return Number of iterated paths.
1927 */ 1223 */
1928GNUNET_PEER_Id 1224unsigned int
1929GCP_get_short_id (const struct CadetPeer *peer) 1225GCP_iterate_paths_at (struct CadetPeer *cp,
1226 unsigned int dist,
1227 GCP_PathIterator callback,
1228 void *callback_cls)
1930{ 1229{
1931 return peer->id; 1230 unsigned int ret = 0;
1932}
1933
1934 1231
1935/** 1232 if (dist >= cp->path_dll_length)
1936 * Set tunnel. 1233 {
1937 * 1234 LOG (GNUNET_ERROR_TYPE_DEBUG,
1938 * If tunnel is NULL and there was a search active, stop it, as it's useless. 1235 "Asked to look for paths at distance %u, but maximum for me is < %u\n",
1939 * 1236 dist,
1940 * @param peer Peer. 1237 cp->path_dll_length);
1941 * @param t Tunnel. 1238 return 0;
1942 */ 1239 }
1943void 1240 for (struct CadetPeerPathEntry *pe = cp->path_heads[dist];
1944GCP_set_tunnel (struct CadetPeer *peer, struct CadetTunnel *t) 1241 NULL != pe;
1945{ 1242 pe = pe->next)
1946 peer->tunnel = t; 1243 {
1947 if (NULL == t && GNUNET_YES == is_searching (peer)) 1244 if (GNUNET_NO ==
1948 { 1245 callback (callback_cls,
1949 GCP_stop_search (peer); 1246 pe->path,
1950 } 1247 dist))
1248 return ret;
1249 ret++;
1250 }
1251 return ret;
1951} 1252}
1952 1253
1953 1254
1954/** 1255/**
1955 * Get the tunnel towards a peer. 1256 * Get the tunnel towards a peer.
1956 * 1257 *
1957 * @param peer Peer to get from. 1258 * @param cp Peer to get from.
1958 * 1259 * @param create #GNUNET_YES to create a tunnel if we do not have one
1959 * @return Tunnel towards peer. 1260 * @return Tunnel towards peer.
1960 */ 1261 */
1961struct CadetTunnel * 1262struct CadetTunnel *
1962GCP_get_tunnel (const struct CadetPeer *peer) 1263GCP_get_tunnel (struct CadetPeer *cp,
1264 int create)
1963{ 1265{
1964 if (NULL == peer) 1266 if (NULL == cp)
1965 return NULL; 1267 return NULL;
1966 return peer->tunnel; 1268 if ( (NULL != cp->t) ||
1269 (GNUNET_NO == create) )
1270 return cp->t;
1271 cp->t = GCT_create_tunnel (cp);
1272 consider_peer_activate (cp);
1273 return cp->t;
1967} 1274}
1968 1275
1969 1276
1970/** 1277/**
1971 * Set the hello message. 1278 * Hello offer was passed to the transport service. Mark it
1279 * as done.
1972 * 1280 *
1973 * @param peer Peer whose message to set. 1281 * @param cls the `struct CadetPeer` where the offer completed
1974 * @param hello Hello message.
1975 */ 1282 */
1976void 1283static void
1977GCP_set_hello (struct CadetPeer *peer, 1284hello_offer_done (void *cls)
1978 const struct GNUNET_HELLO_Message *hello)
1979{ 1285{
1980 struct GNUNET_HELLO_Message *old; 1286 struct CadetPeer *cp = cls;
1981 size_t size;
1982 1287
1983 GCC_check_connections (); 1288 cp->hello_offer = NULL;
1984 LOG (GNUNET_ERROR_TYPE_DEBUG, "set hello for %s\n", GCP_2s (peer));
1985 if (NULL == hello)
1986 return;
1987
1988 old = GCP_get_hello (peer);
1989 if (NULL == old)
1990 {
1991 size = GNUNET_HELLO_size (hello);
1992 peer->hello = GNUNET_malloc (size);
1993 GNUNET_memcpy (peer->hello, hello, size);
1994 }
1995 else
1996 {
1997 peer->hello = GNUNET_HELLO_merge (old, hello);
1998 GNUNET_free (old);
1999 }
2000 GCC_check_connections ();
2001} 1289}
2002 1290
2003 1291
2004/** 1292/**
2005 * Get the hello message. 1293 * We got a HELLO for a @a peer, remember it, and possibly
2006 * 1294 * trigger adequate actions (like trying to connect).
2007 * @param peer Peer whose message to get.
2008 * 1295 *
2009 * @return Hello message. 1296 * @param cp the peer we got a HELLO for
1297 * @param hello the HELLO to remember
2010 */ 1298 */
2011struct GNUNET_HELLO_Message * 1299void
2012GCP_get_hello (struct CadetPeer *peer) 1300GCP_set_hello (struct CadetPeer *cp,
1301 const struct GNUNET_HELLO_Message *hello)
2013{ 1302{
2014 struct GNUNET_TIME_Absolute expiration; 1303 struct GNUNET_HELLO_Message *mrg;
2015 struct GNUNET_TIME_Relative remaining;
2016
2017 if (NULL == peer->hello)
2018 return NULL;
2019 1304
2020 expiration = GNUNET_HELLO_get_last_expiration (peer->hello); 1305 LOG (GNUNET_ERROR_TYPE_DEBUG,
2021 remaining = GNUNET_TIME_absolute_get_remaining (expiration); 1306 "Got %u byte HELLO for peer %s\n",
2022 if (0 == remaining.rel_value_us) 1307 (unsigned int) GNUNET_HELLO_size (hello),
2023 { 1308 GCP_2s (cp));
2024 LOG (GNUNET_ERROR_TYPE_DEBUG, " get - hello expired on %s\n", 1309 if (NULL != cp->hello_offer)
2025 GNUNET_STRINGS_absolute_time_to_string (expiration)); 1310 {
2026 GNUNET_free (peer->hello); 1311 GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer);
2027 peer->hello = NULL; 1312 cp->hello_offer = NULL;
2028 } 1313 }
2029 return peer->hello; 1314 if (NULL != cp->hello)
1315 {
1316 mrg = GNUNET_HELLO_merge (hello,
1317 cp->hello);
1318 GNUNET_free (cp->hello);
1319 cp->hello = mrg;
1320 }
1321 else
1322 {
1323 cp->hello = GNUNET_memdup (hello,
1324 GNUNET_HELLO_size (hello));
1325 }
1326 cp->hello_offer
1327 = GNUNET_TRANSPORT_offer_hello (cfg,
1328 GNUNET_HELLO_get_header (cp->hello) ,
1329 &hello_offer_done,
1330 cp);
1331 /* New HELLO means cp's destruction time may change... */
1332 consider_peer_destroy (cp);
2030} 1333}
2031 1334
2032 1335
2033/** 1336/**
2034 * Try to connect to a peer on TRANSPORT level. 1337 * The tunnel to the given peer no longer exists, remove it from our
1338 * data structures, and possibly clean up the peer itself.
2035 * 1339 *
2036 * @param peer Peer to whom to connect. 1340 * @param cp the peer affected
1341 * @param t the dead tunnel
2037 */ 1342 */
2038void 1343void
2039GCP_try_connect (struct CadetPeer *peer) 1344GCP_drop_tunnel (struct CadetPeer *cp,
1345 struct CadetTunnel *t)
2040{ 1346{
2041 struct GNUNET_HELLO_Message *hello; 1347 LOG (GNUNET_ERROR_TYPE_DEBUG,
2042 struct GNUNET_MessageHeader *mh; 1348 "Dropping tunnel %s to peer %s\n",
2043 1349 GCT_2s (t),
2044 if (GNUNET_YES != 1350 GCP_2s (cp));
2045 GNUNET_CONFIGURATION_get_value_yesno (cfg, 1351 GNUNET_assert (cp->t == t);
2046 "CADET", 1352 cp->t = NULL;
2047 "DISABLE_TRY_CONNECT")) 1353 consider_peer_destroy (cp);
2048 return;
2049 GCC_check_connections ();
2050 if (GNUNET_YES == GCP_is_neighbor (peer))
2051 return;
2052 hello = GCP_get_hello (peer);
2053 if (NULL == hello)
2054 return;
2055
2056 mh = GNUNET_HELLO_get_header (hello);
2057 if (NULL != peer->hello_offer)
2058 {
2059 GNUNET_TRANSPORT_offer_hello_cancel (peer->hello_offer);
2060 peer->hello_offer = NULL;
2061 }
2062 peer->hello_offer = GNUNET_TRANSPORT_offer_hello (cfg,
2063 mh,
2064 &hello_offer_done,
2065 peer);
2066 if (NULL == peer->connectivity_suggestion)
2067 peer->connectivity_suggestion
2068 = GNUNET_ATS_connectivity_suggest (ats_ch,
2069 GCP_get_id (peer),
2070 1); /* strength */
2071 GCC_check_connections ();
2072} 1354}
2073 1355
2074 1356
2075/** 1357/**
2076 * Notify a peer that a link between two other peers is broken. If any path 1358 * Test if @a cp has a core-level connection
2077 * used that link, eliminate it.
2078 * 1359 *
2079 * @param peer Peer affected by the change. 1360 * @param cp peer to test
2080 * @param peer1 Peer whose link is broken. 1361 * @return #GNUNET_YES if @a cp has a core-level connection
2081 * @param peer2 Peer whose link is broken.
2082 */ 1362 */
2083void 1363int
2084GCP_notify_broken_link (struct CadetPeer *peer, 1364GCP_has_core_connection (struct CadetPeer *cp)
2085 const struct GNUNET_PeerIdentity *peer1,
2086 const struct GNUNET_PeerIdentity *peer2)
2087{ 1365{
2088 struct CadetPeerPath *iter; 1366 return (NULL != cp->core_mq) ? GNUNET_YES : GNUNET_NO;
2089 struct CadetPeerPath *next;
2090 unsigned int i;
2091 GNUNET_PEER_Id p1;
2092 GNUNET_PEER_Id p2;
2093
2094 GCC_check_connections ();
2095 p1 = GNUNET_PEER_search (peer1);
2096 p2 = GNUNET_PEER_search (peer2);
2097
2098 LOG (GNUNET_ERROR_TYPE_DEBUG, "Link %u-%u broken\n", p1, p2);
2099 if (0 == p1 || 0 == p2)
2100 {
2101 /* We don't even know them */
2102 return;
2103 }
2104
2105 for (iter = peer->path_head; NULL != iter; iter = next)
2106 {
2107 next = iter->next;
2108 for (i = 0; i < iter->length - 1; i++)
2109 {
2110 if ((iter->peers[i] == p1 && iter->peers[i + 1] == p2)
2111 || (iter->peers[i] == p2 && iter->peers[i + 1] == p1))
2112 {
2113 char *s;
2114
2115 s = path_2s (iter);
2116 LOG (GNUNET_ERROR_TYPE_DEBUG, " - invalidating %s\n", s);
2117 GNUNET_free (s);
2118
2119 path_invalidate (iter);
2120 }
2121 }
2122 }
2123 GCC_check_connections ();
2124} 1367}
2125 1368
2126 1369
2127/** 1370/**
2128 * Count the number of known paths toward the peer. 1371 * Start message queue change notifications.
2129 *
2130 * @param peer Peer to get path info.
2131 * 1372 *
2132 * @return Number of known paths. 1373 * @param cp peer to notify for
1374 * @param cb function to call if mq becomes available or unavailable
1375 * @param cb_cls closure for @a cb
1376 * @return handle to cancel request
2133 */ 1377 */
2134unsigned int 1378struct GCP_MessageQueueManager *
2135GCP_count_paths (const struct CadetPeer *peer) 1379GCP_request_mq (struct CadetPeer *cp,
1380 GCP_MessageQueueNotificationCallback cb,
1381 void *cb_cls)
2136{ 1382{
2137 struct CadetPeerPath *iter; 1383 struct GCP_MessageQueueManager *mqm;
2138 unsigned int i;
2139 1384
2140 for (iter = peer->path_head, i = 0; NULL != iter; iter = iter->next) 1385 mqm = GNUNET_new (struct GCP_MessageQueueManager);
2141 i++; 1386 mqm->cb = cb;
2142 1387 mqm->cb_cls = cb_cls;
2143 return i; 1388 mqm->cp = cp;
1389 GNUNET_CONTAINER_DLL_insert (cp->mqm_head,
1390 cp->mqm_tail,
1391 mqm);
1392 LOG (GNUNET_ERROR_TYPE_DEBUG,
1393 "Creating MQM %p for peer %s\n",
1394 mqm,
1395 GCP_2s (cp));
1396 if (NULL != cp->core_mq)
1397 cb (cb_cls,
1398 GNUNET_YES);
1399 return mqm;
2144} 1400}
2145 1401
2146 1402
2147/** 1403/**
2148 * Iterate over the paths to a peer. 1404 * Stops message queue change notifications.
2149 * 1405 *
2150 * @param peer Peer to get path info. 1406 * @param mqm handle matching request to cancel
2151 * @param callback Function to call for every path. 1407 * @param last_env final message to transmit, or NULL
2152 * @param cls Closure for @a callback.
2153 *
2154 * @return Number of iterated paths.
2155 */ 1408 */
2156unsigned int 1409void
2157GCP_iterate_paths (struct CadetPeer *peer, 1410GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm,
2158 GCP_path_iterator callback, 1411 struct GNUNET_MQ_Envelope *last_env)
2159 void *cls) 1412{
2160{ 1413 struct CadetPeer *cp = mqm->cp;
2161 struct CadetPeerPath *iter; 1414
2162 unsigned int i; 1415 LOG (GNUNET_ERROR_TYPE_DEBUG,
2163 1416 "Destroying MQM %p for peer %s%s\n",
2164 for (iter = peer->path_head, i = 0; NULL != iter; iter = iter->next) 1417 mqm,
1418 GCP_2s (cp),
1419 (NULL == last_env) ? "" : " with last ditch transmission");
1420 if (NULL != mqm->env)
1421 GNUNET_MQ_discard (mqm->env);
1422 if (NULL != last_env)
1423 {
1424 if (NULL != cp->core_mq)
2165 { 1425 {
2166 i++; 1426 GNUNET_MQ_notify_sent (last_env,
2167 if (GNUNET_YES != callback (cls, peer, iter)) 1427 &mqm_send_done,
2168 break; 1428 cp);
1429 GNUNET_MQ_send (cp->core_mq,
1430 last_env);
2169 } 1431 }
2170 1432 else
2171 return i; 1433 {
1434 GNUNET_MQ_discard (last_env);
1435 }
1436 }
1437 if (cp->mqm_ready_ptr == mqm)
1438 cp->mqm_ready_ptr = mqm->next;
1439 GNUNET_CONTAINER_DLL_remove (cp->mqm_head,
1440 cp->mqm_tail,
1441 mqm);
1442 GNUNET_free (mqm);
2172} 1443}
2173 1444
2174 1445
2175/** 1446/**
2176 * Iterate all known peers. 1447 * Send the message in @a env to @a cp, overriding queueing logic.
1448 * This function should only be used to send error messages outside
1449 * of flow and congestion control, similar to ICMP. Note that
1450 * the envelope may be silently discarded as well.
2177 * 1451 *
2178 * @param iter Iterator. 1452 * @param cp peer to send the message to
2179 * @param cls Closure for @c iter. 1453 * @param env envelope with the message to send
2180 */ 1454 */
2181void 1455void
2182GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, 1456GCP_send_ooo (struct CadetPeer *cp,
2183 void *cls) 1457 struct GNUNET_MQ_Envelope *env)
2184{ 1458{
2185 GCC_check_connections (); 1459 LOG (GNUNET_ERROR_TYPE_DEBUG,
2186 GNUNET_CONTAINER_multipeermap_iterate (peers, 1460 "Sending message to %s out of management\n",
2187 iter, 1461 GCP_2s (cp));
2188 cls); 1462 if (NULL == cp->core_mq)
2189 GCC_check_connections (); 1463 {
1464 GNUNET_MQ_discard (env);
1465 return;
1466 }
1467 GNUNET_MQ_notify_sent (env,
1468 &mqm_send_done,
1469 cp);
1470 GNUNET_MQ_send (cp->core_mq,
1471 env);
2190} 1472}
2191 1473
2192 1474
2193/**
2194 * Get the static string for a peer ID.
2195 *
2196 * @param peer Peer.
2197 *
2198 * @return Static string for it's ID.
2199 */
2200const char *
2201GCP_2s (const struct CadetPeer *peer)
2202{
2203 if (NULL == peer)
2204 return "(NULL)";
2205 return GNUNET_i2s (GNUNET_PEER_resolve2 (peer->id));
2206}
2207 1475
2208 1476
2209/* end of gnunet-service-cadet_peer.c */ 1477/* end of gnunet-service-cadet-new_peer.c */