diff options
author | Christian Grothoff <christian@grothoff.org> | 2019-05-11 19:30:57 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2019-05-11 19:30:57 +0200 |
commit | bc32b1f4b64ab0897efc1fe3125c5748e17cb561 (patch) | |
tree | a48ffce44427b7bfa47c0c3bef3f37110ba4d817 /src | |
parent | da604c171418b64fcd37a46c4526ba97b6ee47dc (diff) | |
download | gnunet-bc32b1f4b64ab0897efc1fe3125c5748e17cb561.tar.gz gnunet-bc32b1f4b64ab0897efc1fe3125c5748e17cb561.zip |
move encryption logic into DVBox
Diffstat (limited to 'src')
-rw-r--r-- | src/transport/gnunet-service-tng.c | 2068 |
1 files changed, 889 insertions, 1179 deletions
diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c index 08a8ec893..f07e1c88d 100644 --- a/src/transport/gnunet-service-tng.c +++ b/src/transport/gnunet-service-tng.c | |||
@@ -24,8 +24,14 @@ | |||
24 | * | 24 | * |
25 | * TODO: | 25 | * TODO: |
26 | * Implement next: | 26 | * Implement next: |
27 | * - properly encrypt *all* DV traffic, not only backchannel; | 27 | * - realize "pull" based logic (#handle_client_send()) for |
28 | * rename BackchannelEncapsulation logic to DVEncapsulation! | 28 | * `struct PendingMessage` which waits for a queue on any |
29 | * applicable route to be 'ready', in contrast | ||
30 | * to the 'push' based routing we use for control messages. | ||
31 | * Basically, when a queue goes idle, it should "search" | ||
32 | * via its neighbour for either virtual links or DVH's that | ||
33 | * have it as first hop and then find messages in those | ||
34 | * virtual links! | ||
29 | * - realize transport-to-transport flow control (needed in case | 35 | * - realize transport-to-transport flow control (needed in case |
30 | * communicators do not offer flow control). Note that we may not | 36 | * communicators do not offer flow control). Note that we may not |
31 | * want to simply delay the ACKs as that may cause unnecessary | 37 | * want to simply delay the ACKs as that may cause unnecessary |
@@ -327,37 +333,10 @@ struct TransportBackchannelEncapsulationMessage | |||
327 | */ | 333 | */ |
328 | struct GNUNET_MessageHeader header; | 334 | struct GNUNET_MessageHeader header; |
329 | 335 | ||
330 | /** | 336 | /* Followed by *another* message header which is the message to |
331 | * Reserved, always zero. | 337 | the communicator */ |
332 | */ | ||
333 | uint32_t reserved GNUNET_PACKED; | ||
334 | |||
335 | /** | ||
336 | * Target's peer identity (as backchannels may be transmitted | ||
337 | * indirectly, or even be broadcast). | ||
338 | */ | ||
339 | struct GNUNET_PeerIdentity target; | ||
340 | |||
341 | /** | ||
342 | * Ephemeral key setup by the sender for @e target, used | ||
343 | * to encrypt the payload. | ||
344 | */ | ||
345 | struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key; | ||
346 | |||
347 | /** | ||
348 | * We use an IV here as the @e ephemeral_key is re-used for | ||
349 | * #EPHEMERAL_VALIDITY time to avoid re-signing it all the time. | ||
350 | */ | ||
351 | struct GNUNET_ShortHashCode iv; | ||
352 | |||
353 | /** | ||
354 | * HMAC over the ciphertext of the encrypted, variable-size | ||
355 | * body that follows. Verified via DH of @e target and | ||
356 | * @e ephemeral_key | ||
357 | */ | ||
358 | struct GNUNET_HashCode hmac; | ||
359 | 338 | ||
360 | /* Followed by encrypted, variable-size payload */ | 339 | /* Followed by a 0-terminated name of the communicator */ |
361 | }; | 340 | }; |
362 | 341 | ||
363 | 342 | ||
@@ -405,7 +384,7 @@ struct EphemeralConfirmationPS | |||
405 | * Plaintext of the variable-size payload that is encrypted | 384 | * Plaintext of the variable-size payload that is encrypted |
406 | * within a `struct TransportBackchannelEncapsulationMessage` | 385 | * within a `struct TransportBackchannelEncapsulationMessage` |
407 | */ | 386 | */ |
408 | struct TransportBackchannelRequestPayloadP | 387 | struct TransportDVBoxPayloadP |
409 | { | 388 | { |
410 | 389 | ||
411 | /** | 390 | /** |
@@ -432,10 +411,7 @@ struct TransportBackchannelRequestPayloadP | |||
432 | struct GNUNET_TIME_AbsoluteNBO monotonic_time; | 411 | struct GNUNET_TIME_AbsoluteNBO monotonic_time; |
433 | 412 | ||
434 | /* Followed by a `struct GNUNET_MessageHeader` with a message | 413 | /* Followed by a `struct GNUNET_MessageHeader` with a message |
435 | for a communicator */ | 414 | for the target peer */ |
436 | |||
437 | /* Followed by a 0-termianted string specifying the name of | ||
438 | the communicator which is to receive the message */ | ||
439 | }; | 415 | }; |
440 | 416 | ||
441 | 417 | ||
@@ -746,6 +722,13 @@ struct TransportDVLearnMessage | |||
746 | * shortcut. | 722 | * shortcut. |
747 | * | 723 | * |
748 | * If a peer finds itself still on the list, it must drop the message. | 724 | * If a peer finds itself still on the list, it must drop the message. |
725 | * | ||
726 | * The payload of the box can only be decrypted and verified by the | ||
727 | * ultimate receiver. Intermediaries do not learn the sender's | ||
728 | * identity and the path the message has taken. However, the first | ||
729 | * hop does learn the sender as @e total_hops would be zero and thus | ||
730 | * the predecessor must be the origin (so this is not really useful | ||
731 | * for anonymization). | ||
749 | */ | 732 | */ |
750 | struct TransportDVBoxMessage | 733 | struct TransportDVBoxMessage |
751 | { | 734 | { |
@@ -757,27 +740,48 @@ struct TransportDVBoxMessage | |||
757 | /** | 740 | /** |
758 | * Number of total hops this messages travelled. In NBO. | 741 | * Number of total hops this messages travelled. In NBO. |
759 | * @e origin sets this to zero, to be incremented at | 742 | * @e origin sets this to zero, to be incremented at |
760 | * each hop. | 743 | * each hop. Peers should limit the @e total_hops value |
744 | * they accept from other peers. | ||
761 | */ | 745 | */ |
762 | uint16_t total_hops GNUNET_PACKED; | 746 | uint16_t total_hops GNUNET_PACKED; |
763 | 747 | ||
764 | /** | 748 | /** |
765 | * Number of hops this messages includes. In NBO. | 749 | * Number of hops this messages includes. In NBO. Reduced by one |
750 | * or more at each hop. Peers should limit the @e num_hops value | ||
751 | * they accept from other peers. | ||
766 | */ | 752 | */ |
767 | uint16_t num_hops GNUNET_PACKED; | 753 | uint16_t num_hops GNUNET_PACKED; |
768 | 754 | ||
769 | /** | 755 | /** |
770 | * Identity of the peer that originated the message. | 756 | * Ephemeral key setup by the sender for target, used to encrypt the |
757 | * payload. Intermediaries must not change this value. | ||
758 | */ | ||
759 | struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key; | ||
760 | |||
761 | /** | ||
762 | * We use an IV here as the @e ephemeral_key is re-used for | ||
763 | * #EPHEMERAL_VALIDITY time to avoid re-signing it all the time. | ||
764 | * Intermediaries must not change this value. | ||
765 | */ | ||
766 | struct GNUNET_ShortHashCode iv; | ||
767 | |||
768 | /** | ||
769 | * HMAC over the ciphertext of the encrypted, variable-size body | ||
770 | * that follows. Verified via DH of target and @e ephemeral_key. | ||
771 | * Intermediaries must not change this value. | ||
771 | */ | 772 | */ |
772 | struct GNUNET_PeerIdentity origin; | 773 | struct GNUNET_HashCode hmac; |
773 | 774 | ||
774 | /* Followed by @e num_hops `struct GNUNET_PeerIdentity` values; | 775 | /* Followed by @e num_hops `struct GNUNET_PeerIdentity` values; |
775 | excluding the @e origin and the current peer, the last must be | 776 | excluding the @e origin and the current peer, the last must be |
776 | the ultimate target; if @e num_hops is zero, the receiver of this | 777 | the ultimate target; if @e num_hops is zero, the receiver of this |
777 | message is the ultimate target. */ | 778 | message is the ultimate target. */ |
778 | 779 | ||
779 | /* Followed by the actual message, which itself may be | 780 | /* Followed by encrypted, variable-size payload, which |
780 | another box, but not a DV_LEARN or DV_BOX message! */ | 781 | must begin with a `struct TransportDVBoxPayloadP` */ |
782 | |||
783 | /* Followed by the actual message, which itself must not be a | ||
784 | a DV_LEARN or DV_BOX message! */ | ||
781 | }; | 785 | }; |
782 | 786 | ||
783 | 787 | ||
@@ -978,56 +982,6 @@ struct LearnLaunchEntry | |||
978 | 982 | ||
979 | 983 | ||
980 | /** | 984 | /** |
981 | * Entry in our cache of ephemeral keys we currently use. This way, we only | ||
982 | * sign an ephemeral once per @e target, and then can re-use it over multiple | ||
983 | * #GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION messages (as | ||
984 | * signing is expensive and in some cases we may use backchannel messages a | ||
985 | * lot). | ||
986 | */ | ||
987 | struct EphemeralCacheEntry | ||
988 | { | ||
989 | |||
990 | /** | ||
991 | * Target's peer identity (we don't re-use ephemerals | ||
992 | * to limit linkability of messages). | ||
993 | */ | ||
994 | struct GNUNET_PeerIdentity target; | ||
995 | |||
996 | /** | ||
997 | * Signature affirming @e ephemeral_key of type | ||
998 | * #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL | ||
999 | */ | ||
1000 | struct GNUNET_CRYPTO_EddsaSignature sender_sig; | ||
1001 | |||
1002 | /** | ||
1003 | * How long is @e sender_sig valid | ||
1004 | */ | ||
1005 | struct GNUNET_TIME_Absolute ephemeral_validity; | ||
1006 | |||
1007 | /** | ||
1008 | * What time was @e sender_sig created | ||
1009 | */ | ||
1010 | struct GNUNET_TIME_Absolute monotime; | ||
1011 | |||
1012 | /** | ||
1013 | * Our ephemeral key. | ||
1014 | */ | ||
1015 | struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key; | ||
1016 | |||
1017 | /** | ||
1018 | * Our private ephemeral key. | ||
1019 | */ | ||
1020 | struct GNUNET_CRYPTO_EcdhePrivateKey private_key; | ||
1021 | |||
1022 | /** | ||
1023 | * Node in the ephemeral cache for this entry. | ||
1024 | * Used for expiration. | ||
1025 | */ | ||
1026 | struct GNUNET_CONTAINER_HeapNode *hn; | ||
1027 | }; | ||
1028 | |||
1029 | |||
1030 | /** | ||
1031 | * Information we keep per #GOODPUT_AGING_SLOTS about historic | 985 | * Information we keep per #GOODPUT_AGING_SLOTS about historic |
1032 | * (or current) transmission performance. | 986 | * (or current) transmission performance. |
1033 | */ | 987 | */ |
@@ -1168,6 +1122,16 @@ struct VirtualLink | |||
1168 | struct CommunicatorMessageContext *cmc_tail; | 1122 | struct CommunicatorMessageContext *cmc_tail; |
1169 | 1123 | ||
1170 | /** | 1124 | /** |
1125 | * Head of list of messages pending for this VL. | ||
1126 | */ | ||
1127 | struct PendingMessage *pending_msg_head; | ||
1128 | |||
1129 | /** | ||
1130 | * Tail of list of messages pending for this VL. | ||
1131 | */ | ||
1132 | struct PendingMessage *pending_msg_tail; | ||
1133 | |||
1134 | /** | ||
1171 | * Task scheduled to possibly notfiy core that this peer is no | 1135 | * Task scheduled to possibly notfiy core that this peer is no |
1172 | * longer counting as confirmed. Runs the #core_visibility_check(), | 1136 | * longer counting as confirmed. Runs the #core_visibility_check(), |
1173 | * which checks that some DV-path or a queue exists that is still | 1137 | * which checks that some DV-path or a queue exists that is still |
@@ -1186,6 +1150,12 @@ struct VirtualLink | |||
1186 | struct DistanceVector *dv; | 1150 | struct DistanceVector *dv; |
1187 | 1151 | ||
1188 | /** | 1152 | /** |
1153 | * Used to generate unique UUIDs for messages that are being | ||
1154 | * fragmented. | ||
1155 | */ | ||
1156 | uint64_t message_uuid_ctr; | ||
1157 | |||
1158 | /** | ||
1189 | * How many more messages can we send to core before we exhaust | 1159 | * How many more messages can we send to core before we exhaust |
1190 | * the receive window of CORE for this peer? If this hits zero, | 1160 | * the receive window of CORE for this peer? If this hits zero, |
1191 | * we must tell communicators to stop providing us more messages | 1161 | * we must tell communicators to stop providing us more messages |
@@ -1319,16 +1289,6 @@ struct DistanceVectorHop | |||
1319 | struct DistanceVectorHop *prev_neighbour; | 1289 | struct DistanceVectorHop *prev_neighbour; |
1320 | 1290 | ||
1321 | /** | 1291 | /** |
1322 | * Head of MDLL of messages routed via this path. | ||
1323 | */ | ||
1324 | struct PendingMessage *pending_msg_head; | ||
1325 | |||
1326 | /** | ||
1327 | * Tail of MDLL of messages routed via this path. | ||
1328 | */ | ||
1329 | struct PendingMessage *pending_msg_tail; | ||
1330 | |||
1331 | /** | ||
1332 | * Head of DLL of PAs that used our @a path. | 1292 | * Head of DLL of PAs that used our @a path. |
1333 | */ | 1293 | */ |
1334 | struct PendingAcknowledgement *pa_head; | 1294 | struct PendingAcknowledgement *pa_head; |
@@ -1416,6 +1376,32 @@ struct DistanceVector | |||
1416 | * CORE? If so, this is the virtual link, otherwise NULL. | 1376 | * CORE? If so, this is the virtual link, otherwise NULL. |
1417 | */ | 1377 | */ |
1418 | struct VirtualLink *link; | 1378 | struct VirtualLink *link; |
1379 | |||
1380 | /** | ||
1381 | * Signature affirming @e ephemeral_key of type | ||
1382 | * #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL | ||
1383 | */ | ||
1384 | struct GNUNET_CRYPTO_EddsaSignature sender_sig; | ||
1385 | |||
1386 | /** | ||
1387 | * How long is @e sender_sig valid | ||
1388 | */ | ||
1389 | struct GNUNET_TIME_Absolute ephemeral_validity; | ||
1390 | |||
1391 | /** | ||
1392 | * What time was @e sender_sig created | ||
1393 | */ | ||
1394 | struct GNUNET_TIME_Absolute monotime; | ||
1395 | |||
1396 | /** | ||
1397 | * Our ephemeral key. | ||
1398 | */ | ||
1399 | struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key; | ||
1400 | |||
1401 | /** | ||
1402 | * Our private ephemeral key. | ||
1403 | */ | ||
1404 | struct GNUNET_CRYPTO_EcdhePrivateKey private_key; | ||
1419 | }; | 1405 | }; |
1420 | 1406 | ||
1421 | 1407 | ||
@@ -1673,16 +1659,6 @@ struct Neighbour | |||
1673 | struct GNUNET_SCHEDULER_Task *reassembly_timeout_task; | 1659 | struct GNUNET_SCHEDULER_Task *reassembly_timeout_task; |
1674 | 1660 | ||
1675 | /** | 1661 | /** |
1676 | * Head of list of messages pending for this neighbour. | ||
1677 | */ | ||
1678 | struct PendingMessage *pending_msg_head; | ||
1679 | |||
1680 | /** | ||
1681 | * Tail of list of messages pending for this neighbour. | ||
1682 | */ | ||
1683 | struct PendingMessage *pending_msg_tail; | ||
1684 | |||
1685 | /** | ||
1686 | * Head of MDLL of DV hops that have this neighbour as next hop. Must be | 1662 | * Head of MDLL of DV hops that have this neighbour as next hop. Must be |
1687 | * purged if this neighbour goes down. | 1663 | * purged if this neighbour goes down. |
1688 | */ | 1664 | */ |
@@ -1729,12 +1705,6 @@ struct Neighbour | |||
1729 | struct GNUNET_TIME_Absolute last_dv_learn_monotime; | 1705 | struct GNUNET_TIME_Absolute last_dv_learn_monotime; |
1730 | 1706 | ||
1731 | /** | 1707 | /** |
1732 | * Used to generate unique UUIDs for messages that are being | ||
1733 | * fragmented. | ||
1734 | */ | ||
1735 | uint64_t message_uuid_ctr; | ||
1736 | |||
1737 | /** | ||
1738 | * Do we have the lastest value for @e last_dv_learn_monotime from | 1708 | * Do we have the lastest value for @e last_dv_learn_monotime from |
1739 | * PEERSTORE yet, or are we still waiting for a reply of PEERSTORE? | 1709 | * PEERSTORE yet, or are we still waiting for a reply of PEERSTORE? |
1740 | */ | 1710 | */ |
@@ -1840,14 +1810,14 @@ enum PendingMessageType | |||
1840 | struct PendingMessage | 1810 | struct PendingMessage |
1841 | { | 1811 | { |
1842 | /** | 1812 | /** |
1843 | * Kept in a MDLL of messages for this @a target. | 1813 | * Kept in a MDLL of messages for this @a vl. |
1844 | */ | 1814 | */ |
1845 | struct PendingMessage *next_neighbour; | 1815 | struct PendingMessage *next_vl; |
1846 | 1816 | ||
1847 | /** | 1817 | /** |
1848 | * Kept in a MDLL of messages for this @a target. | 1818 | * Kept in a MDLL of messages for this @a vl. |
1849 | */ | 1819 | */ |
1850 | struct PendingMessage *prev_neighbour; | 1820 | struct PendingMessage *prev_vl; |
1851 | 1821 | ||
1852 | /** | 1822 | /** |
1853 | * Kept in a MDLL of messages from this @a client (if @e pmt is #PMT_CORE) | 1823 | * Kept in a MDLL of messages from this @a client (if @e pmt is #PMT_CORE) |
@@ -1872,18 +1842,6 @@ struct PendingMessage | |||
1872 | struct PendingMessage *prev_frag; | 1842 | struct PendingMessage *prev_frag; |
1873 | 1843 | ||
1874 | /** | 1844 | /** |
1875 | * Kept in a MDLL of messages using this @a dvh (if @e dvh is | ||
1876 | * non-NULL). | ||
1877 | */ | ||
1878 | struct PendingMessage *next_dvh; | ||
1879 | |||
1880 | /** | ||
1881 | * Kept in a MDLL of messages using this @a dvh (if @e dvh is | ||
1882 | * non-NULL). | ||
1883 | */ | ||
1884 | struct PendingMessage *prev_dvh; | ||
1885 | |||
1886 | /** | ||
1887 | * Head of DLL of PAs for this pending message. | 1845 | * Head of DLL of PAs for this pending message. |
1888 | */ | 1846 | */ |
1889 | struct PendingAcknowledgement *pa_head; | 1847 | struct PendingAcknowledgement *pa_head; |
@@ -1900,16 +1858,9 @@ struct PendingMessage | |||
1900 | struct PendingMessage *bpm; | 1858 | struct PendingMessage *bpm; |
1901 | 1859 | ||
1902 | /** | 1860 | /** |
1903 | * Target of the request (for transmission, may not be ultimate | 1861 | * Target of the request (always the ultimate destination!). |
1904 | * destination!). | ||
1905 | */ | 1862 | */ |
1906 | struct Neighbour *target; | 1863 | struct VirtualLink *vl; |
1907 | |||
1908 | /** | ||
1909 | * Distance vector path selected for this message, or | ||
1910 | * NULL if transmitted directly. | ||
1911 | */ | ||
1912 | struct DistanceVectorHop *dvh; | ||
1913 | 1864 | ||
1914 | /** | 1865 | /** |
1915 | * Set to non-NULL value if this message is currently being given to a | 1866 | * Set to non-NULL value if this message is currently being given to a |
@@ -2508,26 +2459,6 @@ static struct GNUNET_CONTAINER_Heap *validation_heap; | |||
2508 | static struct GNUNET_PEERSTORE_Handle *peerstore; | 2459 | static struct GNUNET_PEERSTORE_Handle *peerstore; |
2509 | 2460 | ||
2510 | /** | 2461 | /** |
2511 | * Heap sorting `struct EphemeralCacheEntry` by their | ||
2512 | * key/signature validity. | ||
2513 | */ | ||
2514 | static struct GNUNET_CONTAINER_Heap *ephemeral_heap; | ||
2515 | |||
2516 | /** | ||
2517 | * Hash map for looking up `struct EphemeralCacheEntry`s | ||
2518 | * by peer identity. (We may have ephemerals in our | ||
2519 | * cache for which we do not have a neighbour entry, | ||
2520 | * and similar many neighbours may not need ephemerals, | ||
2521 | * so we use a second map.) | ||
2522 | */ | ||
2523 | static struct GNUNET_CONTAINER_MultiPeerMap *ephemeral_map; | ||
2524 | |||
2525 | /** | ||
2526 | * Task to free expired ephemerals. | ||
2527 | */ | ||
2528 | static struct GNUNET_SCHEDULER_Task *ephemeral_task; | ||
2529 | |||
2530 | /** | ||
2531 | * Task run to initiate DV learning. | 2462 | * Task run to initiate DV learning. |
2532 | */ | 2463 | */ |
2533 | static struct GNUNET_SCHEDULER_Task *dvlearn_task; | 2464 | static struct GNUNET_SCHEDULER_Task *dvlearn_task; |
@@ -2629,16 +2560,76 @@ free_pending_acknowledgement (struct PendingAcknowledgement *pa) | |||
2629 | 2560 | ||
2630 | 2561 | ||
2631 | /** | 2562 | /** |
2632 | * Free cached ephemeral key. | 2563 | * Free fragment tree below @e root, excluding @e root itself. |
2564 | * FIXME: this does NOT seem to have the intended semantics | ||
2565 | * based on how this is called. Seems we generally DO expect | ||
2566 | * @a root to be free'ed itself as well! | ||
2633 | * | 2567 | * |
2634 | * @param ece cached signature to free | 2568 | * @param root root of the tree to free |
2635 | */ | 2569 | */ |
2636 | static void | 2570 | static void |
2637 | free_ephemeral (struct EphemeralCacheEntry *ece) | 2571 | free_fragment_tree (struct PendingMessage *root) |
2638 | { | 2572 | { |
2639 | GNUNET_CONTAINER_multipeermap_remove (ephemeral_map, &ece->target, ece); | 2573 | struct PendingMessage *frag; |
2640 | GNUNET_CONTAINER_heap_remove_node (ece->hn); | 2574 | |
2641 | GNUNET_free (ece); | 2575 | while (NULL != (frag = root->head_frag)) |
2576 | { | ||
2577 | struct PendingAcknowledgement *pa; | ||
2578 | |||
2579 | free_fragment_tree (frag); | ||
2580 | while (NULL != (pa = frag->pa_head)) | ||
2581 | { | ||
2582 | GNUNET_CONTAINER_MDLL_remove (pm, frag->pa_head, frag->pa_tail, pa); | ||
2583 | pa->pm = NULL; | ||
2584 | } | ||
2585 | GNUNET_CONTAINER_MDLL_remove (frag, root->head_frag, root->tail_frag, frag); | ||
2586 | GNUNET_free (frag); | ||
2587 | } | ||
2588 | } | ||
2589 | |||
2590 | |||
2591 | /** | ||
2592 | * Release memory associated with @a pm and remove @a pm from associated | ||
2593 | * data structures. @a pm must be a top-level pending message and not | ||
2594 | * a fragment in the tree. The entire tree is freed (if applicable). | ||
2595 | * | ||
2596 | * @param pm the pending message to free | ||
2597 | */ | ||
2598 | static void | ||
2599 | free_pending_message (struct PendingMessage *pm) | ||
2600 | { | ||
2601 | struct TransportClient *tc = pm->client; | ||
2602 | struct VirtualLink *vl = pm->vl; | ||
2603 | struct PendingAcknowledgement *pa; | ||
2604 | |||
2605 | if (NULL != tc) | ||
2606 | { | ||
2607 | GNUNET_CONTAINER_MDLL_remove (client, | ||
2608 | tc->details.core.pending_msg_head, | ||
2609 | tc->details.core.pending_msg_tail, | ||
2610 | pm); | ||
2611 | } | ||
2612 | if (NULL != vl) | ||
2613 | { | ||
2614 | GNUNET_CONTAINER_MDLL_remove (vl, | ||
2615 | vl->pending_msg_head, | ||
2616 | vl->pending_msg_tail, | ||
2617 | pm); | ||
2618 | } | ||
2619 | while (NULL != (pa = pm->pa_head)) | ||
2620 | { | ||
2621 | GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa); | ||
2622 | pa->pm = NULL; | ||
2623 | } | ||
2624 | |||
2625 | free_fragment_tree (pm); | ||
2626 | if (NULL != pm->qe) | ||
2627 | { | ||
2628 | GNUNET_assert (pm == pm->qe->pm); | ||
2629 | pm->qe->pm = NULL; | ||
2630 | } | ||
2631 | GNUNET_free_non_null (pm->bpm); | ||
2632 | GNUNET_free (pm); | ||
2642 | } | 2633 | } |
2643 | 2634 | ||
2644 | 2635 | ||
@@ -2650,6 +2641,10 @@ free_ephemeral (struct EphemeralCacheEntry *ece) | |||
2650 | static void | 2641 | static void |
2651 | free_virtual_link (struct VirtualLink *vl) | 2642 | free_virtual_link (struct VirtualLink *vl) |
2652 | { | 2643 | { |
2644 | struct PendingMessage *pm; | ||
2645 | |||
2646 | while (NULL != (pm = vl->pending_msg_head)) | ||
2647 | free_pending_message (pm); | ||
2653 | GNUNET_CONTAINER_multipeermap_remove (links, &vl->target, vl); | 2648 | GNUNET_CONTAINER_multipeermap_remove (links, &vl->target, vl); |
2654 | if (NULL != vl->visibility_task) | 2649 | if (NULL != vl->visibility_task) |
2655 | { | 2650 | { |
@@ -2744,16 +2739,7 @@ free_distance_vector_hop (struct DistanceVectorHop *dvh) | |||
2744 | struct Neighbour *n = dvh->next_hop; | 2739 | struct Neighbour *n = dvh->next_hop; |
2745 | struct DistanceVector *dv = dvh->dv; | 2740 | struct DistanceVector *dv = dvh->dv; |
2746 | struct PendingAcknowledgement *pa; | 2741 | struct PendingAcknowledgement *pa; |
2747 | struct PendingMessage *pm; | ||
2748 | 2742 | ||
2749 | while (NULL != (pm = dvh->pending_msg_head)) | ||
2750 | { | ||
2751 | GNUNET_CONTAINER_MDLL_remove (dvh, | ||
2752 | dvh->pending_msg_head, | ||
2753 | dvh->pending_msg_tail, | ||
2754 | pm); | ||
2755 | pm->dvh = NULL; | ||
2756 | } | ||
2757 | while (NULL != (pa = dvh->pa_head)) | 2743 | while (NULL != (pa = dvh->pa_head)) |
2758 | { | 2744 | { |
2759 | GNUNET_CONTAINER_MDLL_remove (dvh, dvh->pa_head, dvh->pa_tail, pa); | 2745 | GNUNET_CONTAINER_MDLL_remove (dvh, dvh->pa_head, dvh->pa_tail, pa); |
@@ -3098,11 +3084,6 @@ transmit_on_queue (void *cls); | |||
3098 | static void | 3084 | static void |
3099 | schedule_transmit_on_queue (struct Queue *queue, int inside_job) | 3085 | schedule_transmit_on_queue (struct Queue *queue, int inside_job) |
3100 | { | 3086 | { |
3101 | struct Neighbour *n = queue->neighbour; | ||
3102 | struct PendingMessage *pm = n->pending_msg_head; | ||
3103 | struct GNUNET_TIME_Relative out_delay; | ||
3104 | |||
3105 | GNUNET_assert (NULL != pm); | ||
3106 | if (queue->tc->details.communicator.total_queue_length >= | 3087 | if (queue->tc->details.communicator.total_queue_length >= |
3107 | COMMUNICATOR_TOTAL_QUEUE_LIMIT) | 3088 | COMMUNICATOR_TOTAL_QUEUE_LIMIT) |
3108 | { | 3089 | { |
@@ -3121,8 +3102,10 @@ schedule_transmit_on_queue (struct Queue *queue, int inside_job) | |||
3121 | GNUNET_NO); | 3102 | GNUNET_NO); |
3122 | return; | 3103 | return; |
3123 | } | 3104 | } |
3105 | #if FIXME - NEXT | ||
3106 | struct Neighbour *n = queue->neighbour; | ||
3107 | struct GNUNET_TIME_Relative out_delay; | ||
3124 | 3108 | ||
3125 | out_delay = GNUNET_TIME_absolute_get_remaining (pm->next_attempt); | ||
3126 | if ((GNUNET_YES == inside_job) && (0 == out_delay.rel_value_us)) | 3109 | if ((GNUNET_YES == inside_job) && (0 == out_delay.rel_value_us)) |
3127 | { | 3110 | { |
3128 | GNUNET_log ( | 3111 | GNUNET_log ( |
@@ -3148,6 +3131,7 @@ schedule_transmit_on_queue (struct Queue *queue, int inside_job) | |||
3148 | pm->logging_uuid, | 3131 | pm->logging_uuid, |
3149 | queue->address, | 3132 | queue->address, |
3150 | GNUNET_STRINGS_relative_time_to_string (out_delay, GNUNET_YES)); | 3133 | GNUNET_STRINGS_relative_time_to_string (out_delay, GNUNET_YES)); |
3134 | #endif | ||
3151 | } | 3135 | } |
3152 | 3136 | ||
3153 | 3137 | ||
@@ -3488,85 +3472,6 @@ check_client_send (void *cls, const struct OutboundMessage *obm) | |||
3488 | 3472 | ||
3489 | 3473 | ||
3490 | /** | 3474 | /** |
3491 | * Free fragment tree below @e root, excluding @e root itself. | ||
3492 | * FIXME: this does NOT seem to have the intended semantics | ||
3493 | * based on how this is called. Seems we generally DO expect | ||
3494 | * @a root to be free'ed itself as well! | ||
3495 | * | ||
3496 | * @param root root of the tree to free | ||
3497 | */ | ||
3498 | static void | ||
3499 | free_fragment_tree (struct PendingMessage *root) | ||
3500 | { | ||
3501 | struct PendingMessage *frag; | ||
3502 | |||
3503 | while (NULL != (frag = root->head_frag)) | ||
3504 | { | ||
3505 | struct PendingAcknowledgement *pa; | ||
3506 | |||
3507 | free_fragment_tree (frag); | ||
3508 | while (NULL != (pa = frag->pa_head)) | ||
3509 | { | ||
3510 | GNUNET_CONTAINER_MDLL_remove (pm, frag->pa_head, frag->pa_tail, pa); | ||
3511 | pa->pm = NULL; | ||
3512 | } | ||
3513 | GNUNET_CONTAINER_MDLL_remove (frag, root->head_frag, root->tail_frag, frag); | ||
3514 | GNUNET_free (frag); | ||
3515 | } | ||
3516 | } | ||
3517 | |||
3518 | |||
3519 | /** | ||
3520 | * Release memory associated with @a pm and remove @a pm from associated | ||
3521 | * data structures. @a pm must be a top-level pending message and not | ||
3522 | * a fragment in the tree. The entire tree is freed (if applicable). | ||
3523 | * | ||
3524 | * @param pm the pending message to free | ||
3525 | */ | ||
3526 | static void | ||
3527 | free_pending_message (struct PendingMessage *pm) | ||
3528 | { | ||
3529 | struct TransportClient *tc = pm->client; | ||
3530 | struct Neighbour *target = pm->target; | ||
3531 | struct DistanceVectorHop *dvh = pm->dvh; | ||
3532 | struct PendingAcknowledgement *pa; | ||
3533 | |||
3534 | if (NULL != tc) | ||
3535 | { | ||
3536 | GNUNET_CONTAINER_MDLL_remove (client, | ||
3537 | tc->details.core.pending_msg_head, | ||
3538 | tc->details.core.pending_msg_tail, | ||
3539 | pm); | ||
3540 | } | ||
3541 | if (NULL != dvh) | ||
3542 | { | ||
3543 | GNUNET_CONTAINER_MDLL_remove (dvh, | ||
3544 | dvh->pending_msg_head, | ||
3545 | dvh->pending_msg_tail, | ||
3546 | pm); | ||
3547 | } | ||
3548 | GNUNET_CONTAINER_MDLL_remove (neighbour, | ||
3549 | target->pending_msg_head, | ||
3550 | target->pending_msg_tail, | ||
3551 | pm); | ||
3552 | while (NULL != (pa = pm->pa_head)) | ||
3553 | { | ||
3554 | GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa); | ||
3555 | pa->pm = NULL; | ||
3556 | } | ||
3557 | |||
3558 | free_fragment_tree (pm); | ||
3559 | if (NULL != pm->qe) | ||
3560 | { | ||
3561 | GNUNET_assert (pm == pm->qe->pm); | ||
3562 | pm->qe->pm = NULL; | ||
3563 | } | ||
3564 | GNUNET_free_non_null (pm->bpm); | ||
3565 | GNUNET_free (pm); | ||
3566 | } | ||
3567 | |||
3568 | |||
3569 | /** | ||
3570 | * Send a response to the @a pm that we have processed a "send" | 3475 | * Send a response to the @a pm that we have processed a "send" |
3571 | * request. Sends a confirmation to the "core" client responsible for | 3476 | * request. Sends a confirmation to the "core" client responsible for |
3572 | * the original request and free's @a pm. | 3477 | * the original request and free's @a pm. |
@@ -3577,18 +3482,18 @@ static void | |||
3577 | client_send_response (struct PendingMessage *pm) | 3482 | client_send_response (struct PendingMessage *pm) |
3578 | { | 3483 | { |
3579 | struct TransportClient *tc = pm->client; | 3484 | struct TransportClient *tc = pm->client; |
3580 | struct Neighbour *target = pm->target; | 3485 | struct VirtualLink *vl = pm->vl; |
3581 | struct GNUNET_MQ_Envelope *env; | 3486 | struct GNUNET_MQ_Envelope *env; |
3582 | struct SendOkMessage *som; | 3487 | struct SendOkMessage *som; |
3583 | 3488 | ||
3584 | if (NULL != tc) | 3489 | if (NULL != tc) |
3585 | { | 3490 | { |
3586 | env = GNUNET_MQ_msg (som, GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK); | 3491 | env = GNUNET_MQ_msg (som, GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK); |
3587 | som->peer = target->pid; | 3492 | som->peer = vl->target; |
3588 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 3493 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
3589 | "Confirming transmission of <%llu> to %s\n", | 3494 | "Confirming transmission of <%llu> to %s\n", |
3590 | pm->logging_uuid, | 3495 | pm->logging_uuid, |
3591 | GNUNET_i2s (&pm->target->pid)); | 3496 | GNUNET_i2s (&vl->target)); |
3592 | GNUNET_MQ_send (tc->mq, env); | 3497 | GNUNET_MQ_send (tc->mq, env); |
3593 | } | 3498 | } |
3594 | free_pending_message (pm); | 3499 | free_pending_message (pm); |
@@ -3596,72 +3501,6 @@ client_send_response (struct PendingMessage *pm) | |||
3596 | 3501 | ||
3597 | 3502 | ||
3598 | /** | 3503 | /** |
3599 | * Create a DV Box message. | ||
3600 | * | ||
3601 | * @param total_hops how many hops did the message take so far | ||
3602 | * @param num_hops length of the @a hops array | ||
3603 | * @param origin origin of the message | ||
3604 | * @param hops next peer(s) to the destination, including destination | ||
3605 | * @param payload encrypted (!) payload of the box | ||
3606 | * @param payload_size number of bytes in @a payload | ||
3607 | * @return boxed message (caller must #GNUNET_free() it). | ||
3608 | */ | ||
3609 | static struct TransportDVBoxMessage * | ||
3610 | create_dv_box (uint16_t total_hops, | ||
3611 | const struct GNUNET_PeerIdentity *origin, | ||
3612 | const struct GNUNET_PeerIdentity *target, | ||
3613 | uint16_t num_hops, | ||
3614 | const struct GNUNET_PeerIdentity *hops, | ||
3615 | const void *payload, | ||
3616 | uint16_t payload_size) | ||
3617 | { | ||
3618 | struct TransportDVBoxMessage *dvb; | ||
3619 | struct GNUNET_PeerIdentity *dhops; | ||
3620 | |||
3621 | GNUNET_assert (UINT16_MAX < | ||
3622 | sizeof (struct TransportDVBoxMessage) + | ||
3623 | sizeof (struct GNUNET_PeerIdentity) * (num_hops + 1) + | ||
3624 | payload_size); | ||
3625 | dvb = GNUNET_malloc (sizeof (struct TransportDVBoxMessage) + | ||
3626 | sizeof (struct GNUNET_PeerIdentity) * (num_hops + 1) + | ||
3627 | payload_size); | ||
3628 | dvb->header.size = | ||
3629 | htons (sizeof (struct TransportDVBoxMessage) + | ||
3630 | sizeof (struct GNUNET_PeerIdentity) * (num_hops + 1) + payload_size); | ||
3631 | dvb->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX); | ||
3632 | dvb->total_hops = htons (total_hops); | ||
3633 | dvb->num_hops = htons (num_hops + 1); | ||
3634 | dvb->origin = *origin; | ||
3635 | dhops = (struct GNUNET_PeerIdentity *) &dvb[1]; | ||
3636 | memcpy (dhops, hops, num_hops * sizeof (struct GNUNET_PeerIdentity)); | ||
3637 | dhops[num_hops] = *target; | ||
3638 | memcpy (&dhops[num_hops + 1], payload, payload_size); | ||
3639 | |||
3640 | if (GNUNET_EXTRA_LOGGING > 0) | ||
3641 | { | ||
3642 | char *path; | ||
3643 | |||
3644 | path = GNUNET_strdup (GNUNET_i2s (&dvb->origin)); | ||
3645 | for (unsigned int i = 0; i <= num_hops; i++) | ||
3646 | { | ||
3647 | char *tmp; | ||
3648 | |||
3649 | GNUNET_asprintf (&tmp, "%s-%s", path, GNUNET_i2s (&dhops[i])); | ||
3650 | GNUNET_free (path); | ||
3651 | path = tmp; | ||
3652 | } | ||
3653 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
3654 | "Creating DVBox for %u bytes of payload via %s\n", | ||
3655 | (unsigned int) payload_size, | ||
3656 | path); | ||
3657 | GNUNET_free (path); | ||
3658 | } | ||
3659 | |||
3660 | return dvb; | ||
3661 | } | ||
3662 | |||
3663 | |||
3664 | /** | ||
3665 | * Pick @a hops_array_length random DV paths satisfying @a options | 3504 | * Pick @a hops_array_length random DV paths satisfying @a options |
3666 | * | 3505 | * |
3667 | * @param dv data structure to pick paths from | 3506 | * @param dv data structure to pick paths from |
@@ -3752,16 +3591,10 @@ handle_client_send (void *cls, const struct OutboundMessage *obm) | |||
3752 | struct TransportClient *tc = cls; | 3591 | struct TransportClient *tc = cls; |
3753 | struct PendingMessage *pm; | 3592 | struct PendingMessage *pm; |
3754 | const struct GNUNET_MessageHeader *obmm; | 3593 | const struct GNUNET_MessageHeader *obmm; |
3755 | struct Neighbour *target; | ||
3756 | struct DistanceVector *dv; | ||
3757 | struct DistanceVectorHop *dvh; | ||
3758 | uint32_t bytes_msg; | 3594 | uint32_t bytes_msg; |
3759 | int was_empty; | ||
3760 | const void *payload; | ||
3761 | size_t payload_size; | ||
3762 | struct TransportDVBoxMessage *dvb; | ||
3763 | struct VirtualLink *vl; | 3595 | struct VirtualLink *vl; |
3764 | enum GNUNET_MQ_PriorityPreferences pp; | 3596 | enum GNUNET_MQ_PriorityPreferences pp; |
3597 | int was_empty; | ||
3765 | 3598 | ||
3766 | GNUNET_assert (CT_CORE == tc->type); | 3599 | GNUNET_assert (CT_CORE == tc->type); |
3767 | obmm = (const struct GNUNET_MessageHeader *) &obm[1]; | 3600 | obmm = (const struct GNUNET_MessageHeader *) &obm[1]; |
@@ -3781,73 +3614,34 @@ handle_client_send (void *cls, const struct OutboundMessage *obm) | |||
3781 | GNUNET_NO); | 3614 | GNUNET_NO); |
3782 | return; | 3615 | return; |
3783 | } | 3616 | } |
3784 | target = lookup_neighbour (&obm->peer); | ||
3785 | if (NULL == target) | ||
3786 | dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, &obm->peer); | ||
3787 | else | ||
3788 | dv = NULL; | ||
3789 | GNUNET_assert ((NULL != target) || (NULL != dv)); | ||
3790 | if (NULL == target) | ||
3791 | { | ||
3792 | unsigned int res; | ||
3793 | struct DistanceVectorHop *dvh; | ||
3794 | |||
3795 | res = pick_random_dv_hops (dv, RMO_NONE, &dvh, 1); | ||
3796 | GNUNET_assert (1 == res); | ||
3797 | target = dvh->next_hop; | ||
3798 | /* FIXME: encrypt bytes_msg at &obm[1] to &obm->peer first! */ | ||
3799 | dvb = create_dv_box (0, | ||
3800 | &GST_my_identity, | ||
3801 | &obm->peer, | ||
3802 | dvh->distance, | ||
3803 | dvh->path, | ||
3804 | &obm[1], | ||
3805 | bytes_msg); | ||
3806 | payload = dvb; | ||
3807 | payload_size = ntohs (dvb->header.size); | ||
3808 | } | ||
3809 | else | ||
3810 | { | ||
3811 | dvh = NULL; | ||
3812 | dvb = NULL; | ||
3813 | payload = &obm[1]; | ||
3814 | payload_size = bytes_msg; | ||
3815 | } | ||
3816 | 3617 | ||
3817 | was_empty = (NULL == target->pending_msg_head); | 3618 | pm = GNUNET_malloc (sizeof (struct PendingMessage) + bytes_msg); |
3818 | pm = GNUNET_malloc (sizeof (struct PendingMessage) + payload_size); | ||
3819 | pm->logging_uuid = logging_uuid_gen++; | 3619 | pm->logging_uuid = logging_uuid_gen++; |
3820 | pm->prefs = pp; | 3620 | pm->prefs = pp; |
3821 | pm->client = tc; | 3621 | pm->client = tc; |
3822 | pm->target = target; | 3622 | pm->vl = vl; |
3823 | pm->bytes_msg = payload_size; | 3623 | pm->bytes_msg = bytes_msg; |
3824 | memcpy (&pm[1], payload, payload_size); | 3624 | memcpy (&pm[1], obmm, bytes_msg); |
3825 | GNUNET_free_non_null (dvb); | ||
3826 | dvb = NULL; | ||
3827 | pm->dvh = dvh; | ||
3828 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 3625 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
3829 | "Sending %u bytes as <%llu> to %s using %s\n", | 3626 | "Sending %u bytes as <%llu> to %s\n", |
3830 | bytes_msg, | 3627 | bytes_msg, |
3831 | pm->logging_uuid, | 3628 | pm->logging_uuid, |
3832 | GNUNET_i2s (&obm->peer), | 3629 | GNUNET_i2s (&obm->peer)); |
3833 | (NULL == target) ? "distance vector path" : "direct queue"); | ||
3834 | if (NULL != dvh) | ||
3835 | { | ||
3836 | GNUNET_CONTAINER_MDLL_insert (dvh, | ||
3837 | dvh->pending_msg_head, | ||
3838 | dvh->pending_msg_tail, | ||
3839 | pm); | ||
3840 | } | ||
3841 | GNUNET_CONTAINER_MDLL_insert (neighbour, | ||
3842 | target->pending_msg_head, | ||
3843 | target->pending_msg_tail, | ||
3844 | pm); | ||
3845 | GNUNET_CONTAINER_MDLL_insert (client, | 3630 | GNUNET_CONTAINER_MDLL_insert (client, |
3846 | tc->details.core.pending_msg_head, | 3631 | tc->details.core.pending_msg_head, |
3847 | tc->details.core.pending_msg_tail, | 3632 | tc->details.core.pending_msg_tail, |
3848 | pm); | 3633 | pm); |
3634 | was_empty = (NULL == vl->pending_msg_head); | ||
3635 | GNUNET_CONTAINER_MDLL_insert (vl, | ||
3636 | vl->pending_msg_head, | ||
3637 | vl->pending_msg_tail, | ||
3638 | pm); | ||
3849 | if (! was_empty) | 3639 | if (! was_empty) |
3850 | return; /* all queues must already be busy */ | 3640 | return; /* all queues must already be busy */ |
3641 | #if 0 | ||
3642 | // FIXME: check if any DVH or neighbour queue of 'vl' | ||
3643 | // is ready for transmission now. If so, encapsulate | ||
3644 | // 'pm' accordingly and send! | ||
3851 | for (struct Queue *queue = target->queue_head; NULL != queue; | 3645 | for (struct Queue *queue = target->queue_head; NULL != queue; |
3852 | queue = queue->next_neighbour) | 3646 | queue = queue->next_neighbour) |
3853 | { | 3647 | { |
@@ -3862,6 +3656,7 @@ handle_client_send (void *cls, const struct OutboundMessage *obm) | |||
3862 | GNUNET_SCHEDULER_add_now (&transmit_on_queue, queue); | 3656 | GNUNET_SCHEDULER_add_now (&transmit_on_queue, queue); |
3863 | } | 3657 | } |
3864 | } | 3658 | } |
3659 | #endif | ||
3865 | } | 3660 | } |
3866 | 3661 | ||
3867 | 3662 | ||
@@ -4015,13 +3810,6 @@ check_communicator_backchannel ( | |||
4015 | 3810 | ||
4016 | (void) cls; | 3811 | (void) cls; |
4017 | msize = ntohs (cb->header.size) - sizeof (*cb); | 3812 | msize = ntohs (cb->header.size) - sizeof (*cb); |
4018 | if (((size_t) (UINT16_MAX - msize)) > | ||
4019 | sizeof (struct TransportBackchannelEncapsulationMessage) + | ||
4020 | sizeof (struct TransportBackchannelRequestPayloadP)) | ||
4021 | { | ||
4022 | GNUNET_break (0); | ||
4023 | return GNUNET_SYSERR; | ||
4024 | } | ||
4025 | inbox = (const struct GNUNET_MessageHeader *) &cb[1]; | 3813 | inbox = (const struct GNUNET_MessageHeader *) &cb[1]; |
4026 | isize = ntohs (inbox->size); | 3814 | isize = ntohs (inbox->size); |
4027 | if (isize >= msize) | 3815 | if (isize >= msize) |
@@ -4032,7 +3820,7 @@ check_communicator_backchannel ( | |||
4032 | is = (const char *) inbox; | 3820 | is = (const char *) inbox; |
4033 | is += isize; | 3821 | is += isize; |
4034 | msize -= isize; | 3822 | msize -= isize; |
4035 | GNUNET_assert (msize > 0); | 3823 | GNUNET_assert (0 < msize); |
4036 | if ('\0' != is[msize - 1]) | 3824 | if ('\0' != is[msize - 1]) |
4037 | { | 3825 | { |
4038 | GNUNET_break (0); | 3826 | GNUNET_break (0); |
@@ -4043,97 +3831,32 @@ check_communicator_backchannel ( | |||
4043 | 3831 | ||
4044 | 3832 | ||
4045 | /** | 3833 | /** |
4046 | * Remove memory used by expired ephemeral keys. | 3834 | * Ensure ephemeral keys in our @a dv are current. If no current one exists, |
3835 | * set it up. | ||
4047 | * | 3836 | * |
4048 | * @param cls NULL | 3837 | * @param dv[in,out] virtual link to update ephemeral for |
4049 | */ | 3838 | */ |
4050 | static void | 3839 | static void |
4051 | expire_ephemerals (void *cls) | 3840 | update_ephemeral (struct DistanceVector *dv) |
4052 | { | 3841 | { |
4053 | struct EphemeralCacheEntry *ece; | ||
4054 | |||
4055 | (void) cls; | ||
4056 | ephemeral_task = NULL; | ||
4057 | while (NULL != (ece = GNUNET_CONTAINER_heap_peek (ephemeral_heap))) | ||
4058 | { | ||
4059 | if (0 == GNUNET_TIME_absolute_get_remaining (ece->ephemeral_validity) | ||
4060 | .rel_value_us) | ||
4061 | { | ||
4062 | free_ephemeral (ece); | ||
4063 | continue; | ||
4064 | } | ||
4065 | ephemeral_task = GNUNET_SCHEDULER_add_at (ece->ephemeral_validity, | ||
4066 | &expire_ephemerals, | ||
4067 | NULL); | ||
4068 | return; | ||
4069 | } | ||
4070 | } | ||
4071 | |||
4072 | |||
4073 | /** | ||
4074 | * Lookup ephemeral key in our #ephemeral_map. If no valid one exists, | ||
4075 | * generate one, cache it and return it. | ||
4076 | * | ||
4077 | * @param pid peer to look up ephemeral for | ||
4078 | * @param private_key[out] set to the private key | ||
4079 | * @param ephemeral_key[out] set to the key | ||
4080 | * @param ephemeral_sender_sig[out] set to the signature | ||
4081 | * @param monotime[out] set to the monotime used for the signature | ||
4082 | */ | ||
4083 | static void | ||
4084 | lookup_ephemeral (const struct GNUNET_PeerIdentity *pid, | ||
4085 | struct GNUNET_CRYPTO_EcdhePrivateKey *private_key, | ||
4086 | struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral_key, | ||
4087 | struct GNUNET_CRYPTO_EddsaSignature *ephemeral_sender_sig, | ||
4088 | struct GNUNET_TIME_Absolute *monotime) | ||
4089 | { | ||
4090 | struct EphemeralCacheEntry *ece; | ||
4091 | struct EphemeralConfirmationPS ec; | 3842 | struct EphemeralConfirmationPS ec; |
4092 | 3843 | ||
4093 | ece = GNUNET_CONTAINER_multipeermap_get (ephemeral_map, pid); | 3844 | if (0 != |
4094 | if ((NULL != ece) && | 3845 | GNUNET_TIME_absolute_get_remaining (dv->ephemeral_validity).rel_value_us) |
4095 | (0 == GNUNET_TIME_absolute_get_remaining (ece->ephemeral_validity) | 3846 | return; |
4096 | .rel_value_us)) | 3847 | dv->monotime = GNUNET_TIME_absolute_get_monotonic (GST_cfg); |
4097 | { | 3848 | dv->ephemeral_validity = |
4098 | free_ephemeral (ece); | 3849 | GNUNET_TIME_absolute_add (dv->monotime, EPHEMERAL_VALIDITY); |
4099 | ece = NULL; | 3850 | GNUNET_assert (GNUNET_OK == |
4100 | } | 3851 | GNUNET_CRYPTO_ecdhe_key_create2 (&dv->private_key)); |
4101 | if (NULL == ece) | 3852 | GNUNET_CRYPTO_ecdhe_key_get_public (&dv->private_key, &dv->ephemeral_key); |
4102 | { | 3853 | ec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL); |
4103 | ece = GNUNET_new (struct EphemeralCacheEntry); | 3854 | ec.purpose.size = htonl (sizeof (ec)); |
4104 | ece->target = *pid; | 3855 | ec.target = dv->target; |
4105 | ece->monotime = GNUNET_TIME_absolute_get_monotonic (GST_cfg); | 3856 | ec.ephemeral_key = dv->ephemeral_key; |
4106 | ece->ephemeral_validity = | 3857 | GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (GST_my_private_key, |
4107 | GNUNET_TIME_absolute_add (ece->monotime, EPHEMERAL_VALIDITY); | 3858 | &ec.purpose, |
4108 | GNUNET_assert (GNUNET_OK == | 3859 | &dv->sender_sig)); |
4109 | GNUNET_CRYPTO_ecdhe_key_create2 (&ece->private_key)); | ||
4110 | GNUNET_CRYPTO_ecdhe_key_get_public (&ece->private_key, &ece->ephemeral_key); | ||
4111 | ec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL); | ||
4112 | ec.purpose.size = htonl (sizeof (ec)); | ||
4113 | ec.target = *pid; | ||
4114 | ec.ephemeral_key = ece->ephemeral_key; | ||
4115 | GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (GST_my_private_key, | ||
4116 | &ec.purpose, | ||
4117 | &ece->sender_sig)); | ||
4118 | ece->hn = | ||
4119 | GNUNET_CONTAINER_heap_insert (ephemeral_heap, | ||
4120 | ece, | ||
4121 | ece->ephemeral_validity.abs_value_us); | ||
4122 | GNUNET_assert (GNUNET_OK == | ||
4123 | GNUNET_CONTAINER_multipeermap_put ( | ||
4124 | ephemeral_map, | ||
4125 | &ece->target, | ||
4126 | ece, | ||
4127 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
4128 | if (NULL == ephemeral_task) | ||
4129 | ephemeral_task = GNUNET_SCHEDULER_add_at (ece->ephemeral_validity, | ||
4130 | &expire_ephemerals, | ||
4131 | NULL); | ||
4132 | } | ||
4133 | *private_key = ece->private_key; | ||
4134 | *ephemeral_key = ece->ephemeral_key; | ||
4135 | *ephemeral_sender_sig = ece->sender_sig; | ||
4136 | *monotime = ece->monotime; | ||
4137 | } | 3860 | } |
4138 | 3861 | ||
4139 | 3862 | ||
@@ -4239,6 +3962,7 @@ route_via_neighbour (const struct Neighbour *n, | |||
4239 | GNUNET_NO); | 3962 | GNUNET_NO); |
4240 | return; | 3963 | return; |
4241 | } | 3964 | } |
3965 | |||
4242 | sel1 = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, candidates); | 3966 | sel1 = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, candidates); |
4243 | if (0 == (options & RMO_REDUNDANT)) | 3967 | if (0 == (options & RMO_REDUNDANT)) |
4244 | sel2 = candidates; /* picks none! */ | 3968 | sel2 = candidates; /* picks none! */ |
@@ -4268,155 +3992,9 @@ route_via_neighbour (const struct Neighbour *n, | |||
4268 | 3992 | ||
4269 | 3993 | ||
4270 | /** | 3994 | /** |
4271 | * Given a distance vector path @a dvh route @a payload to | ||
4272 | * the ultimate destination respecting @a options. | ||
4273 | * Sets up the boxed message and queues it at the next hop. | ||
4274 | * | ||
4275 | * @param dvh choice of the path for the message | ||
4276 | * @param payload encrypted body to transmit | ||
4277 | * @param payload_len number of bytes in @a payload | ||
4278 | * @param options options to use for control | ||
4279 | */ | ||
4280 | static void | ||
4281 | forward_via_dvh (const struct DistanceVectorHop *dvh, | ||
4282 | const void *payload, | ||
4283 | size_t payload_len, | ||
4284 | enum RouteMessageOptions options) | ||
4285 | { | ||
4286 | struct TransportDVBoxMessage *dvb; | ||
4287 | |||
4288 | dvb = create_dv_box (0, | ||
4289 | &GST_my_identity, | ||
4290 | &dvh->dv->target, | ||
4291 | dvh->distance, | ||
4292 | dvh->path, | ||
4293 | payload, | ||
4294 | payload_len); | ||
4295 | route_via_neighbour (dvh->next_hop, &dvb->header, options); | ||
4296 | GNUNET_free (dvb); | ||
4297 | } | ||
4298 | |||
4299 | |||
4300 | /** | ||
4301 | * Pick a path of @a dv under constraints @a options and schedule | ||
4302 | * transmission of @a hdr. | ||
4303 | * | ||
4304 | * @param n neighbour to send to | ||
4305 | * @param hdr message to send as payload | ||
4306 | * @param options whether path must be confirmed or not | ||
4307 | * and whether we may pick multiple (2) paths | ||
4308 | */ | ||
4309 | static void | ||
4310 | route_via_dv (const struct DistanceVector *dv, | ||
4311 | const struct GNUNET_MessageHeader *hdr, | ||
4312 | enum RouteMessageOptions options) | ||
4313 | { | ||
4314 | struct DistanceVectorHop *hops[2]; | ||
4315 | unsigned int res; | ||
4316 | |||
4317 | res = pick_random_dv_hops (dv, | ||
4318 | options, | ||
4319 | hops, | ||
4320 | (0 == (options & RMO_REDUNDANT)) ? 1 : 2); | ||
4321 | if (0 == res) | ||
4322 | { | ||
4323 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
4324 | "Failed to route message, could not determine DV path\n"); | ||
4325 | return; | ||
4326 | } | ||
4327 | // FIXME: we should encrypt `hdr` here first! | ||
4328 | for (unsigned int i = 0; i < res; i++) | ||
4329 | { | ||
4330 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
4331 | "Routing message of type %u to %s using DV (#%u/%u)\n", | ||
4332 | ntohs (hdr->type), | ||
4333 | GNUNET_i2s (&dv->target), | ||
4334 | i + 1, | ||
4335 | res + 1); | ||
4336 | forward_via_dvh (hops[i], | ||
4337 | hdr, | ||
4338 | ntohs ( | ||
4339 | hdr->size), /* FIXME: can't do this once encrypted... */ | ||
4340 | options & (~RMO_REDUNDANT)); | ||
4341 | } | ||
4342 | } | ||
4343 | |||
4344 | |||
4345 | /** | ||
4346 | * We need to transmit @a hdr to @a target. If necessary, this may | ||
4347 | * involve DV routing. | ||
4348 | * | ||
4349 | * @param target peer to receive @a hdr | ||
4350 | * @param hdr header of the message to route and #GNUNET_free() | ||
4351 | * @param options which transmission channels are allowed | ||
4352 | */ | ||
4353 | static void | ||
4354 | route_message (const struct GNUNET_PeerIdentity *target, | ||
4355 | struct GNUNET_MessageHeader *hdr, | ||
4356 | enum RouteMessageOptions options) | ||
4357 | { | ||
4358 | struct VirtualLink *vl; | ||
4359 | struct Neighbour *n; | ||
4360 | struct DistanceVector *dv; | ||
4361 | |||
4362 | vl = GNUNET_CONTAINER_multipeermap_get (links, target); | ||
4363 | n = vl->n; | ||
4364 | dv = (0 != (options & RMO_DV_ALLOWED)) ? vl->dv : NULL; | ||
4365 | if (0 == (options & RMO_UNCONFIRMED_ALLOWED)) | ||
4366 | { | ||
4367 | /* if confirmed is required, and we do not have anything | ||
4368 | confirmed, drop respective options */ | ||
4369 | if (NULL == n) | ||
4370 | n = lookup_neighbour (target); | ||
4371 | if ((NULL == dv) && (0 != (options & RMO_DV_ALLOWED))) | ||
4372 | dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, target); | ||
4373 | } | ||
4374 | if ((NULL == n) && (NULL == dv)) | ||
4375 | { | ||
4376 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
4377 | "Cannot route message of type %u to %s: no route\n", | ||
4378 | ntohs (hdr->type), | ||
4379 | GNUNET_i2s (target)); | ||
4380 | GNUNET_STATISTICS_update (GST_stats, | ||
4381 | "# Messages dropped in routing: no acceptable method", | ||
4382 | 1, | ||
4383 | GNUNET_NO); | ||
4384 | GNUNET_free (hdr); | ||
4385 | return; | ||
4386 | } | ||
4387 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
4388 | "Routing message of type %u to %s with options %X\n", | ||
4389 | ntohs (hdr->type), | ||
4390 | GNUNET_i2s (target), | ||
4391 | (unsigned int) options); | ||
4392 | /* If both dv and n are possible and we must choose: | ||
4393 | flip a coin for the choice between the two; for now 50/50 */ | ||
4394 | if ((NULL != n) && (NULL != dv) && (0 == (options & RMO_REDUNDANT))) | ||
4395 | { | ||
4396 | if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 2)) | ||
4397 | n = NULL; | ||
4398 | else | ||
4399 | dv = NULL; | ||
4400 | } | ||
4401 | if ((NULL != n) && (NULL != dv)) | ||
4402 | options &= ~RMO_REDUNDANT; /* We will do one DV and one direct, that's | ||
4403 | enough for redunancy, so clear the flag. */ | ||
4404 | if (NULL != n) | ||
4405 | { | ||
4406 | route_via_neighbour (n, hdr, options); | ||
4407 | } | ||
4408 | if (NULL != dv) | ||
4409 | { | ||
4410 | route_via_dv (dv, hdr, options); | ||
4411 | } | ||
4412 | GNUNET_free (hdr); | ||
4413 | } | ||
4414 | |||
4415 | |||
4416 | /** | ||
4417 | * Structure of the key material used to encrypt backchannel messages. | 3995 | * Structure of the key material used to encrypt backchannel messages. |
4418 | */ | 3996 | */ |
4419 | struct BackchannelKeyState | 3997 | struct DVKeyState |
4420 | { | 3998 | { |
4421 | /** | 3999 | /** |
4422 | * State of our block cipher. | 4000 | * State of our block cipher. |
@@ -4457,9 +4035,9 @@ struct BackchannelKeyState | |||
4457 | * @param key[out] symmetric cipher and HMAC state to generate | 4035 | * @param key[out] symmetric cipher and HMAC state to generate |
4458 | */ | 4036 | */ |
4459 | static void | 4037 | static void |
4460 | bc_setup_key_state_from_km (const struct GNUNET_HashCode *km, | 4038 | dv_setup_key_state_from_km (const struct GNUNET_HashCode *km, |
4461 | const struct GNUNET_ShortHashCode *iv, | 4039 | const struct GNUNET_ShortHashCode *iv, |
4462 | struct BackchannelKeyState *key) | 4040 | struct DVKeyState *key) |
4463 | { | 4041 | { |
4464 | /* must match #dh_key_derive_eph_pub */ | 4042 | /* must match #dh_key_derive_eph_pub */ |
4465 | GNUNET_assert (GNUNET_YES == | 4043 | GNUNET_assert (GNUNET_YES == |
@@ -4502,14 +4080,14 @@ dh_key_derive_eph_pid ( | |||
4502 | const struct GNUNET_CRYPTO_EcdhePrivateKey *priv_ephemeral, | 4080 | const struct GNUNET_CRYPTO_EcdhePrivateKey *priv_ephemeral, |
4503 | const struct GNUNET_PeerIdentity *target, | 4081 | const struct GNUNET_PeerIdentity *target, |
4504 | const struct GNUNET_ShortHashCode *iv, | 4082 | const struct GNUNET_ShortHashCode *iv, |
4505 | struct BackchannelKeyState *key) | 4083 | struct DVKeyState *key) |
4506 | { | 4084 | { |
4507 | struct GNUNET_HashCode km; | 4085 | struct GNUNET_HashCode km; |
4508 | 4086 | ||
4509 | GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_ecdh_eddsa (priv_ephemeral, | 4087 | GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_ecdh_eddsa (priv_ephemeral, |
4510 | &target->public_key, | 4088 | &target->public_key, |
4511 | &km)); | 4089 | &km)); |
4512 | bc_setup_key_state_from_km (&km, iv, key); | 4090 | dv_setup_key_state_from_km (&km, iv, key); |
4513 | } | 4091 | } |
4514 | 4092 | ||
4515 | 4093 | ||
@@ -4525,14 +4103,14 @@ dh_key_derive_eph_pid ( | |||
4525 | static void | 4103 | static void |
4526 | dh_key_derive_eph_pub (const struct GNUNET_CRYPTO_EcdhePublicKey *pub_ephemeral, | 4104 | dh_key_derive_eph_pub (const struct GNUNET_CRYPTO_EcdhePublicKey *pub_ephemeral, |
4527 | const struct GNUNET_ShortHashCode *iv, | 4105 | const struct GNUNET_ShortHashCode *iv, |
4528 | struct BackchannelKeyState *key) | 4106 | struct DVKeyState *key) |
4529 | { | 4107 | { |
4530 | struct GNUNET_HashCode km; | 4108 | struct GNUNET_HashCode km; |
4531 | 4109 | ||
4532 | GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_eddsa_ecdh (GST_my_private_key, | 4110 | GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_eddsa_ecdh (GST_my_private_key, |
4533 | pub_ephemeral, | 4111 | pub_ephemeral, |
4534 | &km)); | 4112 | &km)); |
4535 | bc_setup_key_state_from_km (&km, iv, key); | 4113 | dv_setup_key_state_from_km (&km, iv, key); |
4536 | } | 4114 | } |
4537 | 4115 | ||
4538 | 4116 | ||
@@ -4546,7 +4124,7 @@ dh_key_derive_eph_pub (const struct GNUNET_CRYPTO_EcdhePublicKey *pub_ephemeral, | |||
4546 | * @param data_size number of bytes in @a data | 4124 | * @param data_size number of bytes in @a data |
4547 | */ | 4125 | */ |
4548 | static void | 4126 | static void |
4549 | bc_hmac (const struct BackchannelKeyState *key, | 4127 | dv_hmac (const struct DVKeyState *key, |
4550 | struct GNUNET_HashCode *hmac, | 4128 | struct GNUNET_HashCode *hmac, |
4551 | const void *data, | 4129 | const void *data, |
4552 | size_t data_size) | 4130 | size_t data_size) |
@@ -4565,10 +4143,7 @@ bc_hmac (const struct BackchannelKeyState *key, | |||
4565 | * @param in_size number of bytes of input in @a in and available at @a dst | 4143 | * @param in_size number of bytes of input in @a in and available at @a dst |
4566 | */ | 4144 | */ |
4567 | static void | 4145 | static void |
4568 | bc_encrypt (struct BackchannelKeyState *key, | 4146 | dv_encrypt (struct DVKeyState *key, const void *in, void *dst, size_t in_size) |
4569 | const void *in, | ||
4570 | void *dst, | ||
4571 | size_t in_size) | ||
4572 | { | 4147 | { |
4573 | GNUNET_assert (0 == | 4148 | GNUNET_assert (0 == |
4574 | gcry_cipher_encrypt (key->cipher, dst, in_size, in, in_size)); | 4149 | gcry_cipher_encrypt (key->cipher, dst, in_size, in, in_size)); |
@@ -4585,7 +4160,7 @@ bc_encrypt (struct BackchannelKeyState *key, | |||
4585 | * @param out_size number of bytes of input in @a ciph and available in @a out | 4160 | * @param out_size number of bytes of input in @a ciph and available in @a out |
4586 | */ | 4161 | */ |
4587 | static void | 4162 | static void |
4588 | bc_decrypt (struct BackchannelKeyState *key, | 4163 | dv_decrypt (struct DVKeyState *key, |
4589 | void *out, | 4164 | void *out, |
4590 | const void *ciph, | 4165 | const void *ciph, |
4591 | size_t out_size) | 4166 | size_t out_size) |
@@ -4601,7 +4176,7 @@ bc_decrypt (struct BackchannelKeyState *key, | |||
4601 | * @param key key material to clean up (memory must not be free'd!) | 4176 | * @param key key material to clean up (memory must not be free'd!) |
4602 | */ | 4177 | */ |
4603 | static void | 4178 | static void |
4604 | bc_key_clean (struct BackchannelKeyState *key) | 4179 | dv_key_clean (struct DVKeyState *key) |
4605 | { | 4180 | { |
4606 | gcry_cipher_close (key->cipher); | 4181 | gcry_cipher_close (key->cipher); |
4607 | GNUNET_CRYPTO_zero_keys (&key->material, sizeof (key->material)); | 4182 | GNUNET_CRYPTO_zero_keys (&key->material, sizeof (key->material)); |
@@ -4609,7 +4184,234 @@ bc_key_clean (struct BackchannelKeyState *key) | |||
4609 | 4184 | ||
4610 | 4185 | ||
4611 | /** | 4186 | /** |
4187 | * Function to call to further operate on the now DV encapsulated | ||
4188 | * message @a hdr, forwarding it via @a next_hop under respect of | ||
4189 | * @a options. | ||
4190 | * | ||
4191 | * @param cls closure | ||
4192 | * @param next_hop next hop of the DV path | ||
4193 | * @param hdr encapsulated message, technically a `struct TransportDFBoxMessage` | ||
4194 | * @param options options of the original message | ||
4195 | */ | ||
4196 | typedef void (*DVMessageHandler) (void *cls, | ||
4197 | struct Neighbour *next_hop, | ||
4198 | const struct GNUNET_MessageHeader *hdr, | ||
4199 | enum RouteMessageOptions options); | ||
4200 | |||
4201 | /** | ||
4202 | * Pick a path of @a dv under constraints @a options and schedule | ||
4203 | * transmission of @a hdr. | ||
4204 | * | ||
4205 | * @param target neighbour to ultimately send to | ||
4206 | * @param num_dvhs length of the @a dvhs array | ||
4207 | * @param dvhs array of hops to send the message to | ||
4208 | * @param hdr message to send as payload | ||
4209 | * @param use function to call with the encapsulated message | ||
4210 | * @param use_cls closure for @a use | ||
4211 | * @param options whether path must be confirmed or not, to be passed to @a use | ||
4212 | */ | ||
4213 | static void | ||
4214 | encapsulate_for_dv (struct DistanceVector *dv, | ||
4215 | unsigned int num_dvhs, | ||
4216 | struct DistanceVectorHop **dvhs, | ||
4217 | const struct GNUNET_MessageHeader *hdr, | ||
4218 | DVMessageHandler use, | ||
4219 | void *use_cls, | ||
4220 | enum RouteMessageOptions options) | ||
4221 | { | ||
4222 | struct TransportDVBoxMessage box_hdr; | ||
4223 | struct TransportDVBoxPayloadP payload_hdr; | ||
4224 | uint16_t enc_body_size = ntohs (hdr->size); | ||
4225 | char enc[sizeof (struct TransportDVBoxPayloadP) + enc_body_size] GNUNET_ALIGN; | ||
4226 | struct TransportDVBoxPayloadP *enc_payload_hdr = | ||
4227 | (struct TransportDVBoxPayloadP *) enc; | ||
4228 | struct DVKeyState key; | ||
4229 | |||
4230 | /* Encrypt payload */ | ||
4231 | box_hdr.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX); | ||
4232 | box_hdr.total_hops = htons (0); | ||
4233 | update_ephemeral (dv); | ||
4234 | box_hdr.ephemeral_key = dv->ephemeral_key; | ||
4235 | payload_hdr.sender_sig = dv->sender_sig; | ||
4236 | GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, | ||
4237 | &box_hdr.iv, | ||
4238 | sizeof (box_hdr.iv)); | ||
4239 | dh_key_derive_eph_pid (&dv->private_key, &dv->target, &box_hdr.iv, &key); | ||
4240 | payload_hdr.sender = GST_my_identity; | ||
4241 | payload_hdr.monotonic_time = GNUNET_TIME_absolute_hton (dv->monotime); | ||
4242 | dv_encrypt (&key, &payload_hdr, enc_payload_hdr, sizeof (payload_hdr)); | ||
4243 | dv_encrypt (&key, | ||
4244 | hdr, | ||
4245 | &enc[sizeof (struct TransportDVBoxPayloadP)], | ||
4246 | enc_body_size); | ||
4247 | dv_hmac (&key, &box_hdr.hmac, enc, sizeof (enc)); | ||
4248 | dv_key_clean (&key); | ||
4249 | |||
4250 | /* For each selected path, take the pre-computed header and body | ||
4251 | and add the path in the middle of the message; then send it. */ | ||
4252 | for (unsigned int i = 0; i < num_dvhs; i++) | ||
4253 | { | ||
4254 | struct DistanceVectorHop *dvh = dvhs[i]; | ||
4255 | unsigned int num_hops = dvh->distance + 1; | ||
4256 | char buf[sizeof (struct TransportDVBoxMessage) + | ||
4257 | sizeof (struct GNUNET_PeerIdentity) * num_hops + | ||
4258 | sizeof (struct TransportDVBoxPayloadP) + | ||
4259 | enc_body_size] GNUNET_ALIGN; | ||
4260 | struct GNUNET_PeerIdentity *dhops; | ||
4261 | |||
4262 | box_hdr.header.size = htons (sizeof (buf)); | ||
4263 | box_hdr.num_hops = htons (num_hops); | ||
4264 | memcpy (buf, &box_hdr, sizeof (box_hdr)); | ||
4265 | dhops = (struct GNUNET_PeerIdentity *) &buf[sizeof (box_hdr)]; | ||
4266 | memcpy (dhops, | ||
4267 | dvh->path, | ||
4268 | dvh->distance * sizeof (struct GNUNET_PeerIdentity)); | ||
4269 | dhops[dvh->distance] = dv->target; | ||
4270 | if (GNUNET_EXTRA_LOGGING > 0) | ||
4271 | { | ||
4272 | char *path; | ||
4273 | |||
4274 | path = GNUNET_strdup (GNUNET_i2s (&GST_my_identity)); | ||
4275 | for (unsigned int i = 0; i <= num_hops; i++) | ||
4276 | { | ||
4277 | char *tmp; | ||
4278 | |||
4279 | GNUNET_asprintf (&tmp, "%s-%s", path, GNUNET_i2s (&dhops[i])); | ||
4280 | GNUNET_free (path); | ||
4281 | path = tmp; | ||
4282 | } | ||
4283 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
4284 | "Routing message of type %u to %s using DV (#%u/%u) via %s\n", | ||
4285 | ntohs (hdr->type), | ||
4286 | GNUNET_i2s (&dv->target), | ||
4287 | i + 1, | ||
4288 | num_dvhs + 1, | ||
4289 | path); | ||
4290 | GNUNET_free (path); | ||
4291 | } | ||
4292 | |||
4293 | memcpy (&dhops[num_hops], enc, sizeof (enc)); | ||
4294 | use (use_cls, | ||
4295 | dvh->next_hop, | ||
4296 | (const struct GNUNET_MessageHeader *) buf, | ||
4297 | options); | ||
4298 | } | ||
4299 | } | ||
4300 | |||
4301 | |||
4302 | /** | ||
4303 | * Wrapper around #route_via_neighbour() that matches the | ||
4304 | * #DVMessageHandler structure. | ||
4305 | * | ||
4306 | * @param cls unused | ||
4307 | * @param next_hop where to send next | ||
4308 | * @param hdr header of the message to send | ||
4309 | * @param options message options for queue selection | ||
4310 | */ | ||
4311 | static void | ||
4312 | send_dv_to_neighbour (void *cls, | ||
4313 | struct Neighbour *next_hop, | ||
4314 | const struct GNUNET_MessageHeader *hdr, | ||
4315 | enum RouteMessageOptions options) | ||
4316 | { | ||
4317 | (void) cls; | ||
4318 | route_via_neighbour (next_hop, hdr, options); | ||
4319 | } | ||
4320 | |||
4321 | |||
4322 | /** | ||
4323 | * We need to transmit @a hdr to @a target. If necessary, this may | ||
4324 | * involve DV routing. | ||
4325 | * | ||
4326 | * @param target peer to receive @a hdr | ||
4327 | * @param hdr header of the message to route and #GNUNET_free() | ||
4328 | * @param options which transmission channels are allowed | ||
4329 | */ | ||
4330 | static void | ||
4331 | route_message (const struct GNUNET_PeerIdentity *target, | ||
4332 | const struct GNUNET_MessageHeader *hdr, | ||
4333 | enum RouteMessageOptions options) | ||
4334 | { | ||
4335 | struct VirtualLink *vl; | ||
4336 | struct Neighbour *n; | ||
4337 | struct DistanceVector *dv; | ||
4338 | |||
4339 | vl = GNUNET_CONTAINER_multipeermap_get (links, target); | ||
4340 | n = vl->n; | ||
4341 | dv = (0 != (options & RMO_DV_ALLOWED)) ? vl->dv : NULL; | ||
4342 | if (0 == (options & RMO_UNCONFIRMED_ALLOWED)) | ||
4343 | { | ||
4344 | /* if confirmed is required, and we do not have anything | ||
4345 | confirmed, drop respective options */ | ||
4346 | if (NULL == n) | ||
4347 | n = lookup_neighbour (target); | ||
4348 | if ((NULL == dv) && (0 != (options & RMO_DV_ALLOWED))) | ||
4349 | dv = GNUNET_CONTAINER_multipeermap_get (dv_routes, target); | ||
4350 | } | ||
4351 | if ((NULL == n) && (NULL == dv)) | ||
4352 | { | ||
4353 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
4354 | "Cannot route message of type %u to %s: no route\n", | ||
4355 | ntohs (hdr->type), | ||
4356 | GNUNET_i2s (target)); | ||
4357 | GNUNET_STATISTICS_update (GST_stats, | ||
4358 | "# Messages dropped in routing: no acceptable method", | ||
4359 | 1, | ||
4360 | GNUNET_NO); | ||
4361 | return; | ||
4362 | } | ||
4363 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
4364 | "Routing message of type %u to %s with options %X\n", | ||
4365 | ntohs (hdr->type), | ||
4366 | GNUNET_i2s (target), | ||
4367 | (unsigned int) options); | ||
4368 | /* If both dv and n are possible and we must choose: | ||
4369 | flip a coin for the choice between the two; for now 50/50 */ | ||
4370 | if ((NULL != n) && (NULL != dv) && (0 == (options & RMO_REDUNDANT))) | ||
4371 | { | ||
4372 | if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 2)) | ||
4373 | n = NULL; | ||
4374 | else | ||
4375 | dv = NULL; | ||
4376 | } | ||
4377 | if ((NULL != n) && (NULL != dv)) | ||
4378 | options &= ~RMO_REDUNDANT; /* We will do one DV and one direct, that's | ||
4379 | enough for redunancy, so clear the flag. */ | ||
4380 | if (NULL != n) | ||
4381 | { | ||
4382 | route_via_neighbour (n, hdr, options); | ||
4383 | } | ||
4384 | if (NULL != dv) | ||
4385 | { | ||
4386 | struct DistanceVectorHop *hops[2]; | ||
4387 | unsigned int res; | ||
4388 | |||
4389 | res = pick_random_dv_hops (dv, | ||
4390 | options, | ||
4391 | hops, | ||
4392 | (0 == (options & RMO_REDUNDANT)) ? 1 : 2); | ||
4393 | if (0 == res) | ||
4394 | { | ||
4395 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
4396 | "Failed to route message, could not determine DV path\n"); | ||
4397 | return; | ||
4398 | } | ||
4399 | encapsulate_for_dv (dv, | ||
4400 | res, | ||
4401 | hops, | ||
4402 | hdr, | ||
4403 | &send_dv_to_neighbour, | ||
4404 | NULL, | ||
4405 | options & (~RMO_REDUNDANT)); | ||
4406 | } | ||
4407 | } | ||
4408 | |||
4409 | |||
4410 | /** | ||
4612 | * Communicator requests backchannel transmission. Process the request. | 4411 | * Communicator requests backchannel transmission. Process the request. |
4412 | * Just repacks it into our `struct TransportBackchannelEncapsulationMessage *` | ||
4413 | * (which for now has exactly the same format, only a different message type) | ||
4414 | * and passes it on for routing. | ||
4613 | * | 4415 | * |
4614 | * @param cls the client | 4416 | * @param cls the client |
4615 | * @param cb the send message that was sent | 4417 | * @param cb the send message that was sent |
@@ -4620,62 +4422,33 @@ handle_communicator_backchannel ( | |||
4620 | const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb) | 4422 | const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb) |
4621 | { | 4423 | { |
4622 | struct TransportClient *tc = cls; | 4424 | struct TransportClient *tc = cls; |
4623 | struct GNUNET_CRYPTO_EcdhePrivateKey private_key; | 4425 | const struct GNUNET_MessageHeader *inbox = |
4624 | struct GNUNET_TIME_Absolute monotime; | 4426 | (const struct GNUNET_MessageHeader *) &cb[1]; |
4625 | struct TransportBackchannelEncapsulationMessage *enc; | 4427 | uint16_t isize = ntohs (inbox->size); |
4626 | struct TransportBackchannelRequestPayloadP ppay; | 4428 | const char *is = ((const char *) &cb[1]) + isize; |
4627 | struct BackchannelKeyState key; | 4429 | char |
4628 | char *mpos; | 4430 | mbuf[isize + |
4629 | uint16_t msize; | 4431 | sizeof (struct TransportBackchannelEncapsulationMessage)] GNUNET_ALIGN; |
4630 | 4432 | struct TransportBackchannelEncapsulationMessage *be = | |
4631 | { | 4433 | (struct TransportBackchannelEncapsulationMessage *) mbuf; |
4632 | const struct GNUNET_MessageHeader *inbox; | 4434 | |
4633 | const char *is; | 4435 | /* 0-termination of 'is' was checked already in |
4634 | 4436 | #check_communicator_backchannel() */ | |
4635 | inbox = (const struct GNUNET_MessageHeader *) &cb[1]; | 4437 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
4636 | /* 0-termination of 'is' was checked already in | 4438 | "Preparing backchannel transmission to %s:%s of type %u\n", |
4637 | #check_communicator_backchannel() */ | 4439 | GNUNET_i2s (&cb->pid), |
4638 | is = (const char *) &cb[1]; | 4440 | is, |
4639 | is += ntohs (inbox->size); | 4441 | ntohs (inbox->size)); |
4640 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
4641 | "Preparing backchannel transmission to %s:%s of type %u\n", | ||
4642 | GNUNET_i2s (&cb->pid), | ||
4643 | is, | ||
4644 | ntohs (inbox->size)); | ||
4645 | } | ||
4646 | /* encapsulate and encrypt message */ | 4442 | /* encapsulate and encrypt message */ |
4647 | 4443 | be->header.type = | |
4648 | /* FIXME: this should be done with the DV logic for all | ||
4649 | DV messages, NOT here only for backchannel! */ | ||
4650 | msize = ntohs (cb->header.size) - sizeof (*cb) + | ||
4651 | sizeof (struct TransportBackchannelRequestPayloadP); | ||
4652 | enc = GNUNET_malloc (sizeof (*enc) + msize); | ||
4653 | enc->header.type = | ||
4654 | htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION); | 4444 | htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION); |
4655 | enc->header.size = htons (sizeof (*enc) + msize); | 4445 | be->header.size = htons (sizeof (mbuf)); |
4656 | enc->target = cb->pid; | 4446 | memcpy (&be[1], inbox, isize); |
4657 | lookup_ephemeral (&cb->pid, | 4447 | memcpy (&mbuf[sizeof (struct TransportBackchannelEncapsulationMessage) + |
4658 | &private_key, | 4448 | isize], |
4659 | &enc->ephemeral_key, | 4449 | is, |
4660 | &ppay.sender_sig, | 4450 | strlen (is) + 1); |
4661 | &monotime); | 4451 | route_message (&cb->pid, &be->header, RMO_DV_ALLOWED); |
4662 | GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, | ||
4663 | &enc->iv, | ||
4664 | sizeof (enc->iv)); | ||
4665 | dh_key_derive_eph_pid (&private_key, &cb->pid, &enc->iv, &key); | ||
4666 | ppay.monotonic_time = GNUNET_TIME_absolute_hton (monotime); | ||
4667 | mpos = (char *) &enc[1]; | ||
4668 | bc_encrypt (&key, &ppay, mpos, sizeof (ppay)); | ||
4669 | bc_encrypt (&key, | ||
4670 | &cb[1], | ||
4671 | &mpos[sizeof (ppay)], | ||
4672 | ntohs (cb->header.size) - sizeof (*cb)); | ||
4673 | bc_hmac (&key, | ||
4674 | &enc->hmac, | ||
4675 | mpos, | ||
4676 | sizeof (ppay) + ntohs (cb->header.size) - sizeof (*cb)); | ||
4677 | bc_key_clean (&key); | ||
4678 | route_message (&cb->pid, &enc->header, RMO_DV_ALLOWED); | ||
4679 | GNUNET_SERVICE_client_continue (tc->client); | 4452 | GNUNET_SERVICE_client_continue (tc->client); |
4680 | } | 4453 | } |
4681 | 4454 | ||
@@ -5012,7 +4785,11 @@ static void | |||
5012 | transmit_cummulative_ack_cb (void *cls) | 4785 | transmit_cummulative_ack_cb (void *cls) |
5013 | { | 4786 | { |
5014 | struct AcknowledgementCummulator *ac = cls; | 4787 | struct AcknowledgementCummulator *ac = cls; |
5015 | struct TransportReliabilityAckMessage *ack; | 4788 | char buf[sizeof (struct TransportReliabilityAckMessage) + |
4789 | ac->ack_counter * | ||
4790 | sizeof (struct TransportCummulativeAckPayloadP)] GNUNET_ALIGN; | ||
4791 | struct TransportReliabilityAckMessage *ack = | ||
4792 | (struct TransportReliabilityAckMessage *) buf; | ||
5016 | struct TransportCummulativeAckPayloadP *ap; | 4793 | struct TransportCummulativeAckPayloadP *ap; |
5017 | 4794 | ||
5018 | ac->task = NULL; | 4795 | ac->task = NULL; |
@@ -5021,9 +4798,6 @@ transmit_cummulative_ack_cb (void *cls) | |||
5021 | ac->ack_counter, | 4798 | ac->ack_counter, |
5022 | GNUNET_i2s (&ac->target)); | 4799 | GNUNET_i2s (&ac->target)); |
5023 | GNUNET_assert (0 < ac->ack_counter); | 4800 | GNUNET_assert (0 < ac->ack_counter); |
5024 | ack = GNUNET_malloc (sizeof (*ack) + | ||
5025 | ac->ack_counter * | ||
5026 | sizeof (struct TransportCummulativeAckPayloadP)); | ||
5027 | ack->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK); | 4801 | ack->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK); |
5028 | ack->header.size = | 4802 | ack->header.size = |
5029 | htons (sizeof (*ack) + | 4803 | htons (sizeof (*ack) + |
@@ -5576,12 +5350,22 @@ check_backchannel_encapsulation ( | |||
5576 | void *cls, | 5350 | void *cls, |
5577 | const struct TransportBackchannelEncapsulationMessage *be) | 5351 | const struct TransportBackchannelEncapsulationMessage *be) |
5578 | { | 5352 | { |
5579 | uint16_t size = ntohs (be->header.size); | 5353 | uint16_t size = ntohs (be->header.size) - sizeof (*be); |
5354 | const struct GNUNET_MessageHeader *inbox = | ||
5355 | (const struct GNUNET_MessageHeader *) &be[1]; | ||
5356 | const char *is; | ||
5357 | uint16_t isize; | ||
5580 | 5358 | ||
5581 | (void) cls; | 5359 | (void) cls; |
5582 | if ((size - sizeof (*be)) < | 5360 | if (ntohs (inbox->size) >= size) |
5583 | (sizeof (struct TransportBackchannelRequestPayloadP) + | 5361 | { |
5584 | sizeof (struct GNUNET_MessageHeader))) | 5362 | GNUNET_break_op (0); |
5363 | return GNUNET_SYSERR; | ||
5364 | } | ||
5365 | isize = ntohs (inbox->size); | ||
5366 | is = ((const char *) inbox) + isize; | ||
5367 | size -= isize; | ||
5368 | if ('\0' != is[size - 1]) | ||
5585 | { | 5369 | { |
5586 | GNUNET_break_op (0); | 5370 | GNUNET_break_op (0); |
5587 | return GNUNET_SYSERR; | 5371 | return GNUNET_SYSERR; |
@@ -5591,40 +5375,27 @@ check_backchannel_encapsulation ( | |||
5591 | 5375 | ||
5592 | 5376 | ||
5593 | /** | 5377 | /** |
5594 | * We received the plaintext @a msg from backtalker @a b. Forward | 5378 | * Communicator gave us a backchannel encapsulation. Process the request. |
5595 | * it to the respective communicator. | 5379 | * (We are the destination of the backchannel here.) |
5596 | * | 5380 | * |
5597 | * @param b a backtalker | 5381 | * @param cls a `struct CommunicatorMessageContext` (must call |
5598 | * @param msg a message, consisting of a `struct GNUNET_MessageHeader` | 5382 | * #finish_cmc_handling() when done) |
5599 | * followed by the target name of the communicator | 5383 | * @param be the message that was received |
5600 | * @param msg_size number of bytes in @a msg | ||
5601 | */ | 5384 | */ |
5602 | static void | 5385 | static void |
5603 | forward_backchannel_payload (struct Backtalker *b, | 5386 | handle_backchannel_encapsulation ( |
5604 | const void *msg, | 5387 | void *cls, |
5605 | size_t msg_size) | 5388 | const struct TransportBackchannelEncapsulationMessage *be) |
5606 | { | 5389 | { |
5390 | struct CommunicatorMessageContext *cmc = cls; | ||
5607 | struct GNUNET_TRANSPORT_CommunicatorBackchannelIncoming *cbi; | 5391 | struct GNUNET_TRANSPORT_CommunicatorBackchannelIncoming *cbi; |
5608 | struct GNUNET_MQ_Envelope *env; | 5392 | struct GNUNET_MQ_Envelope *env; |
5609 | struct TransportClient *tc; | 5393 | struct TransportClient *tc; |
5610 | const struct GNUNET_MessageHeader *mh; | 5394 | const struct GNUNET_MessageHeader *inbox = |
5611 | const char *target_communicator; | 5395 | (const struct GNUNET_MessageHeader *) &be[1]; |
5612 | uint16_t mhs; | 5396 | uint16_t isize = ntohs (inbox->size); |
5397 | const char *target_communicator = ((const char *) inbox) + isize; | ||
5613 | 5398 | ||
5614 | /* Determine target_communicator and check @a msg is well-formed */ | ||
5615 | mh = msg; | ||
5616 | mhs = ntohs (mh->size); | ||
5617 | if (mhs <= msg_size) | ||
5618 | { | ||
5619 | GNUNET_break_op (0); | ||
5620 | return; | ||
5621 | } | ||
5622 | target_communicator = &((const char *) msg)[ntohs (mh->size)]; | ||
5623 | if ('\0' != target_communicator[msg_size - mhs - 1]) | ||
5624 | { | ||
5625 | GNUNET_break_op (0); | ||
5626 | return; | ||
5627 | } | ||
5628 | /* Find client providing this communicator */ | 5399 | /* Find client providing this communicator */ |
5629 | for (tc = clients_head; NULL != tc; tc = tc->next) | 5400 | for (tc = clients_head; NULL != tc; tc = tc->next) |
5630 | if ((CT_COMMUNICATOR == tc->type) && | 5401 | if ((CT_COMMUNICATOR == tc->type) && |
@@ -5646,344 +5417,20 @@ forward_backchannel_payload (struct Backtalker *b, | |||
5646 | /* Finally, deliver backchannel message to communicator */ | 5417 | /* Finally, deliver backchannel message to communicator */ |
5647 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 5418 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
5648 | "Delivering backchannel message from %s of type %u to %s\n", | 5419 | "Delivering backchannel message from %s of type %u to %s\n", |
5649 | GNUNET_i2s (&b->pid), | 5420 | GNUNET_i2s (&cmc->im.sender), |
5650 | ntohs (mh->type), | 5421 | ntohs (inbox->type), |
5651 | target_communicator); | 5422 | target_communicator); |
5652 | env = GNUNET_MQ_msg_extra ( | 5423 | env = GNUNET_MQ_msg_extra ( |
5653 | cbi, | 5424 | cbi, |
5654 | msg_size, | 5425 | isize, |
5655 | GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL_INCOMING); | 5426 | GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL_INCOMING); |
5656 | cbi->pid = b->pid; | 5427 | cbi->pid = cmc->im.sender; |
5657 | memcpy (&cbi[1], msg, msg_size); | 5428 | memcpy (&cbi[1], inbox, isize); |
5658 | GNUNET_MQ_send (tc->mq, env); | 5429 | GNUNET_MQ_send (tc->mq, env); |
5659 | } | 5430 | } |
5660 | 5431 | ||
5661 | 5432 | ||
5662 | /** | 5433 | /** |
5663 | * Free data structures associated with @a b. | ||
5664 | * | ||
5665 | * @param b data structure to release | ||
5666 | */ | ||
5667 | static void | ||
5668 | free_backtalker (struct Backtalker *b) | ||
5669 | { | ||
5670 | if (NULL != b->get) | ||
5671 | { | ||
5672 | GNUNET_PEERSTORE_iterate_cancel (b->get); | ||
5673 | b->get = NULL; | ||
5674 | GNUNET_assert (NULL != b->cmc); | ||
5675 | finish_cmc_handling (b->cmc); | ||
5676 | b->cmc = NULL; | ||
5677 | } | ||
5678 | if (NULL != b->task) | ||
5679 | { | ||
5680 | GNUNET_SCHEDULER_cancel (b->task); | ||
5681 | b->task = NULL; | ||
5682 | } | ||
5683 | if (NULL != b->sc) | ||
5684 | { | ||
5685 | GNUNET_PEERSTORE_store_cancel (b->sc); | ||
5686 | b->sc = NULL; | ||
5687 | } | ||
5688 | GNUNET_assert ( | ||
5689 | GNUNET_YES == | ||
5690 | GNUNET_CONTAINER_multipeermap_remove (backtalkers, &b->pid, b)); | ||
5691 | GNUNET_free (b); | ||
5692 | } | ||
5693 | |||
5694 | |||
5695 | /** | ||
5696 | * Callback to free backtalker records. | ||
5697 | * | ||
5698 | * @param cls NULL | ||
5699 | * @param pid unused | ||
5700 | * @param value a `struct Backtalker` | ||
5701 | * @return #GNUNET_OK (always) | ||
5702 | */ | ||
5703 | static int | ||
5704 | free_backtalker_cb (void *cls, | ||
5705 | const struct GNUNET_PeerIdentity *pid, | ||
5706 | void *value) | ||
5707 | { | ||
5708 | struct Backtalker *b = value; | ||
5709 | |||
5710 | (void) cls; | ||
5711 | (void) pid; | ||
5712 | free_backtalker (b); | ||
5713 | return GNUNET_OK; | ||
5714 | } | ||
5715 | |||
5716 | |||
5717 | /** | ||
5718 | * Function called when it is time to clean up a backtalker. | ||
5719 | * | ||
5720 | * @param cls a `struct Backtalker` | ||
5721 | */ | ||
5722 | static void | ||
5723 | backtalker_timeout_cb (void *cls) | ||
5724 | { | ||
5725 | struct Backtalker *b = cls; | ||
5726 | |||
5727 | b->task = NULL; | ||
5728 | if (0 != GNUNET_TIME_absolute_get_remaining (b->timeout).rel_value_us) | ||
5729 | { | ||
5730 | b->task = GNUNET_SCHEDULER_add_at (b->timeout, &backtalker_timeout_cb, b); | ||
5731 | return; | ||
5732 | } | ||
5733 | GNUNET_assert (NULL == b->sc); | ||
5734 | free_backtalker (b); | ||
5735 | } | ||
5736 | |||
5737 | |||
5738 | /** | ||
5739 | * Function called with the monotonic time of a backtalker | ||
5740 | * by PEERSTORE. Updates the time and continues processing. | ||
5741 | * | ||
5742 | * @param cls a `struct Backtalker` | ||
5743 | * @param record the information found, NULL for the last call | ||
5744 | * @param emsg error message | ||
5745 | */ | ||
5746 | static void | ||
5747 | backtalker_monotime_cb (void *cls, | ||
5748 | const struct GNUNET_PEERSTORE_Record *record, | ||
5749 | const char *emsg) | ||
5750 | { | ||
5751 | struct Backtalker *b = cls; | ||
5752 | struct GNUNET_TIME_AbsoluteNBO *mtbe; | ||
5753 | struct GNUNET_TIME_Absolute mt; | ||
5754 | |||
5755 | (void) emsg; | ||
5756 | if (NULL == record) | ||
5757 | { | ||
5758 | /* we're done with #backtalker_monotime_cb() invocations, | ||
5759 | continue normal processing */ | ||
5760 | b->get = NULL; | ||
5761 | GNUNET_assert (NULL != b->cmc); | ||
5762 | finish_cmc_handling (b->cmc); | ||
5763 | b->cmc = NULL; | ||
5764 | if (0 != b->body_size) | ||
5765 | forward_backchannel_payload (b, &b[1], b->body_size); | ||
5766 | return; | ||
5767 | } | ||
5768 | if (sizeof (*mtbe) != record->value_size) | ||
5769 | { | ||
5770 | GNUNET_break (0); | ||
5771 | return; | ||
5772 | } | ||
5773 | mtbe = record->value; | ||
5774 | mt = GNUNET_TIME_absolute_ntoh (*mtbe); | ||
5775 | if (mt.abs_value_us > b->monotonic_time.abs_value_us) | ||
5776 | { | ||
5777 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
5778 | "Backtalker message from %s dropped, monotime in the past\n", | ||
5779 | GNUNET_i2s (&b->pid)); | ||
5780 | GNUNET_STATISTICS_update ( | ||
5781 | GST_stats, | ||
5782 | "# Backchannel messages dropped: monotonic time not increasing", | ||
5783 | 1, | ||
5784 | GNUNET_NO); | ||
5785 | b->monotonic_time = mt; | ||
5786 | /* Setting body_size to 0 prevents call to #forward_backchannel_payload() | ||
5787 | */ | ||
5788 | b->body_size = 0; | ||
5789 | return; | ||
5790 | } | ||
5791 | } | ||
5792 | |||
5793 | |||
5794 | /** | ||
5795 | * Function called by PEERSTORE when the store operation of | ||
5796 | * a backtalker's monotonic time is complete. | ||
5797 | * | ||
5798 | * @param cls the `struct Backtalker` | ||
5799 | * @param success #GNUNET_OK on success | ||
5800 | */ | ||
5801 | static void | ||
5802 | backtalker_monotime_store_cb (void *cls, int success) | ||
5803 | { | ||
5804 | struct Backtalker *b = cls; | ||
5805 | |||
5806 | if (GNUNET_OK != success) | ||
5807 | { | ||
5808 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
5809 | "Failed to store backtalker's monotonic time in PEERSTORE!\n"); | ||
5810 | } | ||
5811 | b->sc = NULL; | ||
5812 | b->task = GNUNET_SCHEDULER_add_at (b->timeout, &backtalker_timeout_cb, b); | ||
5813 | } | ||
5814 | |||
5815 | |||
5816 | /** | ||
5817 | * The backtalker @a b monotonic time changed. Update PEERSTORE. | ||
5818 | * | ||
5819 | * @param b a backtalker with updated monotonic time | ||
5820 | */ | ||
5821 | static void | ||
5822 | update_backtalker_monotime (struct Backtalker *b) | ||
5823 | { | ||
5824 | struct GNUNET_TIME_AbsoluteNBO mtbe; | ||
5825 | |||
5826 | if (NULL != b->sc) | ||
5827 | { | ||
5828 | GNUNET_PEERSTORE_store_cancel (b->sc); | ||
5829 | b->sc = NULL; | ||
5830 | } | ||
5831 | else | ||
5832 | { | ||
5833 | GNUNET_SCHEDULER_cancel (b->task); | ||
5834 | b->task = NULL; | ||
5835 | } | ||
5836 | mtbe = GNUNET_TIME_absolute_hton (b->monotonic_time); | ||
5837 | b->sc = | ||
5838 | GNUNET_PEERSTORE_store (peerstore, | ||
5839 | "transport", | ||
5840 | &b->pid, | ||
5841 | GNUNET_PEERSTORE_TRANSPORT_BACKCHANNEL_MONOTIME, | ||
5842 | &mtbe, | ||
5843 | sizeof (mtbe), | ||
5844 | GNUNET_TIME_UNIT_FOREVER_ABS, | ||
5845 | GNUNET_PEERSTORE_STOREOPTION_REPLACE, | ||
5846 | &backtalker_monotime_store_cb, | ||
5847 | b); | ||
5848 | } | ||
5849 | |||
5850 | |||
5851 | /** | ||
5852 | * Communicator gave us a backchannel encapsulation. Process the request. | ||
5853 | * (We are not the origin of the backchannel here, the communicator simply | ||
5854 | * received a backchannel message and we are expected to forward it.) | ||
5855 | * | ||
5856 | * @param cls a `struct CommunicatorMessageContext` (must call | ||
5857 | * #finish_cmc_handling() when done) | ||
5858 | * @param be the message that was received | ||
5859 | */ | ||
5860 | static void | ||
5861 | handle_backchannel_encapsulation ( | ||
5862 | void *cls, | ||
5863 | const struct TransportBackchannelEncapsulationMessage *be) | ||
5864 | { | ||
5865 | struct CommunicatorMessageContext *cmc = cls; | ||
5866 | struct BackchannelKeyState key; | ||
5867 | struct GNUNET_HashCode hmac; | ||
5868 | const char *hdr; | ||
5869 | size_t hdr_len; | ||
5870 | |||
5871 | if (0 != GNUNET_memcmp (&be->target, &GST_my_identity)) | ||
5872 | { | ||
5873 | /* not for me, try to route to target */ | ||
5874 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
5875 | "Forwarding backtalk to %s\n", | ||
5876 | GNUNET_i2s (&be->target)); | ||
5877 | route_message (&be->target, | ||
5878 | GNUNET_copy_message (&be->header), | ||
5879 | RMO_DV_ALLOWED); | ||
5880 | finish_cmc_handling (cmc); | ||
5881 | return; | ||
5882 | } | ||
5883 | /* FIXME: this should be done when decrypting _any_ DV | ||
5884 | message, not only for backchannels! */ | ||
5885 | dh_key_derive_eph_pub (&be->ephemeral_key, &be->iv, &key); | ||
5886 | hdr = (const char *) &be[1]; | ||
5887 | hdr_len = ntohs (be->header.size) - sizeof (*be); | ||
5888 | bc_hmac (&key, &hmac, hdr, hdr_len); | ||
5889 | if (0 != GNUNET_memcmp (&hmac, &be->hmac)) | ||
5890 | { | ||
5891 | /* HMAC missmatch, disard! */ | ||
5892 | GNUNET_break_op (0); | ||
5893 | finish_cmc_handling (cmc); | ||
5894 | return; | ||
5895 | } | ||
5896 | /* begin actual decryption */ | ||
5897 | { | ||
5898 | struct Backtalker *b; | ||
5899 | struct GNUNET_TIME_Absolute monotime; | ||
5900 | struct TransportBackchannelRequestPayloadP ppay; | ||
5901 | char body[hdr_len - sizeof (ppay)]; | ||
5902 | |||
5903 | GNUNET_assert (hdr_len >= | ||
5904 | sizeof (ppay) + sizeof (struct GNUNET_MessageHeader)); | ||
5905 | bc_decrypt (&key, &ppay, hdr, sizeof (ppay)); | ||
5906 | bc_decrypt (&key, &body, &hdr[sizeof (ppay)], hdr_len - sizeof (ppay)); | ||
5907 | bc_key_clean (&key); | ||
5908 | monotime = GNUNET_TIME_absolute_ntoh (ppay.monotonic_time); | ||
5909 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
5910 | "Decrypted backtalk from %s\n", | ||
5911 | GNUNET_i2s (&ppay.sender)); | ||
5912 | b = GNUNET_CONTAINER_multipeermap_get (backtalkers, &ppay.sender); | ||
5913 | if ((NULL != b) && (monotime.abs_value_us < b->monotonic_time.abs_value_us)) | ||
5914 | { | ||
5915 | GNUNET_STATISTICS_update ( | ||
5916 | GST_stats, | ||
5917 | "# Backchannel messages dropped: monotonic time not increasing", | ||
5918 | 1, | ||
5919 | GNUNET_NO); | ||
5920 | finish_cmc_handling (cmc); | ||
5921 | return; | ||
5922 | } | ||
5923 | if ((NULL == b) || | ||
5924 | (0 != GNUNET_memcmp (&b->last_ephemeral, &be->ephemeral_key))) | ||
5925 | { | ||
5926 | /* Check signature */ | ||
5927 | struct EphemeralConfirmationPS ec; | ||
5928 | |||
5929 | ec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL); | ||
5930 | ec.purpose.size = htonl (sizeof (ec)); | ||
5931 | ec.target = GST_my_identity; | ||
5932 | ec.ephemeral_key = be->ephemeral_key; | ||
5933 | if ( | ||
5934 | GNUNET_OK != | ||
5935 | GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL, | ||
5936 | &ec.purpose, | ||
5937 | &ppay.sender_sig, | ||
5938 | &ppay.sender.public_key)) | ||
5939 | { | ||
5940 | /* Signature invalid, disard! */ | ||
5941 | GNUNET_break_op (0); | ||
5942 | finish_cmc_handling (cmc); | ||
5943 | return; | ||
5944 | } | ||
5945 | } | ||
5946 | if (NULL != b) | ||
5947 | { | ||
5948 | /* update key cache and mono time */ | ||
5949 | b->last_ephemeral = be->ephemeral_key; | ||
5950 | b->monotonic_time = monotime; | ||
5951 | update_backtalker_monotime (b); | ||
5952 | forward_backchannel_payload (b, body, sizeof (body)); | ||
5953 | b->timeout = | ||
5954 | GNUNET_TIME_relative_to_absolute (BACKCHANNEL_INACTIVITY_TIMEOUT); | ||
5955 | finish_cmc_handling (cmc); | ||
5956 | return; | ||
5957 | } | ||
5958 | /* setup data structure to cache signature AND check | ||
5959 | monotonic time with PEERSTORE before forwarding backchannel payload */ | ||
5960 | b = GNUNET_malloc (sizeof (struct Backtalker) + sizeof (body)); | ||
5961 | b->pid = ppay.sender; | ||
5962 | b->body_size = sizeof (body); | ||
5963 | memcpy (&b[1], body, sizeof (body)); | ||
5964 | GNUNET_assert (GNUNET_YES == | ||
5965 | GNUNET_CONTAINER_multipeermap_put ( | ||
5966 | backtalkers, | ||
5967 | &b->pid, | ||
5968 | b, | ||
5969 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
5970 | b->monotonic_time = monotime; /* NOTE: to be checked still! */ | ||
5971 | b->cmc = cmc; | ||
5972 | b->timeout = | ||
5973 | GNUNET_TIME_relative_to_absolute (BACKCHANNEL_INACTIVITY_TIMEOUT); | ||
5974 | b->task = GNUNET_SCHEDULER_add_at (b->timeout, &backtalker_timeout_cb, b); | ||
5975 | b->get = | ||
5976 | GNUNET_PEERSTORE_iterate (peerstore, | ||
5977 | "transport", | ||
5978 | &b->pid, | ||
5979 | GNUNET_PEERSTORE_TRANSPORT_BACKCHANNEL_MONOTIME, | ||
5980 | &backtalker_monotime_cb, | ||
5981 | b); | ||
5982 | } | ||
5983 | } | ||
5984 | |||
5985 | |||
5986 | /** | ||
5987 | * Task called when we should check if any of the DV paths | 5434 | * Task called when we should check if any of the DV paths |
5988 | * we have learned to a target are due for garbage collection. | 5435 | * we have learned to a target are due for garbage collection. |
5989 | * | 5436 | * |
@@ -6043,6 +5490,8 @@ activate_core_visible_dv_path (struct DistanceVectorHop *hop) | |||
6043 | "Creating new virtual link to %s using DV!\n", | 5490 | "Creating new virtual link to %s using DV!\n", |
6044 | GNUNET_i2s (&dv->target)); | 5491 | GNUNET_i2s (&dv->target)); |
6045 | vl = GNUNET_new (struct VirtualLink); | 5492 | vl = GNUNET_new (struct VirtualLink); |
5493 | vl->message_uuid_ctr = | ||
5494 | GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX); | ||
6046 | vl->target = dv->target; | 5495 | vl->target = dv->target; |
6047 | vl->dv = dv; | 5496 | vl->dv = dv; |
6048 | vl->core_recv_window = RECV_WINDOW_SIZE; | 5497 | vl->core_recv_window = RECV_WINDOW_SIZE; |
@@ -6300,7 +5749,9 @@ forward_dv_learn (const struct GNUNET_PeerIdentity *next_hop, | |||
6300 | struct GNUNET_TIME_Absolute in_time) | 5749 | struct GNUNET_TIME_Absolute in_time) |
6301 | { | 5750 | { |
6302 | struct DVPathEntryP *dhops; | 5751 | struct DVPathEntryP *dhops; |
6303 | struct TransportDVLearnMessage *fwd; | 5752 | char buf[sizeof (struct TransportDVLearnMessage) + |
5753 | (nhops + 1) * sizeof (struct DVPathEntryP)] GNUNET_ALIGN; | ||
5754 | struct TransportDVLearnMessage *fwd = (struct TransportDVLearnMessage *) buf; | ||
6304 | struct GNUNET_TIME_Relative nnd; | 5755 | struct GNUNET_TIME_Relative nnd; |
6305 | 5756 | ||
6306 | /* compute message for forwarding */ | 5757 | /* compute message for forwarding */ |
@@ -6309,8 +5760,6 @@ forward_dv_learn (const struct GNUNET_PeerIdentity *next_hop, | |||
6309 | GNUNET_i2s (&msg->initiator), | 5760 | GNUNET_i2s (&msg->initiator), |
6310 | GNUNET_i2s2 (next_hop)); | 5761 | GNUNET_i2s2 (next_hop)); |
6311 | GNUNET_assert (nhops < MAX_DV_HOPS_ALLOWED); | 5762 | GNUNET_assert (nhops < MAX_DV_HOPS_ALLOWED); |
6312 | fwd = GNUNET_malloc (sizeof (struct TransportDVLearnMessage) + | ||
6313 | (nhops + 1) * sizeof (struct DVPathEntryP)); | ||
6314 | fwd->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN); | 5763 | fwd->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN); |
6315 | fwd->header.size = htons (sizeof (struct TransportDVLearnMessage) + | 5764 | fwd->header.size = htons (sizeof (struct TransportDVLearnMessage) + |
6316 | (nhops + 1) * sizeof (struct DVPathEntryP)); | 5765 | (nhops + 1) * sizeof (struct DVPathEntryP)); |
@@ -6914,10 +6363,6 @@ check_dv_box (void *cls, const struct TransportDVBoxMessage *dvb) | |||
6914 | uint16_t num_hops = ntohs (dvb->num_hops); | 6363 | uint16_t num_hops = ntohs (dvb->num_hops); |
6915 | const struct GNUNET_PeerIdentity *hops = | 6364 | const struct GNUNET_PeerIdentity *hops = |
6916 | (const struct GNUNET_PeerIdentity *) &dvb[1]; | 6365 | (const struct GNUNET_PeerIdentity *) &dvb[1]; |
6917 | const struct GNUNET_MessageHeader *inbox = | ||
6918 | (const struct GNUNET_MessageHeader *) &hops[num_hops]; | ||
6919 | uint16_t isize; | ||
6920 | uint16_t itype; | ||
6921 | 6366 | ||
6922 | (void) cls; | 6367 | (void) cls; |
6923 | if (size < sizeof (*dvb) + num_hops * sizeof (struct GNUNET_PeerIdentity) + | 6368 | if (size < sizeof (*dvb) + num_hops * sizeof (struct GNUNET_PeerIdentity) + |
@@ -6926,25 +6371,13 @@ check_dv_box (void *cls, const struct TransportDVBoxMessage *dvb) | |||
6926 | GNUNET_break_op (0); | 6371 | GNUNET_break_op (0); |
6927 | return GNUNET_SYSERR; | 6372 | return GNUNET_SYSERR; |
6928 | } | 6373 | } |
6929 | isize = ntohs (inbox->size); | 6374 | /* This peer must not be on the path */ |
6930 | if (size != | 6375 | for (unsigned int i = 0; i < num_hops; i++) |
6931 | sizeof (*dvb) + num_hops * sizeof (struct GNUNET_PeerIdentity) + isize) | 6376 | if (0 == GNUNET_memcmp (&hops[i], &GST_my_identity)) |
6932 | { | 6377 | { |
6933 | GNUNET_break_op (0); | 6378 | GNUNET_break_op (0); |
6934 | return GNUNET_SYSERR; | 6379 | return GNUNET_SYSERR; |
6935 | } | 6380 | } |
6936 | itype = ntohs (inbox->type); | ||
6937 | if ((GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX == itype) || | ||
6938 | (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN == itype)) | ||
6939 | { | ||
6940 | GNUNET_break_op (0); | ||
6941 | return GNUNET_SYSERR; | ||
6942 | } | ||
6943 | if (0 == GNUNET_memcmp (&dvb->origin, &GST_my_identity)) | ||
6944 | { | ||
6945 | GNUNET_break_op (0); | ||
6946 | return GNUNET_SYSERR; | ||
6947 | } | ||
6948 | return GNUNET_YES; | 6381 | return GNUNET_YES; |
6949 | } | 6382 | } |
6950 | 6383 | ||
@@ -6963,31 +6396,215 @@ check_dv_box (void *cls, const struct TransportDVBoxMessage *dvb) | |||
6963 | */ | 6396 | */ |
6964 | static void | 6397 | static void |
6965 | forward_dv_box (struct Neighbour *next_hop, | 6398 | forward_dv_box (struct Neighbour *next_hop, |
6399 | const struct TransportDVBoxMessage *hdr, | ||
6966 | uint16_t total_hops, | 6400 | uint16_t total_hops, |
6967 | uint16_t num_hops, | 6401 | uint16_t num_hops, |
6968 | const struct GNUNET_PeerIdentity *origin, | ||
6969 | const struct GNUNET_PeerIdentity *hops, | 6402 | const struct GNUNET_PeerIdentity *hops, |
6970 | const void *payload, | 6403 | const void *enc_payload, |
6971 | uint16_t payload_size) | 6404 | uint16_t enc_payload_size) |
6972 | { | 6405 | { |
6973 | struct TransportDVBoxMessage *dvb; | 6406 | char buf[sizeof (struct TransportDVBoxMessage) + |
6407 | num_hops * sizeof (struct GNUNET_PeerIdentity) + enc_payload_size]; | ||
6408 | struct GNUNET_PeerIdentity *dhops = | ||
6409 | (struct GNUNET_PeerIdentity *) &buf[sizeof (struct TransportDVBoxMessage)]; | ||
6974 | 6410 | ||
6975 | dvb = create_dv_box (total_hops, | 6411 | memcpy (buf, hdr, sizeof (*hdr)); |
6976 | origin, | 6412 | memcpy (dhops, hops, num_hops * sizeof (struct GNUNET_PeerIdentity)); |
6977 | &hops[num_hops - 1] /* == target */, | 6413 | memcpy (&dhops[num_hops], enc_payload, enc_payload_size); |
6978 | num_hops - 1 /* do not count target twice */, | 6414 | route_message (&next_hop->pid, |
6979 | hops, | 6415 | (const struct GNUNET_MessageHeader *) buf, |
6980 | payload, | 6416 | RMO_NONE); |
6981 | payload_size); | 6417 | } |
6982 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 6418 | |
6983 | "Routing DV Box of %u bytes from %s at %u/%u hops via %s\n", | 6419 | |
6984 | payload_size, | 6420 | /** |
6985 | GNUNET_i2s (origin), | 6421 | * Free data structures associated with @a b. |
6986 | (unsigned int) num_hops, | 6422 | * |
6987 | (unsigned int) total_hops, | 6423 | * @param b data structure to release |
6988 | GNUNET_i2s2 (&next_hop->pid)); | 6424 | */ |
6989 | route_message (&next_hop->pid, &dvb->header, RMO_NONE); | 6425 | static void |
6990 | GNUNET_free (dvb); | 6426 | free_backtalker (struct Backtalker *b) |
6427 | { | ||
6428 | if (NULL != b->get) | ||
6429 | { | ||
6430 | GNUNET_PEERSTORE_iterate_cancel (b->get); | ||
6431 | b->get = NULL; | ||
6432 | GNUNET_assert (NULL != b->cmc); | ||
6433 | finish_cmc_handling (b->cmc); | ||
6434 | b->cmc = NULL; | ||
6435 | } | ||
6436 | if (NULL != b->task) | ||
6437 | { | ||
6438 | GNUNET_SCHEDULER_cancel (b->task); | ||
6439 | b->task = NULL; | ||
6440 | } | ||
6441 | if (NULL != b->sc) | ||
6442 | { | ||
6443 | GNUNET_PEERSTORE_store_cancel (b->sc); | ||
6444 | b->sc = NULL; | ||
6445 | } | ||
6446 | GNUNET_assert ( | ||
6447 | GNUNET_YES == | ||
6448 | GNUNET_CONTAINER_multipeermap_remove (backtalkers, &b->pid, b)); | ||
6449 | GNUNET_free (b); | ||
6450 | } | ||
6451 | |||
6452 | |||
6453 | /** | ||
6454 | * Callback to free backtalker records. | ||
6455 | * | ||
6456 | * @param cls NULL | ||
6457 | * @param pid unused | ||
6458 | * @param value a `struct Backtalker` | ||
6459 | * @return #GNUNET_OK (always) | ||
6460 | */ | ||
6461 | static int | ||
6462 | free_backtalker_cb (void *cls, | ||
6463 | const struct GNUNET_PeerIdentity *pid, | ||
6464 | void *value) | ||
6465 | { | ||
6466 | struct Backtalker *b = value; | ||
6467 | |||
6468 | (void) cls; | ||
6469 | (void) pid; | ||
6470 | free_backtalker (b); | ||
6471 | return GNUNET_OK; | ||
6472 | } | ||
6473 | |||
6474 | |||
6475 | /** | ||
6476 | * Function called when it is time to clean up a backtalker. | ||
6477 | * | ||
6478 | * @param cls a `struct Backtalker` | ||
6479 | */ | ||
6480 | static void | ||
6481 | backtalker_timeout_cb (void *cls) | ||
6482 | { | ||
6483 | struct Backtalker *b = cls; | ||
6484 | |||
6485 | b->task = NULL; | ||
6486 | if (0 != GNUNET_TIME_absolute_get_remaining (b->timeout).rel_value_us) | ||
6487 | { | ||
6488 | b->task = GNUNET_SCHEDULER_add_at (b->timeout, &backtalker_timeout_cb, b); | ||
6489 | return; | ||
6490 | } | ||
6491 | GNUNET_assert (NULL == b->sc); | ||
6492 | free_backtalker (b); | ||
6493 | } | ||
6494 | |||
6495 | |||
6496 | /** | ||
6497 | * Function called with the monotonic time of a backtalker | ||
6498 | * by PEERSTORE. Updates the time and continues processing. | ||
6499 | * | ||
6500 | * @param cls a `struct Backtalker` | ||
6501 | * @param record the information found, NULL for the last call | ||
6502 | * @param emsg error message | ||
6503 | */ | ||
6504 | static void | ||
6505 | backtalker_monotime_cb (void *cls, | ||
6506 | const struct GNUNET_PEERSTORE_Record *record, | ||
6507 | const char *emsg) | ||
6508 | { | ||
6509 | struct Backtalker *b = cls; | ||
6510 | struct GNUNET_TIME_AbsoluteNBO *mtbe; | ||
6511 | struct GNUNET_TIME_Absolute mt; | ||
6512 | |||
6513 | (void) emsg; | ||
6514 | if (NULL == record) | ||
6515 | { | ||
6516 | /* we're done with #backtalker_monotime_cb() invocations, | ||
6517 | continue normal processing */ | ||
6518 | b->get = NULL; | ||
6519 | GNUNET_assert (NULL != b->cmc); | ||
6520 | if (0 != b->body_size) | ||
6521 | demultiplex_with_cmc (b->cmc, | ||
6522 | (const struct GNUNET_MessageHeader *) &b[1]); | ||
6523 | else | ||
6524 | finish_cmc_handling (b->cmc); | ||
6525 | b->cmc = NULL; | ||
6526 | return; | ||
6527 | } | ||
6528 | if (sizeof (*mtbe) != record->value_size) | ||
6529 | { | ||
6530 | GNUNET_break (0); | ||
6531 | return; | ||
6532 | } | ||
6533 | mtbe = record->value; | ||
6534 | mt = GNUNET_TIME_absolute_ntoh (*mtbe); | ||
6535 | if (mt.abs_value_us > b->monotonic_time.abs_value_us) | ||
6536 | { | ||
6537 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
6538 | "Backtalker message from %s dropped, monotime in the past\n", | ||
6539 | GNUNET_i2s (&b->pid)); | ||
6540 | GNUNET_STATISTICS_update ( | ||
6541 | GST_stats, | ||
6542 | "# Backchannel messages dropped: monotonic time not increasing", | ||
6543 | 1, | ||
6544 | GNUNET_NO); | ||
6545 | b->monotonic_time = mt; | ||
6546 | /* Setting body_size to 0 prevents call to #forward_backchannel_payload() | ||
6547 | */ | ||
6548 | b->body_size = 0; | ||
6549 | return; | ||
6550 | } | ||
6551 | } | ||
6552 | |||
6553 | |||
6554 | /** | ||
6555 | * Function called by PEERSTORE when the store operation of | ||
6556 | * a backtalker's monotonic time is complete. | ||
6557 | * | ||
6558 | * @param cls the `struct Backtalker` | ||
6559 | * @param success #GNUNET_OK on success | ||
6560 | */ | ||
6561 | static void | ||
6562 | backtalker_monotime_store_cb (void *cls, int success) | ||
6563 | { | ||
6564 | struct Backtalker *b = cls; | ||
6565 | |||
6566 | if (GNUNET_OK != success) | ||
6567 | { | ||
6568 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
6569 | "Failed to store backtalker's monotonic time in PEERSTORE!\n"); | ||
6570 | } | ||
6571 | b->sc = NULL; | ||
6572 | b->task = GNUNET_SCHEDULER_add_at (b->timeout, &backtalker_timeout_cb, b); | ||
6573 | } | ||
6574 | |||
6575 | |||
6576 | /** | ||
6577 | * The backtalker @a b monotonic time changed. Update PEERSTORE. | ||
6578 | * | ||
6579 | * @param b a backtalker with updated monotonic time | ||
6580 | */ | ||
6581 | static void | ||
6582 | update_backtalker_monotime (struct Backtalker *b) | ||
6583 | { | ||
6584 | struct GNUNET_TIME_AbsoluteNBO mtbe; | ||
6585 | |||
6586 | if (NULL != b->sc) | ||
6587 | { | ||
6588 | GNUNET_PEERSTORE_store_cancel (b->sc); | ||
6589 | b->sc = NULL; | ||
6590 | } | ||
6591 | else | ||
6592 | { | ||
6593 | GNUNET_SCHEDULER_cancel (b->task); | ||
6594 | b->task = NULL; | ||
6595 | } | ||
6596 | mtbe = GNUNET_TIME_absolute_hton (b->monotonic_time); | ||
6597 | b->sc = | ||
6598 | GNUNET_PEERSTORE_store (peerstore, | ||
6599 | "transport", | ||
6600 | &b->pid, | ||
6601 | GNUNET_PEERSTORE_TRANSPORT_BACKCHANNEL_MONOTIME, | ||
6602 | &mtbe, | ||
6603 | sizeof (mtbe), | ||
6604 | GNUNET_TIME_UNIT_FOREVER_ABS, | ||
6605 | GNUNET_PEERSTORE_STOREOPTION_REPLACE, | ||
6606 | &backtalker_monotime_store_cb, | ||
6607 | b); | ||
6991 | } | 6608 | } |
6992 | 6609 | ||
6993 | 6610 | ||
@@ -7006,8 +6623,13 @@ handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb) | |||
7006 | uint16_t num_hops = ntohs (dvb->num_hops); | 6623 | uint16_t num_hops = ntohs (dvb->num_hops); |
7007 | const struct GNUNET_PeerIdentity *hops = | 6624 | const struct GNUNET_PeerIdentity *hops = |
7008 | (const struct GNUNET_PeerIdentity *) &dvb[1]; | 6625 | (const struct GNUNET_PeerIdentity *) &dvb[1]; |
7009 | const struct GNUNET_MessageHeader *inbox = | 6626 | const char *enc_payload = (const char *) &hops[num_hops]; |
7010 | (const struct GNUNET_MessageHeader *) &hops[num_hops]; | 6627 | uint16_t enc_payload_size = |
6628 | size - (num_hops * sizeof (struct GNUNET_PeerIdentity)); | ||
6629 | struct DVKeyState key; | ||
6630 | struct GNUNET_HashCode hmac; | ||
6631 | const char *hdr; | ||
6632 | size_t hdr_len; | ||
7011 | 6633 | ||
7012 | if (GNUNET_EXTRA_LOGGING > 0) | 6634 | if (GNUNET_EXTRA_LOGGING > 0) |
7013 | { | 6635 | { |
@@ -7050,12 +6672,12 @@ handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb) | |||
7050 | i, | 6672 | i, |
7051 | num_hops); | 6673 | num_hops); |
7052 | forward_dv_box (n, | 6674 | forward_dv_box (n, |
6675 | dvb, | ||
7053 | ntohs (dvb->total_hops) + 1, | 6676 | ntohs (dvb->total_hops) + 1, |
7054 | num_hops - i - 1, /* number of hops left */ | 6677 | num_hops - i - 1, /* number of hops left */ |
7055 | &dvb->origin, | ||
7056 | &hops[i + 1], /* remaining hops */ | 6678 | &hops[i + 1], /* remaining hops */ |
7057 | (const void *) &dvb[1], | 6679 | enc_payload, |
7058 | size); | 6680 | enc_payload_size); |
7059 | GNUNET_STATISTICS_update (GST_stats, | 6681 | GNUNET_STATISTICS_update (GST_stats, |
7060 | "# DV hops skipped routing boxes", | 6682 | "# DV hops skipped routing boxes", |
7061 | i, | 6683 | i, |
@@ -7076,18 +6698,140 @@ handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb) | |||
7076 | return; | 6698 | return; |
7077 | } | 6699 | } |
7078 | /* We are the target. Unbox and handle message. */ | 6700 | /* We are the target. Unbox and handle message. */ |
7079 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
7080 | "DVBox received for me from %s\n", | ||
7081 | GNUNET_i2s (&dvb->origin)); | ||
7082 | GNUNET_STATISTICS_update (GST_stats, | 6701 | GNUNET_STATISTICS_update (GST_stats, |
7083 | "# DV boxes opened (ultimate target)", | 6702 | "# DV boxes opened (ultimate target)", |
7084 | 1, | 6703 | 1, |
7085 | GNUNET_NO); | 6704 | GNUNET_NO); |
7086 | cmc->im.sender = dvb->origin; | ||
7087 | cmc->total_hops = ntohs (dvb->total_hops); | 6705 | cmc->total_hops = ntohs (dvb->total_hops); |
7088 | // FIXME: should *decrypt* inbox here; needs BackchannelEncapsulation! | 6706 | |
7089 | // FIXME: need to prevent box-in-a-box, so check inbox type! | 6707 | dh_key_derive_eph_pub (&dvb->ephemeral_key, &dvb->iv, &key); |
7090 | demultiplex_with_cmc (cmc, inbox); | 6708 | hdr = (const char *) &dvb[1]; |
6709 | hdr_len = ntohs (dvb->header.size) - sizeof (*dvb); | ||
6710 | dv_hmac (&key, &hmac, hdr, hdr_len); | ||
6711 | if (0 != GNUNET_memcmp (&hmac, &dvb->hmac)) | ||
6712 | { | ||
6713 | /* HMAC missmatch, disard! */ | ||
6714 | GNUNET_break_op (0); | ||
6715 | finish_cmc_handling (cmc); | ||
6716 | return; | ||
6717 | } | ||
6718 | /* begin actual decryption */ | ||
6719 | { | ||
6720 | struct Backtalker *b; | ||
6721 | struct GNUNET_TIME_Absolute monotime; | ||
6722 | struct TransportDVBoxPayloadP ppay; | ||
6723 | char body[hdr_len - sizeof (ppay)] GNUNET_ALIGN; | ||
6724 | const struct GNUNET_MessageHeader *mh = | ||
6725 | (const struct GNUNET_MessageHeader *) body; | ||
6726 | |||
6727 | GNUNET_assert (hdr_len >= | ||
6728 | sizeof (ppay) + sizeof (struct GNUNET_MessageHeader)); | ||
6729 | dv_decrypt (&key, &ppay, hdr, sizeof (ppay)); | ||
6730 | dv_decrypt (&key, &body, &hdr[sizeof (ppay)], hdr_len - sizeof (ppay)); | ||
6731 | dv_key_clean (&key); | ||
6732 | if (ntohs (mh->size) != sizeof (body)) | ||
6733 | { | ||
6734 | GNUNET_break_op (0); | ||
6735 | finish_cmc_handling (cmc); | ||
6736 | return; | ||
6737 | } | ||
6738 | /* need to prevent box-in-a-box (and DV_LEARN) so check inbox type! */ | ||
6739 | switch (ntohs (mh->type)) | ||
6740 | { | ||
6741 | case GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX: | ||
6742 | GNUNET_break_op (0); | ||
6743 | finish_cmc_handling (cmc); | ||
6744 | return; | ||
6745 | case GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN: | ||
6746 | GNUNET_break_op (0); | ||
6747 | finish_cmc_handling (cmc); | ||
6748 | return; | ||
6749 | default: | ||
6750 | /* permitted, continue */ | ||
6751 | break; | ||
6752 | } | ||
6753 | monotime = GNUNET_TIME_absolute_ntoh (ppay.monotonic_time); | ||
6754 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
6755 | "Decrypted backtalk from %s\n", | ||
6756 | GNUNET_i2s (&ppay.sender)); | ||
6757 | b = GNUNET_CONTAINER_multipeermap_get (backtalkers, &ppay.sender); | ||
6758 | if ((NULL != b) && (monotime.abs_value_us < b->monotonic_time.abs_value_us)) | ||
6759 | { | ||
6760 | GNUNET_STATISTICS_update ( | ||
6761 | GST_stats, | ||
6762 | "# Backchannel messages dropped: monotonic time not increasing", | ||
6763 | 1, | ||
6764 | GNUNET_NO); | ||
6765 | finish_cmc_handling (cmc); | ||
6766 | return; | ||
6767 | } | ||
6768 | if ((NULL == b) || | ||
6769 | (0 != GNUNET_memcmp (&b->last_ephemeral, &dvb->ephemeral_key))) | ||
6770 | { | ||
6771 | /* Check signature */ | ||
6772 | struct EphemeralConfirmationPS ec; | ||
6773 | |||
6774 | ec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL); | ||
6775 | ec.purpose.size = htonl (sizeof (ec)); | ||
6776 | ec.target = GST_my_identity; | ||
6777 | ec.ephemeral_key = dvb->ephemeral_key; | ||
6778 | if ( | ||
6779 | GNUNET_OK != | ||
6780 | GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL, | ||
6781 | &ec.purpose, | ||
6782 | &ppay.sender_sig, | ||
6783 | &ppay.sender.public_key)) | ||
6784 | { | ||
6785 | /* Signature invalid, disard! */ | ||
6786 | GNUNET_break_op (0); | ||
6787 | finish_cmc_handling (cmc); | ||
6788 | return; | ||
6789 | } | ||
6790 | } | ||
6791 | /* Update sender, we now know the real origin! */ | ||
6792 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
6793 | "DVBox received for me from %s via %s\n", | ||
6794 | GNUNET_i2s2 (&ppay.sender), | ||
6795 | GNUNET_i2s (&cmc->im.sender)); | ||
6796 | cmc->im.sender = ppay.sender; | ||
6797 | |||
6798 | if (NULL != b) | ||
6799 | { | ||
6800 | /* update key cache and mono time */ | ||
6801 | b->last_ephemeral = dvb->ephemeral_key; | ||
6802 | b->monotonic_time = monotime; | ||
6803 | update_backtalker_monotime (b); | ||
6804 | b->timeout = | ||
6805 | GNUNET_TIME_relative_to_absolute (BACKCHANNEL_INACTIVITY_TIMEOUT); | ||
6806 | |||
6807 | demultiplex_with_cmc (cmc, mh); | ||
6808 | return; | ||
6809 | } | ||
6810 | /* setup data structure to cache signature AND check | ||
6811 | monotonic time with PEERSTORE before forwarding backchannel payload */ | ||
6812 | b = GNUNET_malloc (sizeof (struct Backtalker) + sizeof (body)); | ||
6813 | b->pid = ppay.sender; | ||
6814 | b->body_size = sizeof (body); | ||
6815 | memcpy (&b[1], body, sizeof (body)); | ||
6816 | GNUNET_assert (GNUNET_YES == | ||
6817 | GNUNET_CONTAINER_multipeermap_put ( | ||
6818 | backtalkers, | ||
6819 | &b->pid, | ||
6820 | b, | ||
6821 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
6822 | b->monotonic_time = monotime; /* NOTE: to be checked still! */ | ||
6823 | b->cmc = cmc; | ||
6824 | b->timeout = | ||
6825 | GNUNET_TIME_relative_to_absolute (BACKCHANNEL_INACTIVITY_TIMEOUT); | ||
6826 | b->task = GNUNET_SCHEDULER_add_at (b->timeout, &backtalker_timeout_cb, b); | ||
6827 | b->get = | ||
6828 | GNUNET_PEERSTORE_iterate (peerstore, | ||
6829 | "transport", | ||
6830 | &b->pid, | ||
6831 | GNUNET_PEERSTORE_TRANSPORT_BACKCHANNEL_MONOTIME, | ||
6832 | &backtalker_monotime_cb, | ||
6833 | b); | ||
6834 | } /* end actual decryption */ | ||
7091 | } | 6835 | } |
7092 | 6836 | ||
7093 | 6837 | ||
@@ -7579,7 +7323,7 @@ set_pending_message_uuid (struct PendingMessage *pm) | |||
7579 | { | 7323 | { |
7580 | if (pm->msg_uuid_set) | 7324 | if (pm->msg_uuid_set) |
7581 | return; | 7325 | return; |
7582 | pm->msg_uuid.uuid = pm->target->message_uuid_ctr++; | 7326 | pm->msg_uuid.uuid = pm->vl->message_uuid_ctr++; |
7583 | pm->msg_uuid_set = GNUNET_YES; | 7327 | pm->msg_uuid_set = GNUNET_YES; |
7584 | } | 7328 | } |
7585 | 7329 | ||
@@ -7655,7 +7399,7 @@ fragment_message (struct Queue *queue, | |||
7655 | "Fragmenting message %llu <%llu> to %s for MTU %u\n", | 7399 | "Fragmenting message %llu <%llu> to %s for MTU %u\n", |
7656 | (unsigned long long) pm->msg_uuid.uuid, | 7400 | (unsigned long long) pm->msg_uuid.uuid, |
7657 | pm->logging_uuid, | 7401 | pm->logging_uuid, |
7658 | GNUNET_i2s (&pm->target->pid), | 7402 | GNUNET_i2s (&pm->vl->target), |
7659 | (unsigned int) mtu); | 7403 | (unsigned int) mtu); |
7660 | pa = prepare_pending_acknowledgement (queue, dvh, pm); | 7404 | pa = prepare_pending_acknowledgement (queue, dvh, pm); |
7661 | 7405 | ||
@@ -7702,7 +7446,7 @@ fragment_message (struct Queue *queue, | |||
7702 | GNUNET_malloc (sizeof (struct PendingMessage) + | 7446 | GNUNET_malloc (sizeof (struct PendingMessage) + |
7703 | sizeof (struct TransportFragmentBoxMessage) + fragsize); | 7447 | sizeof (struct TransportFragmentBoxMessage) + fragsize); |
7704 | frag->logging_uuid = logging_uuid_gen++; | 7448 | frag->logging_uuid = logging_uuid_gen++; |
7705 | frag->target = pm->target; | 7449 | frag->vl = pm->vl; |
7706 | frag->frag_parent = ff; | 7450 | frag->frag_parent = ff; |
7707 | frag->timeout = pm->timeout; | 7451 | frag->timeout = pm->timeout; |
7708 | frag->bytes_msg = sizeof (struct TransportFragmentBoxMessage) + fragsize; | 7452 | frag->bytes_msg = sizeof (struct TransportFragmentBoxMessage) + fragsize; |
@@ -7773,14 +7517,14 @@ reliability_box_message (struct Queue *queue, | |||
7773 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 7517 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
7774 | "Preparing reliability box for message <%llu> to %s on queue %s\n", | 7518 | "Preparing reliability box for message <%llu> to %s on queue %s\n", |
7775 | pm->logging_uuid, | 7519 | pm->logging_uuid, |
7776 | GNUNET_i2s (&pm->target->pid), | 7520 | GNUNET_i2s (&pm->vl->target), |
7777 | queue->address); | 7521 | queue->address); |
7778 | pa = prepare_pending_acknowledgement (queue, dvh, pm); | 7522 | pa = prepare_pending_acknowledgement (queue, dvh, pm); |
7779 | 7523 | ||
7780 | bpm = GNUNET_malloc (sizeof (struct PendingMessage) + sizeof (rbox) + | 7524 | bpm = GNUNET_malloc (sizeof (struct PendingMessage) + sizeof (rbox) + |
7781 | pm->bytes_msg); | 7525 | pm->bytes_msg); |
7782 | bpm->logging_uuid = logging_uuid_gen++; | 7526 | bpm->logging_uuid = logging_uuid_gen++; |
7783 | bpm->target = pm->target; | 7527 | bpm->vl = pm->vl; |
7784 | bpm->frag_parent = pm; | 7528 | bpm->frag_parent = pm; |
7785 | GNUNET_CONTAINER_MDLL_insert (frag, pm->head_frag, pm->tail_frag, bpm); | 7529 | GNUNET_CONTAINER_MDLL_insert (frag, pm->head_frag, pm->tail_frag, bpm); |
7786 | bpm->timeout = pm->timeout; | 7530 | bpm->timeout = pm->timeout; |
@@ -7812,7 +7556,7 @@ static void | |||
7812 | update_pm_next_attempt (struct PendingMessage *pm, | 7556 | update_pm_next_attempt (struct PendingMessage *pm, |
7813 | struct GNUNET_TIME_Absolute next_attempt) | 7557 | struct GNUNET_TIME_Absolute next_attempt) |
7814 | { | 7558 | { |
7815 | struct Neighbour *neighbour = pm->target; | 7559 | struct VirtualLink *vl = pm->vl; |
7816 | 7560 | ||
7817 | pm->next_attempt = next_attempt; | 7561 | pm->next_attempt = next_attempt; |
7818 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 7562 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
@@ -7825,17 +7569,17 @@ update_pm_next_attempt (struct PendingMessage *pm, | |||
7825 | struct PendingMessage *pos; | 7569 | struct PendingMessage *pos; |
7826 | 7570 | ||
7827 | /* re-insert sort in neighbour list */ | 7571 | /* re-insert sort in neighbour list */ |
7828 | GNUNET_CONTAINER_MDLL_remove (neighbour, | 7572 | GNUNET_CONTAINER_MDLL_remove (vl, |
7829 | neighbour->pending_msg_head, | 7573 | vl->pending_msg_head, |
7830 | neighbour->pending_msg_tail, | 7574 | vl->pending_msg_tail, |
7831 | pm); | 7575 | pm); |
7832 | pos = neighbour->pending_msg_tail; | 7576 | pos = vl->pending_msg_tail; |
7833 | while ((NULL != pos) && | 7577 | while ((NULL != pos) && |
7834 | (next_attempt.abs_value_us > pos->next_attempt.abs_value_us)) | 7578 | (next_attempt.abs_value_us > pos->next_attempt.abs_value_us)) |
7835 | pos = pos->prev_neighbour; | 7579 | pos = pos->prev_vl; |
7836 | GNUNET_CONTAINER_MDLL_insert_after (neighbour, | 7580 | GNUNET_CONTAINER_MDLL_insert_after (vl, |
7837 | neighbour->pending_msg_head, | 7581 | vl->pending_msg_head, |
7838 | neighbour->pending_msg_tail, | 7582 | vl->pending_msg_tail, |
7839 | pos, | 7583 | pos, |
7840 | pm); | 7584 | pm); |
7841 | } | 7585 | } |
@@ -7871,12 +7615,14 @@ static void | |||
7871 | transmit_on_queue (void *cls) | 7615 | transmit_on_queue (void *cls) |
7872 | { | 7616 | { |
7873 | struct Queue *queue = cls; | 7617 | struct Queue *queue = cls; |
7618 | |||
7619 | queue->transmit_task = NULL; | ||
7620 | #if FIXME - NEXT | ||
7874 | struct Neighbour *n = queue->neighbour; | 7621 | struct Neighbour *n = queue->neighbour; |
7875 | struct PendingMessage *pm; | 7622 | struct PendingMessage *pm; |
7876 | struct PendingMessage *s; | 7623 | struct PendingMessage *s; |
7877 | uint32_t overhead; | 7624 | uint32_t overhead; |
7878 | 7625 | ||
7879 | queue->transmit_task = NULL; | ||
7880 | if (NULL == (pm = n->pending_msg_head)) | 7626 | if (NULL == (pm = n->pending_msg_head)) |
7881 | { | 7627 | { |
7882 | /* no message pending, nothing to do here! */ | 7628 | /* no message pending, nothing to do here! */ |
@@ -8010,6 +7756,7 @@ transmit_on_queue (void *cls) | |||
8010 | 7756 | ||
8011 | /* finally, re-schedule queue transmission task itself */ | 7757 | /* finally, re-schedule queue transmission task itself */ |
8012 | schedule_transmit_on_queue (queue, GNUNET_NO); | 7758 | schedule_transmit_on_queue (queue, GNUNET_NO); |
7759 | #endif | ||
8013 | } | 7760 | } |
8014 | 7761 | ||
8015 | 7762 | ||
@@ -8138,19 +7885,21 @@ handle_send_message_ack (void *cls, | |||
8138 | 7885 | ||
8139 | if (NULL != (pm = qe->pm)) | 7886 | if (NULL != (pm = qe->pm)) |
8140 | { | 7887 | { |
8141 | struct Neighbour *n; | 7888 | struct VirtualLink *vl; |
8142 | 7889 | ||
8143 | GNUNET_assert (qe == pm->qe); | 7890 | GNUNET_assert (qe == pm->qe); |
8144 | pm->qe = NULL; | 7891 | pm->qe = NULL; |
8145 | /* If waiting for this communicator may have blocked transmission | 7892 | /* If waiting for this communicator may have blocked transmission |
8146 | of pm on other queues for this neighbour, force schedule | 7893 | of pm on other queues for this neighbour, force schedule |
8147 | transmit on queue for queues of the neighbour */ | 7894 | transmit on queue for queues of the neighbour */ |
8148 | n = pm->target; | 7895 | vl = pm->vl; |
8149 | if (n->pending_msg_head == pm) | 7896 | if (vl->pending_msg_head == pm) |
8150 | { | 7897 | { |
7898 | #if FIXME - NEXT | ||
8151 | for (struct Queue *queue = n->queue_head; NULL != queue; | 7899 | for (struct Queue *queue = n->queue_head; NULL != queue; |
8152 | queue = queue->next_neighbour) | 7900 | queue = queue->next_neighbour) |
8153 | schedule_transmit_on_queue (queue, GNUNET_NO); | 7901 | schedule_transmit_on_queue (queue, GNUNET_NO); |
7902 | #endif | ||
8154 | } | 7903 | } |
8155 | if (GNUNET_OK != ntohl (sma->status)) | 7904 | if (GNUNET_OK != ntohl (sma->status)) |
8156 | { | 7905 | { |
@@ -8651,8 +8400,6 @@ handle_add_queue_message (void *cls, | |||
8651 | if (NULL == neighbour) | 8400 | if (NULL == neighbour) |
8652 | { | 8401 | { |
8653 | neighbour = GNUNET_new (struct Neighbour); | 8402 | neighbour = GNUNET_new (struct Neighbour); |
8654 | neighbour->message_uuid_ctr = | ||
8655 | GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX); | ||
8656 | neighbour->pid = aqm->receiver; | 8403 | neighbour->pid = aqm->receiver; |
8657 | GNUNET_assert (GNUNET_OK == | 8404 | GNUNET_assert (GNUNET_OK == |
8658 | GNUNET_CONTAINER_multipeermap_put ( | 8405 | GNUNET_CONTAINER_multipeermap_put ( |
@@ -9081,28 +8828,6 @@ free_dv_routes_cb (void *cls, | |||
9081 | 8828 | ||
9082 | 8829 | ||
9083 | /** | 8830 | /** |
9084 | * Free ephemeral entry. | ||
9085 | * | ||
9086 | * @param cls NULL | ||
9087 | * @param pid unused | ||
9088 | * @param value a `struct EphemeralCacheEntry` | ||
9089 | * @return #GNUNET_OK (always) | ||
9090 | */ | ||
9091 | static int | ||
9092 | free_ephemeral_cb (void *cls, | ||
9093 | const struct GNUNET_PeerIdentity *pid, | ||
9094 | void *value) | ||
9095 | { | ||
9096 | struct EphemeralCacheEntry *ece = value; | ||
9097 | |||
9098 | (void) cls; | ||
9099 | (void) pid; | ||
9100 | free_ephemeral (ece); | ||
9101 | return GNUNET_OK; | ||
9102 | } | ||
9103 | |||
9104 | |||
9105 | /** | ||
9106 | * Free validation state. | 8831 | * Free validation state. |
9107 | * | 8832 | * |
9108 | * @param cls NULL | 8833 | * @param cls NULL |
@@ -9180,11 +8905,6 @@ do_shutdown (void *cls) | |||
9180 | struct LearnLaunchEntry *lle; | 8905 | struct LearnLaunchEntry *lle; |
9181 | (void) cls; | 8906 | (void) cls; |
9182 | 8907 | ||
9183 | if (NULL != ephemeral_task) | ||
9184 | { | ||
9185 | GNUNET_SCHEDULER_cancel (ephemeral_task); | ||
9186 | ephemeral_task = NULL; | ||
9187 | } | ||
9188 | GNUNET_CONTAINER_multipeermap_iterate (neighbours, &free_neighbour_cb, NULL); | 8908 | GNUNET_CONTAINER_multipeermap_iterate (neighbours, &free_neighbour_cb, NULL); |
9189 | if (NULL != peerstore) | 8909 | if (NULL != peerstore) |
9190 | { | 8910 | { |
@@ -9239,13 +8959,6 @@ do_shutdown (void *cls) | |||
9239 | GNUNET_CONTAINER_multipeermap_iterate (dv_routes, &free_dv_routes_cb, NULL); | 8959 | GNUNET_CONTAINER_multipeermap_iterate (dv_routes, &free_dv_routes_cb, NULL); |
9240 | GNUNET_CONTAINER_multipeermap_destroy (dv_routes); | 8960 | GNUNET_CONTAINER_multipeermap_destroy (dv_routes); |
9241 | dv_routes = NULL; | 8961 | dv_routes = NULL; |
9242 | GNUNET_CONTAINER_multipeermap_iterate (ephemeral_map, | ||
9243 | &free_ephemeral_cb, | ||
9244 | NULL); | ||
9245 | GNUNET_CONTAINER_multipeermap_destroy (ephemeral_map); | ||
9246 | ephemeral_map = NULL; | ||
9247 | GNUNET_CONTAINER_heap_destroy (ephemeral_heap); | ||
9248 | ephemeral_heap = NULL; | ||
9249 | } | 8962 | } |
9250 | 8963 | ||
9251 | 8964 | ||
@@ -9272,9 +8985,6 @@ run (void *cls, | |||
9272 | neighbours = GNUNET_CONTAINER_multipeermap_create (1024, GNUNET_YES); | 8985 | neighbours = GNUNET_CONTAINER_multipeermap_create (1024, GNUNET_YES); |
9273 | links = GNUNET_CONTAINER_multipeermap_create (512, GNUNET_YES); | 8986 | links = GNUNET_CONTAINER_multipeermap_create (512, GNUNET_YES); |
9274 | dv_routes = GNUNET_CONTAINER_multipeermap_create (1024, GNUNET_YES); | 8987 | dv_routes = GNUNET_CONTAINER_multipeermap_create (1024, GNUNET_YES); |
9275 | ephemeral_map = GNUNET_CONTAINER_multipeermap_create (32, GNUNET_YES); | ||
9276 | ephemeral_heap = | ||
9277 | GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); | ||
9278 | dvlearn_map = GNUNET_CONTAINER_multishortmap_create (2 * MAX_DV_LEARN_PENDING, | 8988 | dvlearn_map = GNUNET_CONTAINER_multishortmap_create (2 * MAX_DV_LEARN_PENDING, |
9279 | GNUNET_YES); | 8989 | GNUNET_YES); |
9280 | validation_map = GNUNET_CONTAINER_multipeermap_create (1024, GNUNET_YES); | 8990 | validation_map = GNUNET_CONTAINER_multipeermap_create (1024, GNUNET_YES); |