diff options
Diffstat (limited to 'src/cadet/gnunet-service-cadet_peer.c')
-rw-r--r-- | src/cadet/gnunet-service-cadet_peer.c | 2219 |
1 files changed, 2219 insertions, 0 deletions
diff --git a/src/cadet/gnunet-service-cadet_peer.c b/src/cadet/gnunet-service-cadet_peer.c new file mode 100644 index 000000000..287d42efe --- /dev/null +++ b/src/cadet/gnunet-service-cadet_peer.c | |||
@@ -0,0 +1,2219 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2013 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | |||
22 | #include "platform.h" | ||
23 | #include "gnunet_util_lib.h" | ||
24 | |||
25 | #include "gnunet_transport_service.h" | ||
26 | #include "gnunet_core_service.h" | ||
27 | #include "gnunet_statistics_service.h" | ||
28 | |||
29 | #include "cadet_protocol.h" | ||
30 | |||
31 | #include "gnunet-service-cadet_peer.h" | ||
32 | #include "gnunet-service-cadet_dht.h" | ||
33 | #include "gnunet-service-cadet_connection.h" | ||
34 | #include "gnunet-service-cadet_tunnel.h" | ||
35 | #include "cadet_path.h" | ||
36 | |||
37 | #define LOG(level, ...) GNUNET_log_from (level,"cadet-p2p",__VA_ARGS__) | ||
38 | |||
39 | /******************************************************************************/ | ||
40 | /******************************** STRUCTS **********************************/ | ||
41 | /******************************************************************************/ | ||
42 | |||
43 | /** | ||
44 | * Struct containing info about a queued transmission to this peer | ||
45 | */ | ||
46 | struct CadetPeerQueue | ||
47 | { | ||
48 | /** | ||
49 | * DLL next | ||
50 | */ | ||
51 | struct CadetPeerQueue *next; | ||
52 | |||
53 | /** | ||
54 | * DLL previous | ||
55 | */ | ||
56 | struct CadetPeerQueue *prev; | ||
57 | |||
58 | /** | ||
59 | * Peer this transmission is directed to. | ||
60 | */ | ||
61 | struct CadetPeer *peer; | ||
62 | |||
63 | /** | ||
64 | * Connection this message belongs to. | ||
65 | */ | ||
66 | struct CadetConnection *c; | ||
67 | |||
68 | /** | ||
69 | * Is FWD in c? | ||
70 | */ | ||
71 | int fwd; | ||
72 | |||
73 | /** | ||
74 | * Pointer to info stucture used as cls. | ||
75 | */ | ||
76 | void *cls; | ||
77 | |||
78 | /** | ||
79 | * Type of message | ||
80 | */ | ||
81 | uint16_t type; | ||
82 | |||
83 | /** | ||
84 | * Type of message | ||
85 | */ | ||
86 | uint16_t payload_type; | ||
87 | |||
88 | /** | ||
89 | * Type of message | ||
90 | */ | ||
91 | uint32_t payload_id; | ||
92 | |||
93 | /** | ||
94 | * Size of the message | ||
95 | */ | ||
96 | size_t size; | ||
97 | |||
98 | /** | ||
99 | * Set when this message starts waiting for CORE. | ||
100 | */ | ||
101 | struct GNUNET_TIME_Absolute start_waiting; | ||
102 | |||
103 | /** | ||
104 | * Function to call on sending. | ||
105 | */ | ||
106 | GMP_sent callback; | ||
107 | |||
108 | /** | ||
109 | * Closure for callback. | ||
110 | */ | ||
111 | void *callback_cls; | ||
112 | }; | ||
113 | |||
114 | /** | ||
115 | * Struct containing all information regarding a given peer | ||
116 | */ | ||
117 | struct CadetPeer | ||
118 | { | ||
119 | /** | ||
120 | * ID of the peer | ||
121 | */ | ||
122 | GNUNET_PEER_Id id; | ||
123 | |||
124 | /** | ||
125 | * Last time we heard from this peer | ||
126 | */ | ||
127 | struct GNUNET_TIME_Absolute last_contact; | ||
128 | |||
129 | /** | ||
130 | * Paths to reach the peer, ordered by ascending hop count | ||
131 | */ | ||
132 | struct CadetPeerPath *path_head; | ||
133 | |||
134 | /** | ||
135 | * Paths to reach the peer, ordered by ascending hop count | ||
136 | */ | ||
137 | struct CadetPeerPath *path_tail; | ||
138 | |||
139 | /** | ||
140 | * Handle to stop the DHT search for paths to this peer | ||
141 | */ | ||
142 | struct GMD_search_handle *search_h; | ||
143 | |||
144 | /** | ||
145 | * Tunnel to this peer, if any. | ||
146 | */ | ||
147 | struct CadetTunnel3 *tunnel; | ||
148 | |||
149 | /** | ||
150 | * Connections that go through this peer, indexed by tid; | ||
151 | */ | ||
152 | struct GNUNET_CONTAINER_MultiHashMap *connections; | ||
153 | |||
154 | /** | ||
155 | * Handle for queued transmissions | ||
156 | */ | ||
157 | struct GNUNET_CORE_TransmitHandle *core_transmit; | ||
158 | |||
159 | /** | ||
160 | * Transmission queue to core DLL head | ||
161 | */ | ||
162 | struct CadetPeerQueue *queue_head; | ||
163 | |||
164 | /** | ||
165 | * Transmission queue to core DLL tail | ||
166 | */ | ||
167 | struct CadetPeerQueue *queue_tail; | ||
168 | |||
169 | /** | ||
170 | * How many messages are in the queue to this peer. | ||
171 | */ | ||
172 | unsigned int queue_n; | ||
173 | |||
174 | /** | ||
175 | * Hello message. | ||
176 | */ | ||
177 | struct GNUNET_HELLO_Message* hello; | ||
178 | }; | ||
179 | |||
180 | |||
181 | /******************************************************************************/ | ||
182 | /******************************* GLOBALS ***********************************/ | ||
183 | /******************************************************************************/ | ||
184 | |||
185 | /** | ||
186 | * Global handle to the statistics service. | ||
187 | */ | ||
188 | extern struct GNUNET_STATISTICS_Handle *stats; | ||
189 | |||
190 | /** | ||
191 | * Local peer own ID (full value). | ||
192 | */ | ||
193 | extern struct GNUNET_PeerIdentity my_full_id; | ||
194 | |||
195 | /** | ||
196 | * Local peer own ID (short) | ||
197 | */ | ||
198 | extern GNUNET_PEER_Id myid; | ||
199 | |||
200 | /** | ||
201 | * Peers known, indexed by PeerIdentity (CadetPeer). | ||
202 | */ | ||
203 | static struct GNUNET_CONTAINER_MultiPeerMap *peers; | ||
204 | |||
205 | /** | ||
206 | * How many peers do we want to remember? | ||
207 | */ | ||
208 | static unsigned long long max_peers; | ||
209 | |||
210 | /** | ||
211 | * Percentage of messages that will be dropped (for test purposes only). | ||
212 | */ | ||
213 | static unsigned long long drop_percent; | ||
214 | |||
215 | /** | ||
216 | * Handle to communicate with core. | ||
217 | */ | ||
218 | static struct GNUNET_CORE_Handle *core_handle; | ||
219 | |||
220 | /** | ||
221 | * Handle to try to start new connections. | ||
222 | */ | ||
223 | static struct GNUNET_TRANSPORT_Handle *transport_handle; | ||
224 | |||
225 | |||
226 | /******************************************************************************/ | ||
227 | /***************************** DEBUG *********************************/ | ||
228 | /******************************************************************************/ | ||
229 | |||
230 | static void | ||
231 | queue_debug (struct CadetPeer *peer) | ||
232 | { | ||
233 | struct CadetPeerQueue *q; | ||
234 | |||
235 | LOG (GNUNET_ERROR_TYPE_DEBUG, "QQQ Messages queued towards %s\n", GMP_2s (peer)); | ||
236 | LOG (GNUNET_ERROR_TYPE_DEBUG, "QQQ core tmt rdy: %p\n", peer->core_transmit); | ||
237 | |||
238 | for (q = peer->queue_head; NULL != q; q = q->next) | ||
239 | { | ||
240 | LOG (GNUNET_ERROR_TYPE_DEBUG, "QQQ - %s %s on %s\n", | ||
241 | GM_m2s (q->type), GM_f2s (q->fwd), GMC_2s (q->c)); | ||
242 | } | ||
243 | |||
244 | LOG (GNUNET_ERROR_TYPE_DEBUG, "QQQ End queued towards %s\n", GMP_2s (peer)); | ||
245 | } | ||
246 | |||
247 | |||
248 | /******************************************************************************/ | ||
249 | /***************************** CORE HELPERS *********************************/ | ||
250 | /******************************************************************************/ | ||
251 | |||
252 | |||
253 | /** | ||
254 | * Iterator to notify all connections of a broken link. Mark connections | ||
255 | * to destroy after all traffic has been sent. | ||
256 | * | ||
257 | * @param cls Closure (peer disconnected). | ||
258 | * @param key Current key code (peer id). | ||
259 | * @param value Value in the hash map (connection). | ||
260 | * | ||
261 | * @return #GNUNET_YES to continue to iterate. | ||
262 | */ | ||
263 | static int | ||
264 | notify_broken (void *cls, | ||
265 | const struct GNUNET_HashCode *key, | ||
266 | void *value) | ||
267 | { | ||
268 | struct CadetPeer *peer = cls; | ||
269 | struct CadetConnection *c = value; | ||
270 | |||
271 | LOG (GNUNET_ERROR_TYPE_DEBUG, " notifying %s due to %s\n", | ||
272 | GMC_2s (c), GMP_2s (peer)); | ||
273 | GMC_notify_broken (c, peer); | ||
274 | |||
275 | return GNUNET_YES; | ||
276 | } | ||
277 | |||
278 | |||
279 | /** | ||
280 | * Remove the direct path to the peer. | ||
281 | * | ||
282 | * @param peer Peer to remove the direct path from. | ||
283 | * | ||
284 | */ | ||
285 | static struct CadetPeerPath * | ||
286 | pop_direct_path (struct CadetPeer *peer) | ||
287 | { | ||
288 | struct CadetPeerPath *iter; | ||
289 | |||
290 | for (iter = peer->path_head; NULL != iter; iter = iter->next) | ||
291 | { | ||
292 | if (2 <= iter->length) | ||
293 | { | ||
294 | GNUNET_CONTAINER_DLL_remove (peer->path_head, peer->path_tail, iter); | ||
295 | return iter; | ||
296 | } | ||
297 | } | ||
298 | return NULL; | ||
299 | } | ||
300 | |||
301 | |||
302 | /******************************************************************************/ | ||
303 | /***************************** CORE CALLBACKS *********************************/ | ||
304 | /******************************************************************************/ | ||
305 | |||
306 | /** | ||
307 | * Method called whenever a given peer connects. | ||
308 | * | ||
309 | * @param cls closure | ||
310 | * @param peer peer identity this notification is about | ||
311 | */ | ||
312 | static void | ||
313 | core_connect (void *cls, const struct GNUNET_PeerIdentity *peer) | ||
314 | { | ||
315 | struct CadetPeer *mp; | ||
316 | struct CadetPeerPath *path; | ||
317 | char own_id[16]; | ||
318 | |||
319 | strncpy (own_id, GNUNET_i2s (&my_full_id), 15); | ||
320 | mp = GMP_get (peer); | ||
321 | if (myid == mp->id) | ||
322 | { | ||
323 | LOG (GNUNET_ERROR_TYPE_INFO, "CONNECTED %s (self)\n", own_id); | ||
324 | path = path_new (1); | ||
325 | } | ||
326 | else | ||
327 | { | ||
328 | LOG (GNUNET_ERROR_TYPE_INFO, "CONNECTED %s <= %s\n", | ||
329 | own_id, GNUNET_i2s (peer)); | ||
330 | path = path_new (2); | ||
331 | path->peers[1] = mp->id; | ||
332 | GNUNET_PEER_change_rc (mp->id, 1); | ||
333 | GNUNET_STATISTICS_update (stats, "# peers", 1, GNUNET_NO); | ||
334 | } | ||
335 | path->peers[0] = myid; | ||
336 | GNUNET_PEER_change_rc (myid, 1); | ||
337 | GMP_add_path (mp, path, GNUNET_YES); | ||
338 | |||
339 | mp->connections = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_YES); | ||
340 | |||
341 | if (NULL != GMP_get_tunnel (mp) && | ||
342 | 0 > GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, peer)) | ||
343 | { | ||
344 | GMP_connect (mp); | ||
345 | } | ||
346 | |||
347 | return; | ||
348 | } | ||
349 | |||
350 | |||
351 | /** | ||
352 | * Method called whenever a peer disconnects. | ||
353 | * | ||
354 | * @param cls closure | ||
355 | * @param peer peer identity this notification is about | ||
356 | */ | ||
357 | static void | ||
358 | core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) | ||
359 | { | ||
360 | struct CadetPeer *p; | ||
361 | struct CadetPeerPath *direct_path; | ||
362 | char own_id[16]; | ||
363 | |||
364 | strncpy (own_id, GNUNET_i2s (&my_full_id), 15); | ||
365 | p = GNUNET_CONTAINER_multipeermap_get (peers, peer); | ||
366 | if (NULL == p) | ||
367 | { | ||
368 | GNUNET_break (0); | ||
369 | return; | ||
370 | } | ||
371 | if (myid == p->id) | ||
372 | LOG (GNUNET_ERROR_TYPE_INFO, "DISCONNECTED %s (self)\n", own_id); | ||
373 | else | ||
374 | LOG (GNUNET_ERROR_TYPE_DEBUG, "DISCONNECTED %s <= %s\n", | ||
375 | own_id, GNUNET_i2s (peer)); | ||
376 | direct_path = pop_direct_path (p); | ||
377 | GNUNET_CONTAINER_multihashmap_iterate (p->connections, ¬ify_broken, p); | ||
378 | GNUNET_CONTAINER_multihashmap_destroy (p->connections); | ||
379 | p->connections = NULL; | ||
380 | if (NULL != p->core_transmit) | ||
381 | { | ||
382 | GNUNET_CORE_notify_transmit_ready_cancel (p->core_transmit); | ||
383 | p->core_transmit = NULL; | ||
384 | } | ||
385 | GNUNET_STATISTICS_update (stats, "# peers", -1, GNUNET_NO); | ||
386 | |||
387 | path_destroy (direct_path); | ||
388 | return; | ||
389 | } | ||
390 | |||
391 | |||
392 | /** | ||
393 | * Functions to handle messages from core | ||
394 | */ | ||
395 | static struct GNUNET_CORE_MessageHandler core_handlers[] = { | ||
396 | {&GMC_handle_create, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE, 0}, | ||
397 | {&GMC_handle_confirm, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK, | ||
398 | sizeof (struct GNUNET_CADET_ConnectionACK)}, | ||
399 | {&GMC_handle_broken, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN, | ||
400 | sizeof (struct GNUNET_CADET_ConnectionBroken)}, | ||
401 | {&GMC_handle_destroy, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY, | ||
402 | sizeof (struct GNUNET_CADET_ConnectionDestroy)}, | ||
403 | {&GMC_handle_ack, GNUNET_MESSAGE_TYPE_CADET_ACK, | ||
404 | sizeof (struct GNUNET_CADET_ACK)}, | ||
405 | {&GMC_handle_poll, GNUNET_MESSAGE_TYPE_CADET_POLL, | ||
406 | sizeof (struct GNUNET_CADET_Poll)}, | ||
407 | {&GMC_handle_encrypted, GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED, 0}, | ||
408 | {&GMC_handle_kx, GNUNET_MESSAGE_TYPE_CADET_KX, 0}, | ||
409 | {NULL, 0, 0} | ||
410 | }; | ||
411 | |||
412 | |||
413 | /** | ||
414 | * To be called on core init/fail. | ||
415 | * | ||
416 | * @param cls Closure (config) | ||
417 | * @param identity the public identity of this peer | ||
418 | */ | ||
419 | static void | ||
420 | core_init (void *cls, | ||
421 | const struct GNUNET_PeerIdentity *identity) | ||
422 | { | ||
423 | const struct GNUNET_CONFIGURATION_Handle *c = cls; | ||
424 | static int i = 0; | ||
425 | |||
426 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Core init\n"); | ||
427 | if (0 != memcmp (identity, &my_full_id, sizeof (my_full_id))) | ||
428 | { | ||
429 | LOG (GNUNET_ERROR_TYPE_ERROR, _("Wrong CORE service\n")); | ||
430 | LOG (GNUNET_ERROR_TYPE_ERROR, " core id %s\n", GNUNET_i2s (identity)); | ||
431 | LOG (GNUNET_ERROR_TYPE_ERROR, " my id %s\n", GNUNET_i2s (&my_full_id)); | ||
432 | GNUNET_CORE_disconnect (core_handle); | ||
433 | core_handle = GNUNET_CORE_connect (c, /* Main configuration */ | ||
434 | NULL, /* Closure passed to CADET functions */ | ||
435 | &core_init, /* Call core_init once connected */ | ||
436 | &core_connect, /* Handle connects */ | ||
437 | &core_disconnect, /* remove peers on disconnects */ | ||
438 | NULL, /* Don't notify about all incoming messages */ | ||
439 | GNUNET_NO, /* For header only in notification */ | ||
440 | NULL, /* Don't notify about all outbound messages */ | ||
441 | GNUNET_NO, /* For header-only out notification */ | ||
442 | core_handlers); /* Register these handlers */ | ||
443 | if (10 < i++) | ||
444 | GNUNET_abort(); | ||
445 | } | ||
446 | GML_start (); | ||
447 | return; | ||
448 | } | ||
449 | |||
450 | |||
451 | /** | ||
452 | * Core callback to write a pre-constructed data packet to core buffer | ||
453 | * | ||
454 | * @param cls Closure (CadetTransmissionDescriptor with data in "data" member). | ||
455 | * @param size Number of bytes available in buf. | ||
456 | * @param buf Where the to write the message. | ||
457 | * | ||
458 | * @return number of bytes written to buf | ||
459 | */ | ||
460 | static size_t | ||
461 | send_core_data_raw (void *cls, size_t size, void *buf) | ||
462 | { | ||
463 | struct GNUNET_MessageHeader *msg = cls; | ||
464 | size_t total_size; | ||
465 | |||
466 | GNUNET_assert (NULL != msg); | ||
467 | total_size = ntohs (msg->size); | ||
468 | |||
469 | if (total_size > size) | ||
470 | { | ||
471 | GNUNET_break (0); | ||
472 | return 0; | ||
473 | } | ||
474 | memcpy (buf, msg, total_size); | ||
475 | GNUNET_free (cls); | ||
476 | return total_size; | ||
477 | } | ||
478 | |||
479 | |||
480 | /** | ||
481 | * Function to send a create connection message to a peer. | ||
482 | * | ||
483 | * @param c Connection to create. | ||
484 | * @param size number of bytes available in buf | ||
485 | * @param buf where the callee should write the message | ||
486 | * @return number of bytes written to buf | ||
487 | */ | ||
488 | static size_t | ||
489 | send_core_connection_create (struct CadetConnection *c, size_t size, void *buf) | ||
490 | { | ||
491 | struct GNUNET_CADET_ConnectionCreate *msg; | ||
492 | struct GNUNET_PeerIdentity *peer_ptr; | ||
493 | const struct CadetPeerPath *p = GMC_get_path (c); | ||
494 | size_t size_needed; | ||
495 | int i; | ||
496 | |||
497 | if (NULL == p) | ||
498 | return 0; | ||
499 | |||
500 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending CONNECTION CREATE...\n"); | ||
501 | size_needed = | ||
502 | sizeof (struct GNUNET_CADET_ConnectionCreate) + | ||
503 | p->length * sizeof (struct GNUNET_PeerIdentity); | ||
504 | |||
505 | if (size < size_needed || NULL == buf) | ||
506 | { | ||
507 | GNUNET_break (0); | ||
508 | return 0; | ||
509 | } | ||
510 | msg = (struct GNUNET_CADET_ConnectionCreate *) buf; | ||
511 | msg->header.size = htons (size_needed); | ||
512 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE); | ||
513 | msg->cid = *GMC_get_id (c); | ||
514 | |||
515 | peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1]; | ||
516 | for (i = 0; i < p->length; i++) | ||
517 | { | ||
518 | GNUNET_PEER_resolve (p->peers[i], peer_ptr++); | ||
519 | } | ||
520 | |||
521 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
522 | "CONNECTION CREATE (%u bytes long) sent!\n", | ||
523 | size_needed); | ||
524 | return size_needed; | ||
525 | } | ||
526 | |||
527 | |||
528 | /** | ||
529 | * Creates a path ack message in buf and frees all unused resources. | ||
530 | * | ||
531 | * @param c Connection to send an ACK on. | ||
532 | * @param size number of bytes available in buf | ||
533 | * @param buf where the callee should write the message | ||
534 | * | ||
535 | * @return number of bytes written to buf | ||
536 | */ | ||
537 | static size_t | ||
538 | send_core_connection_ack (struct CadetConnection *c, size_t size, void *buf) | ||
539 | { | ||
540 | struct GNUNET_CADET_ConnectionACK *msg = buf; | ||
541 | |||
542 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending CONNECTION ACK...\n"); | ||
543 | if (sizeof (struct GNUNET_CADET_ConnectionACK) > size) | ||
544 | { | ||
545 | GNUNET_break (0); | ||
546 | return 0; | ||
547 | } | ||
548 | msg->header.size = htons (sizeof (struct GNUNET_CADET_ConnectionACK)); | ||
549 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK); | ||
550 | msg->cid = *GMC_get_id (c); | ||
551 | |||
552 | LOG (GNUNET_ERROR_TYPE_DEBUG, "CONNECTION ACK sent!\n"); | ||
553 | return sizeof (struct GNUNET_CADET_ConnectionACK); | ||
554 | } | ||
555 | |||
556 | |||
557 | /******************************************************************************/ | ||
558 | /******************************** STATIC ***********************************/ | ||
559 | /******************************************************************************/ | ||
560 | |||
561 | |||
562 | /** | ||
563 | * Get priority for a queued message. | ||
564 | * | ||
565 | * @param q Queued message | ||
566 | * | ||
567 | * @return CORE priority to use. | ||
568 | */ | ||
569 | static enum GNUNET_CORE_Priority | ||
570 | get_priority (struct CadetPeerQueue *q) | ||
571 | { | ||
572 | enum GNUNET_CORE_Priority low; | ||
573 | enum GNUNET_CORE_Priority high; | ||
574 | |||
575 | if (NULL == q) | ||
576 | { | ||
577 | GNUNET_break (0); | ||
578 | return GNUNET_CORE_PRIO_BACKGROUND; | ||
579 | } | ||
580 | |||
581 | /* Relayed traffic has lower priority, our own traffic has higher */ | ||
582 | if (NULL == q->c || GNUNET_NO == GMC_is_origin (q->c, q->fwd)) | ||
583 | { | ||
584 | low = GNUNET_CORE_PRIO_BEST_EFFORT; | ||
585 | high = GNUNET_CORE_PRIO_URGENT; | ||
586 | } | ||
587 | else | ||
588 | { | ||
589 | low = GNUNET_CORE_PRIO_URGENT; | ||
590 | high = GNUNET_CORE_PRIO_CRITICAL_CONTROL; | ||
591 | } | ||
592 | |||
593 | /* Bulky payload has lower priority, control traffic has higher. */ | ||
594 | if (GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED == q->type) | ||
595 | return low; | ||
596 | else | ||
597 | return high; | ||
598 | } | ||
599 | |||
600 | |||
601 | /** | ||
602 | * Iterator over tunnel hash map entries to destroy the tunnel during shutdown. | ||
603 | * | ||
604 | * @param cls closure | ||
605 | * @param key current key code | ||
606 | * @param value value in the hash map | ||
607 | * @return #GNUNET_YES if we should continue to iterate, | ||
608 | * #GNUNET_NO if not. | ||
609 | */ | ||
610 | static int | ||
611 | shutdown_tunnel (void *cls, | ||
612 | const struct GNUNET_PeerIdentity *key, | ||
613 | void *value) | ||
614 | { | ||
615 | struct CadetPeer *p = value; | ||
616 | struct CadetTunnel3 *t = p->tunnel; | ||
617 | |||
618 | if (NULL != t) | ||
619 | GMT_destroy (t); | ||
620 | return GNUNET_YES; | ||
621 | } | ||
622 | |||
623 | |||
624 | /** | ||
625 | * Destroy the peer_info and free any allocated resources linked to it | ||
626 | * | ||
627 | * @param peer The peer_info to destroy. | ||
628 | * | ||
629 | * @return GNUNET_OK on success | ||
630 | */ | ||
631 | static int | ||
632 | peer_destroy (struct CadetPeer *peer) | ||
633 | { | ||
634 | struct GNUNET_PeerIdentity id; | ||
635 | struct CadetPeerPath *p; | ||
636 | struct CadetPeerPath *nextp; | ||
637 | |||
638 | GNUNET_PEER_resolve (peer->id, &id); | ||
639 | GNUNET_PEER_change_rc (peer->id, -1); | ||
640 | |||
641 | LOG (GNUNET_ERROR_TYPE_WARNING, "destroying peer %s\n", GNUNET_i2s (&id)); | ||
642 | |||
643 | if (GNUNET_YES != | ||
644 | GNUNET_CONTAINER_multipeermap_remove (peers, &id, peer)) | ||
645 | { | ||
646 | GNUNET_break (0); | ||
647 | LOG (GNUNET_ERROR_TYPE_WARNING, " not in peermap!!\n"); | ||
648 | } | ||
649 | if (NULL != peer->search_h) | ||
650 | { | ||
651 | GMD_search_stop (peer->search_h); | ||
652 | } | ||
653 | p = peer->path_head; | ||
654 | while (NULL != p) | ||
655 | { | ||
656 | nextp = p->next; | ||
657 | GNUNET_CONTAINER_DLL_remove (peer->path_head, peer->path_tail, p); | ||
658 | path_destroy (p); | ||
659 | p = nextp; | ||
660 | } | ||
661 | GMT_destroy_empty (peer->tunnel); | ||
662 | GNUNET_free (peer); | ||
663 | return GNUNET_OK; | ||
664 | } | ||
665 | |||
666 | |||
667 | /** | ||
668 | * Returns if peer is used (has a tunnel or is neighbor). | ||
669 | * | ||
670 | * @param peer Peer to check. | ||
671 | * | ||
672 | * @return #GNUNET_YES if peer is in use. | ||
673 | */ | ||
674 | static int | ||
675 | peer_is_used (struct CadetPeer *peer) | ||
676 | { | ||
677 | struct CadetPeerPath *p; | ||
678 | |||
679 | if (NULL != peer->tunnel) | ||
680 | return GNUNET_YES; | ||
681 | |||
682 | for (p = peer->path_head; NULL != p; p = p->next) | ||
683 | { | ||
684 | if (p->length < 3) | ||
685 | return GNUNET_YES; | ||
686 | } | ||
687 | return GNUNET_NO; | ||
688 | } | ||
689 | |||
690 | |||
691 | /** | ||
692 | * Iterator over all the peers to get the oldest timestamp. | ||
693 | * | ||
694 | * @param cls Closure (unsued). | ||
695 | * @param key ID of the peer. | ||
696 | * @param value Peer_Info of the peer. | ||
697 | */ | ||
698 | static int | ||
699 | peer_get_oldest (void *cls, | ||
700 | const struct GNUNET_PeerIdentity *key, | ||
701 | void *value) | ||
702 | { | ||
703 | struct CadetPeer *p = value; | ||
704 | struct GNUNET_TIME_Absolute *abs = cls; | ||
705 | |||
706 | /* Don't count active peers */ | ||
707 | if (GNUNET_YES == peer_is_used (p)) | ||
708 | return GNUNET_YES; | ||
709 | |||
710 | if (abs->abs_value_us < p->last_contact.abs_value_us) | ||
711 | abs->abs_value_us = p->last_contact.abs_value_us; | ||
712 | |||
713 | return GNUNET_YES; | ||
714 | } | ||
715 | |||
716 | |||
717 | /** | ||
718 | * Iterator over all the peers to remove the oldest entry. | ||
719 | * | ||
720 | * @param cls Closure (unsued). | ||
721 | * @param key ID of the peer. | ||
722 | * @param value Peer_Info of the peer. | ||
723 | */ | ||
724 | static int | ||
725 | peer_timeout (void *cls, | ||
726 | const struct GNUNET_PeerIdentity *key, | ||
727 | void *value) | ||
728 | { | ||
729 | struct CadetPeer *p = value; | ||
730 | struct GNUNET_TIME_Absolute *abs = cls; | ||
731 | |||
732 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
733 | "peer %s timeout\n", GNUNET_i2s (key)); | ||
734 | |||
735 | if (p->last_contact.abs_value_us == abs->abs_value_us && | ||
736 | GNUNET_NO == peer_is_used (p)) | ||
737 | { | ||
738 | peer_destroy (p); | ||
739 | return GNUNET_NO; | ||
740 | } | ||
741 | return GNUNET_YES; | ||
742 | } | ||
743 | |||
744 | |||
745 | /** | ||
746 | * Delete oldest unused peer. | ||
747 | */ | ||
748 | static void | ||
749 | peer_delete_oldest (void) | ||
750 | { | ||
751 | struct GNUNET_TIME_Absolute abs; | ||
752 | |||
753 | abs = GNUNET_TIME_UNIT_FOREVER_ABS; | ||
754 | |||
755 | GNUNET_CONTAINER_multipeermap_iterate (peers, | ||
756 | &peer_get_oldest, | ||
757 | &abs); | ||
758 | GNUNET_CONTAINER_multipeermap_iterate (peers, | ||
759 | &peer_timeout, | ||
760 | &abs); | ||
761 | } | ||
762 | |||
763 | |||
764 | /** | ||
765 | * Choose the best (yet unused) path towards a peer, | ||
766 | * considering the tunnel properties. | ||
767 | * | ||
768 | * @param peer The destination peer. | ||
769 | * | ||
770 | * @return Best current known path towards the peer, if any. | ||
771 | */ | ||
772 | static struct CadetPeerPath * | ||
773 | peer_get_best_path (const struct CadetPeer *peer) | ||
774 | { | ||
775 | struct CadetPeerPath *best_p; | ||
776 | struct CadetPeerPath *p; | ||
777 | unsigned int best_cost; | ||
778 | unsigned int cost; | ||
779 | |||
780 | best_cost = UINT_MAX; | ||
781 | best_p = NULL; | ||
782 | for (p = peer->path_head; NULL != p; p = p->next) | ||
783 | { | ||
784 | if (GNUNET_NO == path_is_valid (p)) | ||
785 | continue; /* Don't use invalid paths. */ | ||
786 | if (GNUNET_YES == GMT_is_path_used (peer->tunnel, p)) | ||
787 | continue; /* If path is already in use, skip it. */ | ||
788 | |||
789 | if ((cost = GMT_get_path_cost (peer->tunnel, p)) < best_cost) | ||
790 | { | ||
791 | best_cost = cost; | ||
792 | best_p = p; | ||
793 | } | ||
794 | } | ||
795 | return best_p; | ||
796 | } | ||
797 | |||
798 | |||
799 | /** | ||
800 | * Is this queue element sendable? | ||
801 | * | ||
802 | * - All management traffic is always sendable. | ||
803 | * - For payload traffic, check the connection flow control. | ||
804 | * | ||
805 | * @param q Queue element to inspect. | ||
806 | * | ||
807 | * @return #GNUNET_YES if it is sendable, #GNUNET_NO otherwise. | ||
808 | */ | ||
809 | static int | ||
810 | queue_is_sendable (struct CadetPeerQueue *q) | ||
811 | { | ||
812 | /* Is PID-independent? */ | ||
813 | switch (q->type) | ||
814 | { | ||
815 | case GNUNET_MESSAGE_TYPE_CADET_ACK: | ||
816 | case GNUNET_MESSAGE_TYPE_CADET_POLL: | ||
817 | case GNUNET_MESSAGE_TYPE_CADET_KX: | ||
818 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE: | ||
819 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK: | ||
820 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY: | ||
821 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN: | ||
822 | return GNUNET_YES; | ||
823 | |||
824 | case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED: | ||
825 | break; | ||
826 | |||
827 | default: | ||
828 | GNUNET_break (0); | ||
829 | } | ||
830 | |||
831 | return GMC_is_sendable (q->c, q->fwd); | ||
832 | } | ||
833 | |||
834 | |||
835 | /** | ||
836 | * Get first sendable message. | ||
837 | * | ||
838 | * @param peer The destination peer. | ||
839 | * | ||
840 | * @return First transmittable message, if any. Otherwise, NULL. | ||
841 | */ | ||
842 | static struct CadetPeerQueue * | ||
843 | peer_get_first_message (const struct CadetPeer *peer) | ||
844 | { | ||
845 | struct CadetPeerQueue *q; | ||
846 | |||
847 | for (q = peer->queue_head; NULL != q; q = q->next) | ||
848 | { | ||
849 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking %p towards %s\n", q, GMC_2s (q->c)); | ||
850 | if (queue_is_sendable (q)) | ||
851 | return q; | ||
852 | } | ||
853 | |||
854 | return NULL; | ||
855 | } | ||
856 | |||
857 | |||
858 | /** | ||
859 | * Function to process paths received for a new peer addition. The recorded | ||
860 | * paths form the initial tunnel, which can be optimized later. | ||
861 | * Called on each result obtained for the DHT search. | ||
862 | * | ||
863 | * @param cls closure | ||
864 | * @param path | ||
865 | */ | ||
866 | static void | ||
867 | search_handler (void *cls, const struct CadetPeerPath *path) | ||
868 | { | ||
869 | struct CadetPeer *peer = cls; | ||
870 | unsigned int connection_count; | ||
871 | |||
872 | GMP_add_path_to_all (path, GNUNET_NO); | ||
873 | |||
874 | /* Count connections */ | ||
875 | connection_count = GMT_count_connections (peer->tunnel); | ||
876 | |||
877 | /* If we already have 3 (or more (?!)) connections, it's enough */ | ||
878 | if (3 <= connection_count) | ||
879 | return; | ||
880 | |||
881 | if (CADET_TUNNEL3_SEARCHING == GMT_get_cstate (peer->tunnel)) | ||
882 | { | ||
883 | LOG (GNUNET_ERROR_TYPE_DEBUG, " ... connect!\n"); | ||
884 | GMP_connect (peer); | ||
885 | } | ||
886 | return; | ||
887 | } | ||
888 | |||
889 | |||
890 | |||
891 | /** | ||
892 | * Core callback to write a queued packet to core buffer | ||
893 | * | ||
894 | * @param cls Closure (peer info). | ||
895 | * @param size Number of bytes available in buf. | ||
896 | * @param buf Where the to write the message. | ||
897 | * | ||
898 | * @return number of bytes written to buf | ||
899 | */ | ||
900 | static size_t | ||
901 | queue_send (void *cls, size_t size, void *buf) | ||
902 | { | ||
903 | struct CadetPeer *peer = cls; | ||
904 | struct CadetConnection *c; | ||
905 | struct CadetPeerQueue *queue; | ||
906 | const struct GNUNET_PeerIdentity *dst_id; | ||
907 | size_t data_size; | ||
908 | uint32_t pid; | ||
909 | |||
910 | pid = 0; | ||
911 | peer->core_transmit = NULL; | ||
912 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Queue send towards %s (max %u)\n", | ||
913 | GMP_2s (peer), size); | ||
914 | |||
915 | if (NULL == buf || 0 == size) | ||
916 | { | ||
917 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Buffer size 0.\n"); | ||
918 | return 0; | ||
919 | } | ||
920 | |||
921 | /* Initialize */ | ||
922 | queue = peer_get_first_message (peer); | ||
923 | if (NULL == queue) | ||
924 | { | ||
925 | GNUNET_assert (0); /* Core tmt_rdy should've been canceled */ | ||
926 | return 0; | ||
927 | } | ||
928 | c = queue->c; | ||
929 | |||
930 | dst_id = GNUNET_PEER_resolve2 (peer->id); | ||
931 | LOG (GNUNET_ERROR_TYPE_DEBUG, " on connection %s %s\n", | ||
932 | GMC_2s (c), GM_f2s(queue->fwd)); | ||
933 | /* Check if buffer size is enough for the message */ | ||
934 | if (queue->size > size) | ||
935 | { | ||
936 | LOG (GNUNET_ERROR_TYPE_WARNING, "not enough room (%u vs %u), reissue\n", | ||
937 | queue->size, size); | ||
938 | peer->core_transmit = | ||
939 | GNUNET_CORE_notify_transmit_ready (core_handle, | ||
940 | GNUNET_NO, get_priority (queue), | ||
941 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
942 | dst_id, | ||
943 | queue->size, | ||
944 | &queue_send, | ||
945 | peer); | ||
946 | return 0; | ||
947 | } | ||
948 | LOG (GNUNET_ERROR_TYPE_DEBUG, " size %u ok\n", queue->size); | ||
949 | |||
950 | /* Fill buf */ | ||
951 | switch (queue->type) | ||
952 | { | ||
953 | case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED: | ||
954 | pid = GMC_get_pid (queue->c, queue->fwd); | ||
955 | LOG (GNUNET_ERROR_TYPE_DEBUG, " payload ID %u\n", pid); | ||
956 | data_size = send_core_data_raw (queue->cls, size, buf); | ||
957 | ((struct GNUNET_CADET_Encrypted *) buf)->pid = htonl (pid); | ||
958 | break; | ||
959 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY: | ||
960 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN: | ||
961 | case GNUNET_MESSAGE_TYPE_CADET_KX: | ||
962 | case GNUNET_MESSAGE_TYPE_CADET_ACK: | ||
963 | case GNUNET_MESSAGE_TYPE_CADET_POLL: | ||
964 | LOG (GNUNET_ERROR_TYPE_DEBUG, " raw %s\n", GM_m2s (queue->type)); | ||
965 | data_size = send_core_data_raw (queue->cls, size, buf); | ||
966 | break; | ||
967 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE: | ||
968 | LOG (GNUNET_ERROR_TYPE_DEBUG, " path create\n"); | ||
969 | if (GMC_is_origin (c, GNUNET_YES)) | ||
970 | data_size = send_core_connection_create (queue->c, size, buf); | ||
971 | else | ||
972 | data_size = send_core_data_raw (queue->cls, size, buf); | ||
973 | break; | ||
974 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK: | ||
975 | LOG (GNUNET_ERROR_TYPE_DEBUG, " path ack\n"); | ||
976 | if (GMC_is_origin (c, GNUNET_NO) || | ||
977 | GMC_is_origin (c, GNUNET_YES)) | ||
978 | data_size = send_core_connection_ack (queue->c, size, buf); | ||
979 | else | ||
980 | data_size = send_core_data_raw (queue->cls, size, buf); | ||
981 | break; | ||
982 | case GNUNET_MESSAGE_TYPE_CADET_DATA: | ||
983 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE: | ||
984 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY: | ||
985 | /* This should be encapsulted */ | ||
986 | GNUNET_break (0); | ||
987 | data_size = 0; | ||
988 | break; | ||
989 | default: | ||
990 | GNUNET_break (0); | ||
991 | LOG (GNUNET_ERROR_TYPE_WARNING, " type unknown: %u\n", queue->type); | ||
992 | data_size = 0; | ||
993 | } | ||
994 | |||
995 | if (0 < drop_percent && | ||
996 | GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 101) < drop_percent) | ||
997 | { | ||
998 | LOG (GNUNET_ERROR_TYPE_WARNING, "DD %s on connection %s\n", | ||
999 | GM_m2s (queue->type), GMC_2s (c)); | ||
1000 | data_size = 0; | ||
1001 | } | ||
1002 | else | ||
1003 | { | ||
1004 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
1005 | "snd %s (%s %u) on connection %s (%p) %s (size %u)\n", | ||
1006 | GM_m2s (queue->type), GM_m2s (queue->payload_type), | ||
1007 | queue->payload_type, GMC_2s (c), c, GM_f2s (queue->fwd), data_size); | ||
1008 | } | ||
1009 | |||
1010 | /* Free queue, but cls was freed by send_core_* */ | ||
1011 | GMP_queue_destroy (queue, GNUNET_NO, GNUNET_YES, pid); | ||
1012 | |||
1013 | /* If more data in queue, send next */ | ||
1014 | queue = peer_get_first_message (peer); | ||
1015 | if (NULL != queue) | ||
1016 | { | ||
1017 | LOG (GNUNET_ERROR_TYPE_DEBUG, " more data!\n"); | ||
1018 | if (NULL == peer->core_transmit) | ||
1019 | { | ||
1020 | peer->core_transmit = | ||
1021 | GNUNET_CORE_notify_transmit_ready (core_handle, | ||
1022 | GNUNET_NO, get_priority (queue), | ||
1023 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
1024 | dst_id, | ||
1025 | queue->size, | ||
1026 | &queue_send, | ||
1027 | peer); | ||
1028 | queue->start_waiting = GNUNET_TIME_absolute_get (); | ||
1029 | } | ||
1030 | else | ||
1031 | { | ||
1032 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1033 | "* tmt rdy called somewhere else\n"); | ||
1034 | } | ||
1035 | // GMC_start_poll (); FIXME needed? | ||
1036 | } | ||
1037 | else | ||
1038 | { | ||
1039 | // GMC_stop_poll(); FIXME needed? | ||
1040 | } | ||
1041 | |||
1042 | LOG (GNUNET_ERROR_TYPE_DEBUG, " return %d\n", data_size); | ||
1043 | queue_debug (peer); | ||
1044 | return data_size; | ||
1045 | } | ||
1046 | |||
1047 | |||
1048 | /******************************************************************************/ | ||
1049 | /******************************** API ***********************************/ | ||
1050 | /******************************************************************************/ | ||
1051 | |||
1052 | |||
1053 | /** | ||
1054 | * Free a transmission that was already queued with all resources | ||
1055 | * associated to the request. | ||
1056 | * | ||
1057 | * @param queue Queue handler to cancel. | ||
1058 | * @param clear_cls Is it necessary to free associated cls? | ||
1059 | * @param sent Was it really sent? (Could have been canceled) | ||
1060 | * @param pid PID, if relevant (was sent and was a payload message). | ||
1061 | */ | ||
1062 | void | ||
1063 | GMP_queue_destroy (struct CadetPeerQueue *queue, int clear_cls, | ||
1064 | int sent, uint32_t pid) | ||
1065 | { | ||
1066 | struct CadetPeer *peer; | ||
1067 | |||
1068 | peer = queue->peer; | ||
1069 | |||
1070 | if (GNUNET_YES == clear_cls) | ||
1071 | { | ||
1072 | LOG (GNUNET_ERROR_TYPE_DEBUG, "queue destroy type %s\n", | ||
1073 | GM_m2s (queue->type)); | ||
1074 | switch (queue->type) | ||
1075 | { | ||
1076 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY: | ||
1077 | LOG (GNUNET_ERROR_TYPE_INFO, "destroying a DESTROY message\n"); | ||
1078 | /* fall through */ | ||
1079 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK: | ||
1080 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE: | ||
1081 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN: | ||
1082 | case GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE: | ||
1083 | case GNUNET_MESSAGE_TYPE_CADET_KX: | ||
1084 | case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED: | ||
1085 | case GNUNET_MESSAGE_TYPE_CADET_ACK: | ||
1086 | case GNUNET_MESSAGE_TYPE_CADET_POLL: | ||
1087 | GNUNET_free_non_null (queue->cls); | ||
1088 | break; | ||
1089 | |||
1090 | default: | ||
1091 | GNUNET_break (0); | ||
1092 | LOG (GNUNET_ERROR_TYPE_ERROR, " type %s unknown!\n", | ||
1093 | GM_m2s (queue->type)); | ||
1094 | } | ||
1095 | } | ||
1096 | GNUNET_CONTAINER_DLL_remove (peer->queue_head, peer->queue_tail, queue); | ||
1097 | |||
1098 | if (queue->type != GNUNET_MESSAGE_TYPE_CADET_ACK && | ||
1099 | queue->type != GNUNET_MESSAGE_TYPE_CADET_POLL) | ||
1100 | { | ||
1101 | peer->queue_n--; | ||
1102 | } | ||
1103 | |||
1104 | if (NULL != queue->callback) | ||
1105 | { | ||
1106 | LOG (GNUNET_ERROR_TYPE_DEBUG, " calling callback\n"); | ||
1107 | queue->callback (queue->callback_cls, | ||
1108 | queue->c, sent, queue->type, pid, | ||
1109 | queue->fwd, queue->size, | ||
1110 | GNUNET_TIME_absolute_get_duration (queue->start_waiting)); | ||
1111 | } | ||
1112 | |||
1113 | if (NULL == peer_get_first_message (peer) && NULL != peer->core_transmit) | ||
1114 | { | ||
1115 | GNUNET_CORE_notify_transmit_ready_cancel (peer->core_transmit); | ||
1116 | peer->core_transmit = NULL; | ||
1117 | } | ||
1118 | |||
1119 | GNUNET_free (queue); | ||
1120 | } | ||
1121 | |||
1122 | |||
1123 | /** | ||
1124 | * @brief Queue and pass message to core when possible. | ||
1125 | * | ||
1126 | * @param peer Peer towards which to queue the message. | ||
1127 | * @param cls Closure (@c type dependant). It will be used by queue_send to | ||
1128 | * build the message to be sent if not already prebuilt. | ||
1129 | * @param type Type of the message, 0 for a raw message. | ||
1130 | * @param size Size of the message. | ||
1131 | * @param c Connection this message belongs to (can be NULL). | ||
1132 | * @param fwd Is this a message going root->dest? (FWD ACK are NOT FWD!) | ||
1133 | * @param cont Continuation to be called once CORE has taken the message. | ||
1134 | * @param cont_cls Closure for @c cont. | ||
1135 | * | ||
1136 | * @return Handle to cancel the message before it is sent. Once cont is called | ||
1137 | * message has been sent and therefore the handle is no longer valid. | ||
1138 | */ | ||
1139 | struct CadetPeerQueue * | ||
1140 | GMP_queue_add (struct CadetPeer *peer, void *cls, uint16_t type, | ||
1141 | uint16_t payload_type, uint32_t payload_id, size_t size, | ||
1142 | struct CadetConnection *c, int fwd, | ||
1143 | GMP_sent cont, void *cont_cls) | ||
1144 | { | ||
1145 | struct CadetPeerQueue *queue; | ||
1146 | int priority; | ||
1147 | int call_core; | ||
1148 | |||
1149 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
1150 | "que %s (%s %u) on connection %s (%p) %s towards %s (size %u)\n", | ||
1151 | GM_m2s (type), GM_m2s (payload_type), payload_id, | ||
1152 | GMC_2s (c), c, GM_f2s (fwd), GMP_2s (peer), size); | ||
1153 | |||
1154 | if (NULL == peer->connections) | ||
1155 | { | ||
1156 | /* We are not connected to this peer, ignore request. */ | ||
1157 | LOG (GNUNET_ERROR_TYPE_WARNING, "%s not a neighbor\n", GMP_2s (peer)); | ||
1158 | GNUNET_STATISTICS_update (stats, "# messages dropped due to wrong hop", 1, | ||
1159 | GNUNET_NO); | ||
1160 | return NULL; | ||
1161 | } | ||
1162 | |||
1163 | priority = 0; | ||
1164 | |||
1165 | if (GNUNET_MESSAGE_TYPE_CADET_POLL == type || | ||
1166 | GNUNET_MESSAGE_TYPE_CADET_ACK == type) | ||
1167 | { | ||
1168 | priority = 100; | ||
1169 | } | ||
1170 | |||
1171 | LOG (GNUNET_ERROR_TYPE_DEBUG, "priority %d\n", priority); | ||
1172 | |||
1173 | call_core = NULL == c ? GNUNET_YES : GMC_is_sendable (c, fwd); | ||
1174 | queue = GNUNET_new (struct CadetPeerQueue); | ||
1175 | queue->cls = cls; | ||
1176 | queue->type = type; | ||
1177 | queue->payload_type = payload_type; | ||
1178 | queue->payload_id = payload_id; | ||
1179 | queue->size = size; | ||
1180 | queue->peer = peer; | ||
1181 | queue->c = c; | ||
1182 | queue->fwd = fwd; | ||
1183 | queue->callback = cont; | ||
1184 | queue->callback_cls = cont_cls; | ||
1185 | if (100 > priority) | ||
1186 | { | ||
1187 | GNUNET_CONTAINER_DLL_insert_tail (peer->queue_head, peer->queue_tail, queue); | ||
1188 | peer->queue_n++; | ||
1189 | } | ||
1190 | else | ||
1191 | { | ||
1192 | GNUNET_CONTAINER_DLL_insert (peer->queue_head, peer->queue_tail, queue); | ||
1193 | call_core = GNUNET_YES; | ||
1194 | } | ||
1195 | |||
1196 | if (NULL == peer->core_transmit && GNUNET_YES == call_core) | ||
1197 | { | ||
1198 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1199 | "calling core tmt rdy towards %s for %u bytes\n", | ||
1200 | GMP_2s (peer), size); | ||
1201 | peer->core_transmit = | ||
1202 | GNUNET_CORE_notify_transmit_ready (core_handle, | ||
1203 | GNUNET_NO, get_priority (queue), | ||
1204 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
1205 | GNUNET_PEER_resolve2 (peer->id), | ||
1206 | size, | ||
1207 | &queue_send, | ||
1208 | peer); | ||
1209 | queue->start_waiting = GNUNET_TIME_absolute_get (); | ||
1210 | } | ||
1211 | else if (GNUNET_NO == call_core) | ||
1212 | { | ||
1213 | LOG (GNUNET_ERROR_TYPE_DEBUG, "core tmt rdy towards %s not needed\n", | ||
1214 | GMP_2s (peer)); | ||
1215 | |||
1216 | } | ||
1217 | else | ||
1218 | { | ||
1219 | LOG (GNUNET_ERROR_TYPE_DEBUG, "core tmt rdy towards %s already called\n", | ||
1220 | GMP_2s (peer)); | ||
1221 | |||
1222 | } | ||
1223 | queue_debug (peer); | ||
1224 | return queue; | ||
1225 | } | ||
1226 | |||
1227 | |||
1228 | /** | ||
1229 | * Cancel all queued messages to a peer that belong to a certain connection. | ||
1230 | * | ||
1231 | * @param peer Peer towards whom to cancel. | ||
1232 | * @param c Connection whose queued messages to cancel. Might be destroyed by | ||
1233 | * the sent continuation call. | ||
1234 | */ | ||
1235 | void | ||
1236 | GMP_queue_cancel (struct CadetPeer *peer, struct CadetConnection *c) | ||
1237 | { | ||
1238 | struct CadetPeerQueue *q; | ||
1239 | struct CadetPeerQueue *next; | ||
1240 | struct CadetPeerQueue *prev; | ||
1241 | |||
1242 | for (q = peer->queue_head; NULL != q; q = next) | ||
1243 | { | ||
1244 | prev = q->prev; | ||
1245 | if (q->c == c) | ||
1246 | { | ||
1247 | LOG (GNUNET_ERROR_TYPE_DEBUG, "GMP queue cancel %s\n", GM_m2s (q->type)); | ||
1248 | if (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY != q->type) | ||
1249 | { | ||
1250 | q->c = NULL; | ||
1251 | } | ||
1252 | else | ||
1253 | { | ||
1254 | GMP_queue_destroy (q, GNUNET_YES, GNUNET_NO, 0); | ||
1255 | } | ||
1256 | |||
1257 | /* Get next from prev, q->next might be already freed: | ||
1258 | * queue destroy -> callback -> GMC_destroy -> cancel_queues -> here | ||
1259 | */ | ||
1260 | if (NULL == prev) | ||
1261 | next = peer->queue_head; | ||
1262 | else | ||
1263 | next = prev->next; | ||
1264 | } | ||
1265 | else | ||
1266 | { | ||
1267 | next = q->next; | ||
1268 | } | ||
1269 | } | ||
1270 | if (NULL == peer->queue_head) | ||
1271 | { | ||
1272 | if (NULL != peer->core_transmit) | ||
1273 | { | ||
1274 | GNUNET_CORE_notify_transmit_ready_cancel (peer->core_transmit); | ||
1275 | peer->core_transmit = NULL; | ||
1276 | } | ||
1277 | } | ||
1278 | } | ||
1279 | |||
1280 | |||
1281 | /** | ||
1282 | * Get the first transmittable message for a connection. | ||
1283 | * | ||
1284 | * @param peer Neighboring peer. | ||
1285 | * @param c Connection. | ||
1286 | * | ||
1287 | * @return First transmittable message. | ||
1288 | */ | ||
1289 | static struct CadetPeerQueue * | ||
1290 | connection_get_first_message (struct CadetPeer *peer, struct CadetConnection *c) | ||
1291 | { | ||
1292 | struct CadetPeerQueue *q; | ||
1293 | |||
1294 | for (q = peer->queue_head; NULL != q; q = q->next) | ||
1295 | { | ||
1296 | if (q->c != c) | ||
1297 | continue; | ||
1298 | if (queue_is_sendable (q)) | ||
1299 | { | ||
1300 | LOG (GNUNET_ERROR_TYPE_DEBUG, " sendable!!\n"); | ||
1301 | return q; | ||
1302 | } | ||
1303 | LOG (GNUNET_ERROR_TYPE_DEBUG, " not sendable\n"); | ||
1304 | } | ||
1305 | |||
1306 | return NULL; | ||
1307 | } | ||
1308 | |||
1309 | |||
1310 | /** | ||
1311 | * Get the first message for a connection and unqueue it. | ||
1312 | * | ||
1313 | * @param peer Neighboring peer. | ||
1314 | * @param c Connection. | ||
1315 | * | ||
1316 | * @return First message for this connection. | ||
1317 | */ | ||
1318 | struct GNUNET_MessageHeader * | ||
1319 | GMP_connection_pop (struct CadetPeer *peer, struct CadetConnection *c) | ||
1320 | { | ||
1321 | struct CadetPeerQueue *q; | ||
1322 | struct CadetPeerQueue *next; | ||
1323 | struct GNUNET_MessageHeader *msg; | ||
1324 | |||
1325 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection pop on %s\n", GMC_2s (c)); | ||
1326 | for (q = peer->queue_head; NULL != q; q = next) | ||
1327 | { | ||
1328 | next = q->next; | ||
1329 | if (q->c != c) | ||
1330 | continue; | ||
1331 | switch (q->type) | ||
1332 | { | ||
1333 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE: | ||
1334 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK: | ||
1335 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY: | ||
1336 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN: | ||
1337 | case GNUNET_MESSAGE_TYPE_CADET_ACK: | ||
1338 | case GNUNET_MESSAGE_TYPE_CADET_POLL: | ||
1339 | GMP_queue_destroy (q, GNUNET_YES, GNUNET_NO, 0); | ||
1340 | continue; | ||
1341 | |||
1342 | case GNUNET_MESSAGE_TYPE_CADET_KX: | ||
1343 | case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED: | ||
1344 | msg = (struct GNUNET_MessageHeader *) q->cls; | ||
1345 | GMP_queue_destroy (q, GNUNET_NO, GNUNET_NO, 0); | ||
1346 | return msg; | ||
1347 | |||
1348 | default: | ||
1349 | GNUNET_break (0); | ||
1350 | } | ||
1351 | } | ||
1352 | |||
1353 | return NULL; | ||
1354 | } | ||
1355 | |||
1356 | |||
1357 | void | ||
1358 | GMP_queue_unlock (struct CadetPeer *peer, struct CadetConnection *c) | ||
1359 | { | ||
1360 | struct CadetPeerQueue *q; | ||
1361 | size_t size; | ||
1362 | |||
1363 | if (NULL != peer->core_transmit) | ||
1364 | { | ||
1365 | LOG (GNUNET_ERROR_TYPE_DEBUG, " already unlocked!\n"); | ||
1366 | return; /* Already unlocked */ | ||
1367 | } | ||
1368 | |||
1369 | q = connection_get_first_message (peer, c); | ||
1370 | if (NULL == q) | ||
1371 | { | ||
1372 | LOG (GNUNET_ERROR_TYPE_DEBUG, " queue empty!\n"); | ||
1373 | return; /* Nothing to transmit */ | ||
1374 | } | ||
1375 | |||
1376 | size = q->size; | ||
1377 | peer->core_transmit = | ||
1378 | GNUNET_CORE_notify_transmit_ready (core_handle, | ||
1379 | GNUNET_NO, get_priority (q), | ||
1380 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
1381 | GNUNET_PEER_resolve2 (peer->id), | ||
1382 | size, | ||
1383 | &queue_send, | ||
1384 | peer); | ||
1385 | } | ||
1386 | |||
1387 | |||
1388 | /** | ||
1389 | * Initialize the peer subsystem. | ||
1390 | * | ||
1391 | * @param c Configuration. | ||
1392 | */ | ||
1393 | void | ||
1394 | GMP_init (const struct GNUNET_CONFIGURATION_Handle *c) | ||
1395 | { | ||
1396 | LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n"); | ||
1397 | peers = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO); | ||
1398 | if (GNUNET_OK != | ||
1399 | GNUNET_CONFIGURATION_get_value_number (c, "CADET", "MAX_PEERS", | ||
1400 | &max_peers)) | ||
1401 | { | ||
1402 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, | ||
1403 | "CADET", "MAX_PEERS", "USING DEFAULT"); | ||
1404 | max_peers = 1000; | ||
1405 | } | ||
1406 | |||
1407 | if (GNUNET_OK != | ||
1408 | GNUNET_CONFIGURATION_get_value_number (c, "CADET", "DROP_PERCENT", | ||
1409 | &drop_percent)) | ||
1410 | { | ||
1411 | drop_percent = 0; | ||
1412 | } | ||
1413 | else | ||
1414 | { | ||
1415 | LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n"); | ||
1416 | LOG (GNUNET_ERROR_TYPE_WARNING, "Cadet is running with DROP enabled.\n"); | ||
1417 | LOG (GNUNET_ERROR_TYPE_WARNING, "This is NOT a good idea!\n"); | ||
1418 | LOG (GNUNET_ERROR_TYPE_WARNING, "Remove DROP_PERCENT from config file.\n"); | ||
1419 | LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n"); | ||
1420 | } | ||
1421 | |||
1422 | core_handle = GNUNET_CORE_connect (c, /* Main configuration */ | ||
1423 | NULL, /* Closure passed to CADET functions */ | ||
1424 | &core_init, /* Call core_init once connected */ | ||
1425 | &core_connect, /* Handle connects */ | ||
1426 | &core_disconnect, /* remove peers on disconnects */ | ||
1427 | NULL, /* Don't notify about all incoming messages */ | ||
1428 | GNUNET_NO, /* For header only in notification */ | ||
1429 | NULL, /* Don't notify about all outbound messages */ | ||
1430 | GNUNET_NO, /* For header-only out notification */ | ||
1431 | core_handlers); /* Register these handlers */ | ||
1432 | if (GNUNET_YES != | ||
1433 | GNUNET_CONFIGURATION_get_value_yesno (c, "CADET", "DISABLE_TRY_CONNECT")) | ||
1434 | { | ||
1435 | transport_handle = GNUNET_TRANSPORT_connect (c, &my_full_id, NULL, /* cls */ | ||
1436 | /* Notify callbacks */ | ||
1437 | NULL, NULL, NULL); | ||
1438 | } | ||
1439 | else | ||
1440 | { | ||
1441 | LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n"); | ||
1442 | LOG (GNUNET_ERROR_TYPE_WARNING, "* DISABLE TRYING CONNECT in config *\n"); | ||
1443 | LOG (GNUNET_ERROR_TYPE_WARNING, "* Use this only for test purposes. *\n"); | ||
1444 | LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n"); | ||
1445 | transport_handle = NULL; | ||
1446 | } | ||
1447 | |||
1448 | |||
1449 | |||
1450 | if (NULL == core_handle) | ||
1451 | { | ||
1452 | GNUNET_break (0); | ||
1453 | GNUNET_SCHEDULER_shutdown (); | ||
1454 | return; | ||
1455 | } | ||
1456 | |||
1457 | } | ||
1458 | |||
1459 | /** | ||
1460 | * Shut down the peer subsystem. | ||
1461 | */ | ||
1462 | void | ||
1463 | GMP_shutdown (void) | ||
1464 | { | ||
1465 | GNUNET_CONTAINER_multipeermap_iterate (peers, &shutdown_tunnel, NULL); | ||
1466 | |||
1467 | if (core_handle != NULL) | ||
1468 | { | ||
1469 | GNUNET_CORE_disconnect (core_handle); | ||
1470 | core_handle = NULL; | ||
1471 | } | ||
1472 | if (transport_handle != NULL) | ||
1473 | { | ||
1474 | GNUNET_TRANSPORT_disconnect (transport_handle); | ||
1475 | transport_handle = NULL; | ||
1476 | } | ||
1477 | GNUNET_PEER_change_rc (myid, -1); | ||
1478 | } | ||
1479 | |||
1480 | /** | ||
1481 | * Retrieve the CadetPeer stucture associated with the peer, create one | ||
1482 | * and insert it in the appropriate structures if the peer is not known yet. | ||
1483 | * | ||
1484 | * @param peer_id Full identity of the peer. | ||
1485 | * | ||
1486 | * @return Existing or newly created peer structure. | ||
1487 | */ | ||
1488 | struct CadetPeer * | ||
1489 | GMP_get (const struct GNUNET_PeerIdentity *peer_id) | ||
1490 | { | ||
1491 | struct CadetPeer *peer; | ||
1492 | |||
1493 | peer = GNUNET_CONTAINER_multipeermap_get (peers, peer_id); | ||
1494 | if (NULL == peer) | ||
1495 | { | ||
1496 | peer = GNUNET_new (struct CadetPeer); | ||
1497 | if (GNUNET_CONTAINER_multipeermap_size (peers) > max_peers) | ||
1498 | { | ||
1499 | peer_delete_oldest (); | ||
1500 | } | ||
1501 | GNUNET_CONTAINER_multipeermap_put (peers, peer_id, peer, | ||
1502 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
1503 | peer->id = GNUNET_PEER_intern (peer_id); | ||
1504 | } | ||
1505 | peer->last_contact = GNUNET_TIME_absolute_get(); | ||
1506 | |||
1507 | return peer; | ||
1508 | } | ||
1509 | |||
1510 | |||
1511 | /** | ||
1512 | * Retrieve the CadetPeer stucture associated with the peer, create one | ||
1513 | * and insert it in the appropriate structures if the peer is not known yet. | ||
1514 | * | ||
1515 | * @param peer Short identity of the peer. | ||
1516 | * | ||
1517 | * @return Existing or newly created peer structure. | ||
1518 | */ | ||
1519 | struct CadetPeer * | ||
1520 | GMP_get_short (const GNUNET_PEER_Id peer) | ||
1521 | { | ||
1522 | return GMP_get (GNUNET_PEER_resolve2 (peer)); | ||
1523 | } | ||
1524 | |||
1525 | |||
1526 | /** | ||
1527 | * Try to connect to a peer on transport level. | ||
1528 | * | ||
1529 | * @param cls Closure (peer). | ||
1530 | * @param tc TaskContext. | ||
1531 | */ | ||
1532 | static void | ||
1533 | try_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1534 | { | ||
1535 | struct CadetPeer *peer = cls; | ||
1536 | |||
1537 | if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) | ||
1538 | return; | ||
1539 | |||
1540 | GNUNET_TRANSPORT_try_connect (transport_handle, | ||
1541 | GNUNET_PEER_resolve2 (peer->id), NULL, NULL); | ||
1542 | } | ||
1543 | |||
1544 | |||
1545 | /** | ||
1546 | * Try to establish a new connection to this peer (in its tunnel). | ||
1547 | * If the peer doesn't have any path to it yet, try to get one. | ||
1548 | * If the peer already has some path, send a CREATE CONNECTION towards it. | ||
1549 | * | ||
1550 | * @param peer Peer to connect to. | ||
1551 | */ | ||
1552 | void | ||
1553 | GMP_connect (struct CadetPeer *peer) | ||
1554 | { | ||
1555 | struct CadetTunnel3 *t; | ||
1556 | struct CadetPeerPath *p; | ||
1557 | struct CadetConnection *c; | ||
1558 | int rerun_search; | ||
1559 | |||
1560 | LOG (GNUNET_ERROR_TYPE_DEBUG, "peer_connect towards %s\n", GMP_2s (peer)); | ||
1561 | |||
1562 | /* If we have a current hello, try to connect using it. */ | ||
1563 | GMP_try_connect (peer); | ||
1564 | |||
1565 | t = peer->tunnel; | ||
1566 | c = NULL; | ||
1567 | rerun_search = GNUNET_NO; | ||
1568 | |||
1569 | if (NULL != peer->path_head) | ||
1570 | { | ||
1571 | LOG (GNUNET_ERROR_TYPE_DEBUG, " some path exists\n"); | ||
1572 | p = peer_get_best_path (peer); | ||
1573 | if (NULL != p) | ||
1574 | { | ||
1575 | char *s; | ||
1576 | |||
1577 | s = path_2s (p); | ||
1578 | LOG (GNUNET_ERROR_TYPE_DEBUG, " path to use: %s\n", s); | ||
1579 | GNUNET_free (s); | ||
1580 | |||
1581 | c = GMT_use_path (t, p); | ||
1582 | if (NULL == c) | ||
1583 | { | ||
1584 | /* This case can happen when the path includes a first hop that is | ||
1585 | * not yet known to be connected. | ||
1586 | * | ||
1587 | * This happens quite often during testing when running cadet | ||
1588 | * under valgrind: core connect notifications come very late and the | ||
1589 | * DHT result has already come and created a valid path. | ||
1590 | * In this case, the peer->connections hashmap will be NULL and | ||
1591 | * tunnel_use_path will not be able to create a connection from that | ||
1592 | * path. | ||
1593 | * | ||
1594 | * Re-running the DHT GET should give core time to callback. | ||
1595 | * | ||
1596 | * GMT_use_path -> GMC_new -> register_neighbors takes care of | ||
1597 | * updating statistics about this issue. | ||
1598 | */ | ||
1599 | rerun_search = GNUNET_YES; | ||
1600 | } | ||
1601 | else | ||
1602 | { | ||
1603 | GMC_send_create (c); | ||
1604 | return; | ||
1605 | } | ||
1606 | } | ||
1607 | else | ||
1608 | { | ||
1609 | LOG (GNUNET_ERROR_TYPE_DEBUG, " but is NULL, all paths are in use\n"); | ||
1610 | } | ||
1611 | } | ||
1612 | |||
1613 | if (NULL != peer->search_h && GNUNET_YES == rerun_search) | ||
1614 | { | ||
1615 | GMD_search_stop (peer->search_h); | ||
1616 | peer->search_h = NULL; | ||
1617 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1618 | " Stopping DHT GET for peer %s\n", | ||
1619 | GMP_2s (peer)); | ||
1620 | } | ||
1621 | |||
1622 | if (NULL == peer->search_h) | ||
1623 | { | ||
1624 | const struct GNUNET_PeerIdentity *id; | ||
1625 | |||
1626 | id = GNUNET_PEER_resolve2 (peer->id); | ||
1627 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1628 | " Starting DHT GET for peer %s\n", GMP_2s (peer)); | ||
1629 | peer->search_h = GMD_search (id, &search_handler, peer); | ||
1630 | if (CADET_TUNNEL3_NEW == GMT_get_cstate (t)) | ||
1631 | GMT_change_cstate (t, CADET_TUNNEL3_SEARCHING); | ||
1632 | } | ||
1633 | } | ||
1634 | |||
1635 | |||
1636 | /** | ||
1637 | * Chech whether there is a direct (core level) connection to peer. | ||
1638 | * | ||
1639 | * @param peer Peer to check. | ||
1640 | * | ||
1641 | * @return #GNUNET_YES if there is a direct connection. | ||
1642 | */ | ||
1643 | int | ||
1644 | GMP_is_neighbor (const struct CadetPeer *peer) | ||
1645 | { | ||
1646 | struct CadetPeerPath *path; | ||
1647 | |||
1648 | if (NULL == peer->connections) | ||
1649 | return GNUNET_NO; | ||
1650 | |||
1651 | for (path = peer->path_head; NULL != path; path = path->next) | ||
1652 | { | ||
1653 | if (3 > path->length) | ||
1654 | return GNUNET_YES; | ||
1655 | } | ||
1656 | |||
1657 | /* Is not a neighbor but connections is not NULL, probably disconnecting */ | ||
1658 | return GNUNET_NO; | ||
1659 | } | ||
1660 | |||
1661 | |||
1662 | /** | ||
1663 | * Create and initialize a new tunnel towards a peer, in case it has none. | ||
1664 | * In case the peer already has a tunnel, nothing is done. | ||
1665 | * | ||
1666 | * Does not generate any traffic, just creates the local data structures. | ||
1667 | * | ||
1668 | * @param peer Peer towards which to create the tunnel. | ||
1669 | */ | ||
1670 | void | ||
1671 | GMP_add_tunnel (struct CadetPeer *peer) | ||
1672 | { | ||
1673 | if (NULL != peer->tunnel) | ||
1674 | return; | ||
1675 | peer->tunnel = GMT_new (peer); | ||
1676 | } | ||
1677 | |||
1678 | |||
1679 | /** | ||
1680 | * Add a connection to a neighboring peer. | ||
1681 | * | ||
1682 | * Store that the peer is the first hop of the connection in one | ||
1683 | * direction and that on peer disconnect the connection must be | ||
1684 | * notified and destroyed, for it will no longer be valid. | ||
1685 | * | ||
1686 | * @param peer Peer to add connection to. | ||
1687 | * @param c Connection to add. | ||
1688 | * | ||
1689 | * @return GNUNET_OK on success. | ||
1690 | */ | ||
1691 | int | ||
1692 | GMP_add_connection (struct CadetPeer *peer, | ||
1693 | struct CadetConnection *c) | ||
1694 | { | ||
1695 | int result; | ||
1696 | LOG (GNUNET_ERROR_TYPE_DEBUG, "adding connection %s\n", GMC_2s (c)); | ||
1697 | LOG (GNUNET_ERROR_TYPE_DEBUG, "to peer %s\n", GMP_2s (peer)); | ||
1698 | |||
1699 | if (NULL == peer->connections) | ||
1700 | { | ||
1701 | GNUNET_break (0); | ||
1702 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1703 | "Peer %s is not a neighbor!\n", | ||
1704 | GMP_2s (peer)); | ||
1705 | return GNUNET_SYSERR; | ||
1706 | } | ||
1707 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1708 | "peer %s ok, has %u connections.\n", | ||
1709 | GMP_2s (peer), GNUNET_CONTAINER_multihashmap_size (peer->connections)); | ||
1710 | result = GNUNET_CONTAINER_multihashmap_put (peer->connections, | ||
1711 | GMC_get_h (c), | ||
1712 | c, | ||
1713 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
1714 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1715 | " now has %u connections.\n", | ||
1716 | GNUNET_CONTAINER_multihashmap_size (peer->connections)); | ||
1717 | LOG (GNUNET_ERROR_TYPE_DEBUG, "result %u\n", result); | ||
1718 | |||
1719 | return result; | ||
1720 | } | ||
1721 | |||
1722 | |||
1723 | /** | ||
1724 | * Add the path to the peer and update the path used to reach it in case this | ||
1725 | * is the shortest. | ||
1726 | * | ||
1727 | * @param peer Destination peer to add the path to. | ||
1728 | * @param path New path to add. Last peer must be the peer in arg 1. | ||
1729 | * Path will be either used of freed if already known. | ||
1730 | * @param trusted Do we trust that this path is real? | ||
1731 | * | ||
1732 | * @return path if path was taken, pointer to existing duplicate if exists | ||
1733 | * NULL on error. | ||
1734 | */ | ||
1735 | struct CadetPeerPath * | ||
1736 | GMP_add_path (struct CadetPeer *peer, struct CadetPeerPath *path, | ||
1737 | int trusted) | ||
1738 | { | ||
1739 | struct CadetPeerPath *aux; | ||
1740 | unsigned int l; | ||
1741 | unsigned int l2; | ||
1742 | |||
1743 | LOG (GNUNET_ERROR_TYPE_DEBUG, "adding path [%u] to peer %s\n", | ||
1744 | path->length, GMP_2s (peer)); | ||
1745 | |||
1746 | if ((NULL == peer) || (NULL == path)) | ||
1747 | { | ||
1748 | GNUNET_break (0); | ||
1749 | path_destroy (path); | ||
1750 | return NULL; | ||
1751 | } | ||
1752 | if (path->peers[path->length - 1] != peer->id) | ||
1753 | { | ||
1754 | GNUNET_break (0); | ||
1755 | path_destroy (path); | ||
1756 | return NULL; | ||
1757 | } | ||
1758 | |||
1759 | for (l = 1; l < path->length; l++) | ||
1760 | { | ||
1761 | if (path->peers[l] == myid) | ||
1762 | { | ||
1763 | LOG (GNUNET_ERROR_TYPE_DEBUG, " shortening path by %u\n", l); | ||
1764 | for (l2 = 0; l2 < path->length - l; l2++) | ||
1765 | { | ||
1766 | path->peers[l2] = path->peers[l + l2]; | ||
1767 | } | ||
1768 | path->length -= l; | ||
1769 | l = 1; | ||
1770 | path->peers = GNUNET_realloc (path->peers, | ||
1771 | path->length * sizeof (GNUNET_PEER_Id)); | ||
1772 | } | ||
1773 | } | ||
1774 | |||
1775 | LOG (GNUNET_ERROR_TYPE_DEBUG, " final length: %u\n", path->length); | ||
1776 | |||
1777 | if (2 >= path->length && GNUNET_NO == trusted) | ||
1778 | { | ||
1779 | /* Only allow CORE to tell us about direct paths */ | ||
1780 | path_destroy (path); | ||
1781 | return NULL; | ||
1782 | } | ||
1783 | |||
1784 | l = path_get_length (path); | ||
1785 | if (0 == l) | ||
1786 | { | ||
1787 | path_destroy (path); | ||
1788 | return NULL; | ||
1789 | } | ||
1790 | |||
1791 | GNUNET_assert (peer->id == path->peers[path->length - 1]); | ||
1792 | for (aux = peer->path_head; aux != NULL; aux = aux->next) | ||
1793 | { | ||
1794 | l2 = path_get_length (aux); | ||
1795 | if (l2 > l) | ||
1796 | { | ||
1797 | LOG (GNUNET_ERROR_TYPE_DEBUG, " added\n"); | ||
1798 | GNUNET_CONTAINER_DLL_insert_before (peer->path_head, | ||
1799 | peer->path_tail, aux, path); | ||
1800 | if (NULL != peer->tunnel && 3 < GMT_count_connections (peer->tunnel)) | ||
1801 | { | ||
1802 | GMP_connect (peer); | ||
1803 | } | ||
1804 | return path; | ||
1805 | } | ||
1806 | else | ||
1807 | { | ||
1808 | if (l2 == l && memcmp (path->peers, aux->peers, l) == 0) | ||
1809 | { | ||
1810 | LOG (GNUNET_ERROR_TYPE_DEBUG, " already known\n"); | ||
1811 | path_destroy (path); | ||
1812 | return aux; | ||
1813 | } | ||
1814 | } | ||
1815 | } | ||
1816 | GNUNET_CONTAINER_DLL_insert_tail (peer->path_head, peer->path_tail, | ||
1817 | path); | ||
1818 | LOG (GNUNET_ERROR_TYPE_DEBUG, " added last\n"); | ||
1819 | if (NULL != peer->tunnel && 3 < GMT_count_connections (peer->tunnel)) | ||
1820 | { | ||
1821 | GMP_connect (peer); | ||
1822 | } | ||
1823 | return path; | ||
1824 | } | ||
1825 | |||
1826 | |||
1827 | /** | ||
1828 | * Add the path to the origin peer and update the path used to reach it in case | ||
1829 | * this is the shortest. | ||
1830 | * The path is given in peer_info -> destination, therefore we turn the path | ||
1831 | * upside down first. | ||
1832 | * | ||
1833 | * @param peer Peer to add the path to, being the origin of the path. | ||
1834 | * @param path New path to add after being inversed. | ||
1835 | * Path will be either used or freed. | ||
1836 | * @param trusted Do we trust that this path is real? | ||
1837 | * | ||
1838 | * @return path if path was taken, pointer to existing duplicate if exists | ||
1839 | * NULL on error. | ||
1840 | */ | ||
1841 | struct CadetPeerPath * | ||
1842 | GMP_add_path_to_origin (struct CadetPeer *peer, | ||
1843 | struct CadetPeerPath *path, | ||
1844 | int trusted) | ||
1845 | { | ||
1846 | if (NULL == path) | ||
1847 | return NULL; | ||
1848 | path_invert (path); | ||
1849 | return GMP_add_path (peer, path, trusted); | ||
1850 | } | ||
1851 | |||
1852 | |||
1853 | /** | ||
1854 | * Adds a path to the info of all the peers in the path | ||
1855 | * | ||
1856 | * @param p Path to process. | ||
1857 | * @param confirmed Whether we know if the path works or not. | ||
1858 | */ | ||
1859 | void | ||
1860 | GMP_add_path_to_all (const struct CadetPeerPath *p, int confirmed) | ||
1861 | { | ||
1862 | unsigned int i; | ||
1863 | |||
1864 | /* TODO: invert and add */ | ||
1865 | for (i = 0; i < p->length && p->peers[i] != myid; i++) /* skip'em */ ; | ||
1866 | for (i++; i < p->length; i++) | ||
1867 | { | ||
1868 | struct CadetPeer *aux; | ||
1869 | struct CadetPeerPath *copy; | ||
1870 | |||
1871 | aux = GMP_get_short (p->peers[i]); | ||
1872 | copy = path_duplicate (p); | ||
1873 | copy->length = i + 1; | ||
1874 | GMP_add_path (aux, copy, p->length < 3 ? GNUNET_NO : confirmed); | ||
1875 | } | ||
1876 | } | ||
1877 | |||
1878 | |||
1879 | /** | ||
1880 | * Remove any path to the peer that has the extact same peers as the one given. | ||
1881 | * | ||
1882 | * @param peer Peer to remove the path from. | ||
1883 | * @param path Path to remove. Is always destroyed . | ||
1884 | */ | ||
1885 | void | ||
1886 | GMP_remove_path (struct CadetPeer *peer, struct CadetPeerPath *path) | ||
1887 | { | ||
1888 | struct CadetPeerPath *iter; | ||
1889 | struct CadetPeerPath *next; | ||
1890 | |||
1891 | GNUNET_assert (myid == path->peers[0]); | ||
1892 | GNUNET_assert (peer->id == path->peers[path->length - 1]); | ||
1893 | |||
1894 | for (iter = peer->path_head; NULL != iter; iter = next) | ||
1895 | { | ||
1896 | next = iter->next; | ||
1897 | if (0 == memcmp (path->peers, iter->peers, | ||
1898 | sizeof (GNUNET_PEER_Id) * path->length)) | ||
1899 | { | ||
1900 | GNUNET_CONTAINER_DLL_remove (peer->path_head, peer->path_tail, iter); | ||
1901 | if (iter != path) | ||
1902 | path_destroy (iter); | ||
1903 | } | ||
1904 | } | ||
1905 | path_destroy (path); | ||
1906 | } | ||
1907 | |||
1908 | |||
1909 | /** | ||
1910 | * Remove a connection from a neighboring peer. | ||
1911 | * | ||
1912 | * @param peer Peer to remove connection from. | ||
1913 | * @param c Connection to remove. | ||
1914 | * | ||
1915 | * @return GNUNET_OK on success. | ||
1916 | */ | ||
1917 | int | ||
1918 | GMP_remove_connection (struct CadetPeer *peer, | ||
1919 | const struct CadetConnection *c) | ||
1920 | { | ||
1921 | LOG (GNUNET_ERROR_TYPE_DEBUG, "removing connection %s\n", GMC_2s (c)); | ||
1922 | LOG (GNUNET_ERROR_TYPE_DEBUG, "from peer %s\n", GMP_2s (peer)); | ||
1923 | |||
1924 | if (NULL == peer || NULL == peer->connections) | ||
1925 | { | ||
1926 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1927 | "Peer %s is not a neighbor!\n", | ||
1928 | GMP_2s (peer)); | ||
1929 | return GNUNET_SYSERR; | ||
1930 | } | ||
1931 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1932 | "peer %s ok, has %u connections.\n", | ||
1933 | GMP_2s (peer), GNUNET_CONTAINER_multihashmap_size (peer->connections)); | ||
1934 | |||
1935 | return GNUNET_CONTAINER_multihashmap_remove (peer->connections, | ||
1936 | GMC_get_h (c), | ||
1937 | c); | ||
1938 | } | ||
1939 | |||
1940 | /** | ||
1941 | * Start the DHT search for new paths towards the peer: we don't have | ||
1942 | * enough good connections. | ||
1943 | * | ||
1944 | * @param peer Destination peer. | ||
1945 | */ | ||
1946 | void | ||
1947 | GMP_start_search (struct CadetPeer *peer) | ||
1948 | { | ||
1949 | if (NULL != peer->search_h) | ||
1950 | { | ||
1951 | GNUNET_break (0); | ||
1952 | return; | ||
1953 | } | ||
1954 | |||
1955 | peer->search_h = GMD_search (GMP_get_id (peer), &search_handler, peer); | ||
1956 | } | ||
1957 | |||
1958 | |||
1959 | /** | ||
1960 | * Stop the DHT search for new paths towards the peer: we already have | ||
1961 | * enough good connections. | ||
1962 | * | ||
1963 | * @param peer Destination peer. | ||
1964 | */ | ||
1965 | void | ||
1966 | GMP_stop_search (struct CadetPeer *peer) | ||
1967 | { | ||
1968 | if (NULL == peer->search_h) | ||
1969 | { | ||
1970 | return; | ||
1971 | } | ||
1972 | |||
1973 | GMD_search_stop (peer->search_h); | ||
1974 | peer->search_h = NULL; | ||
1975 | } | ||
1976 | |||
1977 | |||
1978 | /** | ||
1979 | * Get the Full ID of a peer. | ||
1980 | * | ||
1981 | * @param peer Peer to get from. | ||
1982 | * | ||
1983 | * @return Full ID of peer. | ||
1984 | */ | ||
1985 | const struct GNUNET_PeerIdentity * | ||
1986 | GMP_get_id (const struct CadetPeer *peer) | ||
1987 | { | ||
1988 | return GNUNET_PEER_resolve2 (peer->id); | ||
1989 | } | ||
1990 | |||
1991 | |||
1992 | /** | ||
1993 | * Get the Short ID of a peer. | ||
1994 | * | ||
1995 | * @param peer Peer to get from. | ||
1996 | * | ||
1997 | * @return Short ID of peer. | ||
1998 | */ | ||
1999 | GNUNET_PEER_Id | ||
2000 | GMP_get_short_id (const struct CadetPeer *peer) | ||
2001 | { | ||
2002 | return peer->id; | ||
2003 | } | ||
2004 | |||
2005 | |||
2006 | /** | ||
2007 | * Set tunnel. | ||
2008 | * | ||
2009 | * @param peer Peer. | ||
2010 | * @param t Tunnel. | ||
2011 | */ | ||
2012 | void | ||
2013 | GMP_set_tunnel (struct CadetPeer *peer, struct CadetTunnel3 *t) | ||
2014 | { | ||
2015 | peer->tunnel = t; | ||
2016 | if (NULL == t && NULL != peer->search_h) | ||
2017 | { | ||
2018 | GMP_stop_search (peer); | ||
2019 | } | ||
2020 | } | ||
2021 | |||
2022 | |||
2023 | /** | ||
2024 | * Get the tunnel towards a peer. | ||
2025 | * | ||
2026 | * @param peer Peer to get from. | ||
2027 | * | ||
2028 | * @return Tunnel towards peer. | ||
2029 | */ | ||
2030 | struct CadetTunnel3 * | ||
2031 | GMP_get_tunnel (const struct CadetPeer *peer) | ||
2032 | { | ||
2033 | return peer->tunnel; | ||
2034 | } | ||
2035 | |||
2036 | |||
2037 | /** | ||
2038 | * Set the hello message. | ||
2039 | * | ||
2040 | * @param peer Peer whose message to set. | ||
2041 | * @param hello Hello message. | ||
2042 | */ | ||
2043 | void | ||
2044 | GMP_set_hello (struct CadetPeer *peer, const struct GNUNET_HELLO_Message *hello) | ||
2045 | { | ||
2046 | struct GNUNET_HELLO_Message *old; | ||
2047 | size_t size; | ||
2048 | |||
2049 | LOG (GNUNET_ERROR_TYPE_DEBUG, "set hello for %s\n", GMP_2s (peer)); | ||
2050 | if (NULL == hello) | ||
2051 | return; | ||
2052 | |||
2053 | old = GMP_get_hello (peer); | ||
2054 | if (NULL == old) | ||
2055 | { | ||
2056 | size = GNUNET_HELLO_size (hello); | ||
2057 | LOG (GNUNET_ERROR_TYPE_DEBUG, " new (%u bytes)\n", size); | ||
2058 | peer->hello = GNUNET_malloc (size); | ||
2059 | memcpy (peer->hello, hello, size); | ||
2060 | } | ||
2061 | else | ||
2062 | { | ||
2063 | peer->hello = GNUNET_HELLO_merge (old, hello); | ||
2064 | LOG (GNUNET_ERROR_TYPE_DEBUG, " merge into %p (%u bytes)\n", | ||
2065 | peer->hello, GNUNET_HELLO_size (hello)); | ||
2066 | GNUNET_free (old); | ||
2067 | } | ||
2068 | } | ||
2069 | |||
2070 | |||
2071 | /** | ||
2072 | * Get the hello message. | ||
2073 | * | ||
2074 | * @param peer Peer whose message to get. | ||
2075 | * | ||
2076 | * @return Hello message. | ||
2077 | */ | ||
2078 | struct GNUNET_HELLO_Message * | ||
2079 | GMP_get_hello (struct CadetPeer *peer) | ||
2080 | { | ||
2081 | struct GNUNET_TIME_Absolute expiration; | ||
2082 | struct GNUNET_TIME_Relative remaining; | ||
2083 | |||
2084 | if (NULL == peer->hello) | ||
2085 | return NULL; | ||
2086 | |||
2087 | expiration = GNUNET_HELLO_get_last_expiration (peer->hello); | ||
2088 | remaining = GNUNET_TIME_absolute_get_remaining (expiration); | ||
2089 | if (0 == remaining.rel_value_us) | ||
2090 | { | ||
2091 | LOG (GNUNET_ERROR_TYPE_DEBUG, " get - hello expired on %s\n", | ||
2092 | GNUNET_STRINGS_absolute_time_to_string (expiration)); | ||
2093 | GNUNET_free (peer->hello); | ||
2094 | peer->hello = NULL; | ||
2095 | } | ||
2096 | return peer->hello; | ||
2097 | } | ||
2098 | |||
2099 | |||
2100 | /** | ||
2101 | * Try to connect to a peer on TRANSPORT level. | ||
2102 | * | ||
2103 | * @param peer Peer to whom to connect. | ||
2104 | */ | ||
2105 | void | ||
2106 | GMP_try_connect (struct CadetPeer *peer) | ||
2107 | { | ||
2108 | struct GNUNET_HELLO_Message *hello; | ||
2109 | struct GNUNET_MessageHeader *mh; | ||
2110 | |||
2111 | if (NULL == transport_handle) | ||
2112 | return; | ||
2113 | |||
2114 | hello = GMP_get_hello (peer); | ||
2115 | if (NULL == hello) | ||
2116 | return; | ||
2117 | |||
2118 | mh = GNUNET_HELLO_get_header (hello); | ||
2119 | GNUNET_TRANSPORT_offer_hello (transport_handle, mh, try_connect, peer); | ||
2120 | } | ||
2121 | |||
2122 | |||
2123 | /** | ||
2124 | * Notify a peer that a link between two other peers is broken. If any path | ||
2125 | * used that link, eliminate it. | ||
2126 | * | ||
2127 | * @param peer Peer affected by the change. | ||
2128 | * @param peer1 Peer whose link is broken. | ||
2129 | * @param peer2 Peer whose link is broken. | ||
2130 | */ | ||
2131 | void | ||
2132 | GMP_notify_broken_link (struct CadetPeer *peer, | ||
2133 | struct GNUNET_PeerIdentity *peer1, | ||
2134 | struct GNUNET_PeerIdentity *peer2) | ||
2135 | { | ||
2136 | struct CadetPeerPath *iter; | ||
2137 | struct CadetPeerPath *next; | ||
2138 | unsigned int i; | ||
2139 | GNUNET_PEER_Id p1; | ||
2140 | GNUNET_PEER_Id p2; | ||
2141 | |||
2142 | p1 = GNUNET_PEER_search (peer1); | ||
2143 | p2 = GNUNET_PEER_search (peer2); | ||
2144 | |||
2145 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Link %u-%u broken\n", p1, p2); | ||
2146 | if (0 == p1 || 0 == p2) | ||
2147 | { | ||
2148 | /* We don't even know them */ | ||
2149 | return; | ||
2150 | } | ||
2151 | |||
2152 | for (iter = peer->path_head; NULL != iter; iter = next) | ||
2153 | { | ||
2154 | next = iter->next; | ||
2155 | for (i = 0; i < iter->length - 1; i++) | ||
2156 | { | ||
2157 | if ((iter->peers[i] == p1 && iter->peers[i + 1] == p2) | ||
2158 | || (iter->peers[i] == p2 && iter->peers[i + 1] == p1)) | ||
2159 | { | ||
2160 | char *s; | ||
2161 | |||
2162 | s = path_2s (iter); | ||
2163 | LOG (GNUNET_ERROR_TYPE_DEBUG, " - invalidating %s\n", s); | ||
2164 | GNUNET_free (s); | ||
2165 | |||
2166 | path_invalidate (iter); | ||
2167 | } | ||
2168 | } | ||
2169 | } | ||
2170 | } | ||
2171 | |||
2172 | |||
2173 | /** | ||
2174 | * Count the number of known paths toward the peer. | ||
2175 | * | ||
2176 | * @param peer Peer to get path info. | ||
2177 | * | ||
2178 | * @return Number of known paths. | ||
2179 | */ | ||
2180 | unsigned int | ||
2181 | GMP_count_paths (const struct CadetPeer *peer) | ||
2182 | { | ||
2183 | struct CadetPeerPath *iter; | ||
2184 | unsigned int i; | ||
2185 | |||
2186 | for (iter = peer->path_head, i = 0; NULL != iter; iter = iter->next) | ||
2187 | i++; | ||
2188 | |||
2189 | return i; | ||
2190 | } | ||
2191 | |||
2192 | |||
2193 | /** | ||
2194 | * Iterate all known peers. | ||
2195 | * | ||
2196 | * @param iter Iterator. | ||
2197 | * @param cls Closure for @c iter. | ||
2198 | */ | ||
2199 | void | ||
2200 | GMP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, void *cls) | ||
2201 | { | ||
2202 | GNUNET_CONTAINER_multipeermap_iterate (peers, iter, cls); | ||
2203 | } | ||
2204 | |||
2205 | |||
2206 | /** | ||
2207 | * Get the static string for a peer ID. | ||
2208 | * | ||
2209 | * @param peer Peer. | ||
2210 | * | ||
2211 | * @return Static string for it's ID. | ||
2212 | */ | ||
2213 | const char * | ||
2214 | GMP_2s (const struct CadetPeer *peer) | ||
2215 | { | ||
2216 | if (NULL == peer) | ||
2217 | return "(NULL)"; | ||
2218 | return GNUNET_i2s (GNUNET_PEER_resolve2 (peer->id)); | ||
2219 | } | ||