aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorng0 <ng0@n0.is>2019-04-23 14:50:21 +0000
committerng0 <ng0@n0.is>2019-04-23 14:50:21 +0000
commit510d62445a15811a9b9de98cffa085f3da592025 (patch)
treefedcd77483cc14a686add6bceb6ef97b682c454b
parent050f5f3f5d783bd080d838d04eb8837672627afb (diff)
parentc929c783cc70935dcebe9fd61634573a47de5a01 (diff)
downloadgnunet-510d62445a15811a9b9de98cffa085f3da592025.tar.gz
gnunet-510d62445a15811a9b9de98cffa085f3da592025.zip
Merge branch 'master' of gnunet.org:gnunet
-rw-r--r--src/include/gnunet_protocols.h7
-rw-r--r--src/transport/gnunet-service-tng.c1565
2 files changed, 1063 insertions, 509 deletions
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index e402460c0..27a7034b0 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -2121,7 +2121,7 @@ extern "C" {
2121 2121
2122/** M<->S<->C: PSYC message which contains a header and one or more message 2122/** M<->S<->C: PSYC message which contains a header and one or more message
2123 * parts. */ 2123 * parts. */
2124#define GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_HEADER \ 2124#define GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_HEADER \
2125 692 // FIXME: start using this where appropriate 2125 692 // FIXME: start using this where appropriate
2126 2126
2127/** Message part: method */ 2127/** Message part: method */
@@ -3108,11 +3108,6 @@ extern "C" {
3108#define GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT 1214 3108#define GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT 1214
3109 3109
3110/** 3110/**
3111 * Acknowledgement generated for a fragment.
3112 */
3113#define GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT_ACK 1215
3114
3115/**
3116 * Wrapper around non-fragmented CORE message used to measure RTT 3111 * Wrapper around non-fragmented CORE message used to measure RTT
3117 * and ensure reliability. 3112 * and ensure reliability.
3118 */ 3113 */
diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c
index 7683ed016..e128a4abf 100644
--- a/src/transport/gnunet-service-tng.c
+++ b/src/transport/gnunet-service-tng.c
@@ -24,9 +24,13 @@
24 * 24 *
25 * TODO: 25 * TODO:
26 * Implement next: 26 * Implement next:
27 * - track RTT, distance, loss, etc. => requires extra data structures! 27 * - FIXME: looping over neighbours when calling forward_dv_learn()!
28 * - FIXME: transmit_on_queue: track dvh we may be using and pass it to
29 * fragment_message() and reliability_box_message() if applicable
28 * - proper use/initialization of timestamps in messages exchanged 30 * - proper use/initialization of timestamps in messages exchanged
29 * during DV learning 31 * during DV learning
32 * - persistence of monotonic time from DVInit to prevent
33 * replay attacks using DVInit messages
30 * - persistence of monotonic time obtained from other peers 34 * - persistence of monotonic time obtained from other peers
31 * in PEERSTORE (by message type) -- done for backchannel, needed elsewhere? 35 * in PEERSTORE (by message type) -- done for backchannel, needed elsewhere?
32 * - change transport-core API to provide proper flow control in both 36 * - change transport-core API to provide proper flow control in both
@@ -38,12 +42,11 @@
38 * 42 *
39 * Later: 43 * Later:
40 * - review retransmission logic, right now there is no smartness there! 44 * - review retransmission logic, right now there is no smartness there!
41 * => congestion control, flow control, etc (requires RTT, loss, etc.) 45 * => congestion control, flow control, etc
42 * 46 *
43 * Optimizations: 47 * Optimizations:
44 * - use shorthashmap on msg_uuid's when matching reliability/fragment ACKs 48 * - AcknowledgementUUIDPs are overkill with 256 bits (128 would do)
45 * against our pending message queue (requires additional per neighbour 49 * => Need 128 bit hash map though!
46 * hash map to be maintained, avoids possible linear scan on pending msgs)
47 * - queue_send_msg and route_message both by API design have to make copies 50 * - queue_send_msg and route_message both by API design have to make copies
48 * of the payload, and route_message on top of that requires a malloc/free. 51 * of the payload, and route_message on top of that requires a malloc/free.
49 * Change design to approximate "zero" copy better... 52 * Change design to approximate "zero" copy better...
@@ -95,6 +98,11 @@
95#include "gnunet_signatures.h" 98#include "gnunet_signatures.h"
96#include "transport.h" 99#include "transport.h"
97 100
101/**
102 * Maximum number of messages we acknowledge together in one
103 * cummulative ACK. Larger values may save a bit of bandwidth.
104 */
105#define MAX_CUMMULATIVE_ACKS 64
98 106
99/** 107/**
100 * What is the size we assume for a read operation in the 108 * What is the size we assume for a read operation in the
@@ -103,6 +111,12 @@
103#define IN_PACKET_SIZE_WITHOUT_MTU 128 111#define IN_PACKET_SIZE_WITHOUT_MTU 128
104 112
105/** 113/**
114 * Number of slots we keep of historic data for computation of
115 * goodput / message loss ratio.
116 */
117#define GOODPUT_AGING_SLOTS 4
118
119/**
106 * Minimum number of hops we should forward DV learn messages 120 * Minimum number of hops we should forward DV learn messages
107 * even if they are NOT useful for us in hope of looping 121 * even if they are NOT useful for us in hope of looping
108 * back to the initiator? 122 * back to the initiator?
@@ -190,6 +204,14 @@
190 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_DAYS, 1) 204 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_DAYS, 1)
191 205
192/** 206/**
207 * How long until we forget about historic accumulators and thus
208 * reset the ACK counter? Should exceed the maximum time an
209 * active connection experiences without an ACK.
210 */
211#define ACK_CUMMULATOR_TIMEOUT \
212 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
213
214/**
193 * What is the non-randomized base frequency at which we 215 * What is the non-randomized base frequency at which we
194 * would initiate DV learn messages? 216 * would initiate DV learn messages?
195 */ 217 */
@@ -248,6 +270,55 @@
248GNUNET_NETWORK_STRUCT_BEGIN 270GNUNET_NETWORK_STRUCT_BEGIN
249 271
250/** 272/**
273 * Unique identifier we attach to a message.
274 */
275struct MessageUUIDP
276{
277 /**
278 * Unique value, generated by incrementing the
279 * `message_uuid_ctr` of `struct Neighbour`.
280 */
281 uint64_t uuid GNUNET_PACKED;
282};
283
284
285/**
286 * Unique identifier to map an acknowledgement to a transmission.
287 */
288struct AcknowledgementUUIDP
289{
290 /**
291 * The UUID value. Not actually a hash, but a random value.
292 */
293 struct GNUNET_ShortHashCode value;
294};
295
296
297/**
298 * Unique identifier we attach to a message.
299 */
300struct FragmentUUIDP
301{
302 /**
303 * Unique value identifying a fragment, in NBO.
304 */
305 uint32_t uuid GNUNET_PACKED;
306};
307
308
309/**
310 * Type of a nonce used for challenges.
311 */
312struct ChallengeNonceP
313{
314 /**
315 * The value of the nonce. Note that this is NOT a hash.
316 */
317 struct GNUNET_ShortHashCode value;
318};
319
320
321/**
251 * Outer layer of an encapsulated backchannel message. 322 * Outer layer of an encapsulated backchannel message.
252 */ 323 */
253struct TransportBackchannelEncapsulationMessage 324struct TransportBackchannelEncapsulationMessage
@@ -335,7 +406,7 @@ struct EphemeralConfirmationPS
335 * Plaintext of the variable-size payload that is encrypted 406 * Plaintext of the variable-size payload that is encrypted
336 * within a `struct TransportBackchannelEncapsulationMessage` 407 * within a `struct TransportBackchannelEncapsulationMessage`
337 */ 408 */
338struct TransportBackchannelRequestPayload 409struct TransportBackchannelRequestPayloadP
339{ 410{
340 411
341 /** 412 /**
@@ -389,7 +460,7 @@ struct TransportBackchannelRequestPayload
389 * Outer layer of an encapsulated unfragmented application message sent 460 * Outer layer of an encapsulated unfragmented application message sent
390 * over an unreliable channel. 461 * over an unreliable channel.
391 */ 462 */
392struct TransportReliabilityBox 463struct TransportReliabilityBoxMessage
393{ 464{
394 /** 465 /**
395 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX 466 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX
@@ -409,7 +480,27 @@ struct TransportReliabilityBox
409 * messages sent over possibly unreliable channels. Should 480 * messages sent over possibly unreliable channels. Should
410 * be a random. 481 * be a random.
411 */ 482 */
412 struct GNUNET_ShortHashCode msg_uuid; 483 struct AcknowledgementUUIDP ack_uuid;
484};
485
486
487/**
488 * Acknowledgement payload.
489 */
490struct TransportCummulativeAckPayloadP
491{
492 /**
493 * How long was the ACK delayed for generating cummulative ACKs?
494 * Used to calculate the correct network RTT by taking the receipt
495 * time of the ack minus the transmission time of the sender minus
496 * this value.
497 */
498 struct GNUNET_TIME_RelativeNBO ack_delay;
499
500 /**
501 * UUID of a message being acknowledged.
502 */
503 struct AcknowledgementUUIDP ack_uuid;
413}; 504};
414 505
415 506
@@ -428,19 +519,12 @@ struct TransportReliabilityAckMessage
428 struct GNUNET_MessageHeader header; 519 struct GNUNET_MessageHeader header;
429 520
430 /** 521 /**
431 * Reserved. Zero. 522 * Counter of ACKs transmitted by the sender to us. Incremented
523 * by one for each ACK, used to detect how many ACKs were lost.
432 */ 524 */
433 uint32_t reserved GNUNET_PACKED; 525 uint32_t ack_counter GNUNET_PACKED;
434 526
435 /** 527 /* followed by any number of `struct TransportCummulativeAckPayloadP`
436 * How long was the ACK delayed relative to the average time of
437 * receipt of the messages being acknowledged? Used to calculate
438 * the average RTT by taking the receipt time of the ack minus the
439 * average transmission time of the sender minus this value.
440 */
441 struct GNUNET_TIME_RelativeNBO avg_ack_delay;
442
443 /* followed by any number of `struct GNUNET_ShortHashCode`
444 messages providing ACKs */ 528 messages providing ACKs */
445}; 529};
446 530
@@ -448,7 +532,7 @@ struct TransportReliabilityAckMessage
448/** 532/**
449 * Outer layer of an encapsulated fragmented application message. 533 * Outer layer of an encapsulated fragmented application message.
450 */ 534 */
451struct TransportFragmentBox 535struct TransportFragmentBoxMessage
452{ 536{
453 /** 537 /**
454 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT 538 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT
@@ -458,18 +542,17 @@ struct TransportFragmentBox
458 /** 542 /**
459 * Unique ID of this fragment (and fragment transmission!). Will 543 * Unique ID of this fragment (and fragment transmission!). Will
460 * change even if a fragement is retransmitted to make each 544 * change even if a fragement is retransmitted to make each
461 * transmission attempt unique! Should be incremented by one for 545 * transmission attempt unique! If a client receives a duplicate
462 * each fragment transmission. If a client receives a duplicate 546 * fragment (same @e frag_off for same @a msg_uuid, it must send
463 * fragment (same @e frag_off), it must send 547 * #GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK immediately.
464 * #GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT_ACK immediately.
465 */ 548 */
466 uint32_t frag_uuid GNUNET_PACKED; 549 struct AcknowledgementUUIDP ack_uuid;
467 550
468 /** 551 /**
469 * Original message ID for of the message that all the1 552 * Original message ID for of the message that all the fragments
470 * fragments belong to. Must be the same for all fragments. 553 * belong to. Must be the same for all fragments.
471 */ 554 */
472 struct GNUNET_ShortHashCode msg_uuid; 555 struct MessageUUIDP msg_uuid;
473 556
474 /** 557 /**
475 * Offset of this fragment in the overall message. 558 * Offset of this fragment in the overall message.
@@ -484,54 +567,6 @@ struct TransportFragmentBox
484 567
485 568
486/** 569/**
487 * Outer layer of an fragmented application message sent over a queue
488 * with finite MTU. When a #GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT is
489 * received, the receiver has two RTTs or 64 further fragments with
490 * the same basic message time to send an acknowledgement, possibly
491 * acknowledging up to 65 fragments in one ACK. ACKs must also be
492 * sent immediately once all fragments were sent.
493 */
494struct TransportFragmentAckMessage
495{
496 /**
497 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT_ACK
498 */
499 struct GNUNET_MessageHeader header;
500
501 /**
502 * Unique ID of the lowest fragment UUID being acknowledged.
503 */
504 uint32_t frag_uuid GNUNET_PACKED;
505
506 /**
507 * Bitfield of up to 64 additional fragments following the
508 * @e msg_uuid being acknowledged by this message.
509 */
510 uint64_t extra_acks GNUNET_PACKED;
511
512 /**
513 * Original message ID for of the message that all the
514 * fragments belong to.
515 */
516 struct GNUNET_ShortHashCode msg_uuid;
517
518 /**
519 * How long was the ACK delayed relative to the average time of
520 * receipt of the fragments being acknowledged? Used to calculate
521 * the average RTT by taking the receipt time of the ack minus the
522 * average transmission time of the sender minus this value.
523 */
524 struct GNUNET_TIME_RelativeNBO avg_ack_delay;
525
526 /**
527 * How long until the receiver will stop trying reassembly
528 * of this message?
529 */
530 struct GNUNET_TIME_RelativeNBO reassembly_timeout;
531};
532
533
534/**
535 * Content signed by the initator during DV learning. 570 * Content signed by the initator during DV learning.
536 * 571 *
537 * The signature is required to prevent DDoS attacks. A peer sending out this 572 * The signature is required to prevent DDoS attacks. A peer sending out this
@@ -572,7 +607,7 @@ struct DvInitPS
572 /** 607 /**
573 * Challenge value used by the initiator to re-identify the path. 608 * Challenge value used by the initiator to re-identify the path.
574 */ 609 */
575 struct GNUNET_ShortHashCode challenge; 610 struct ChallengeNonceP challenge;
576}; 611};
577 612
578 613
@@ -612,13 +647,13 @@ struct DvHopPS
612 /** 647 /**
613 * Challenge value used by the initiator to re-identify the path. 648 * Challenge value used by the initiator to re-identify the path.
614 */ 649 */
615 struct GNUNET_ShortHashCode challenge; 650 struct ChallengeNonceP challenge;
616}; 651};
617 652
618 653
619/** 654/**
620 * An entry describing a peer on a path in a 655 * An entry describing a peer on a path in a
621 * `struct TransportDVLearn` message. 656 * `struct TransportDVLearnMessage` message.
622 */ 657 */
623struct DVPathEntryP 658struct DVPathEntryP
624{ 659{
@@ -648,7 +683,7 @@ struct DVPathEntryP
648 * zero, peers that can forward to the initator should always try to 683 * zero, peers that can forward to the initator should always try to
649 * forward to the initiator. 684 * forward to the initiator.
650 */ 685 */
651struct TransportDVLearn 686struct TransportDVLearnMessage
652{ 687{
653 /** 688 /**
654 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN 689 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN
@@ -692,7 +727,7 @@ struct TransportDVLearn
692 /** 727 /**
693 * Challenge value used by the initiator to re-identify the path. 728 * Challenge value used by the initiator to re-identify the path.
694 */ 729 */
695 struct GNUNET_ShortHashCode challenge; 730 struct ChallengeNonceP challenge;
696 731
697 /* Followed by @e num_hops `struct DVPathEntryP` values, 732 /* Followed by @e num_hops `struct DVPathEntryP` values,
698 excluding the initiator of the DV trace; the last entry is the 733 excluding the initiator of the DV trace; the last entry is the
@@ -715,7 +750,7 @@ struct TransportDVLearn
715 * 750 *
716 * If a peer finds itself still on the list, it must drop the message. 751 * If a peer finds itself still on the list, it must drop the message.
717 */ 752 */
718struct TransportDVBox 753struct TransportDVBoxMessage
719{ 754{
720 /** 755 /**
721 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX 756 * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX
@@ -753,7 +788,7 @@ struct TransportDVBox
753 * Message send to another peer to validate that it can indeed 788 * Message send to another peer to validate that it can indeed
754 * receive messages at a particular address. 789 * receive messages at a particular address.
755 */ 790 */
756struct TransportValidationChallenge 791struct TransportValidationChallengeMessage
757{ 792{
758 793
759 /** 794 /**
@@ -769,7 +804,7 @@ struct TransportValidationChallenge
769 /** 804 /**
770 * Challenge to be signed by the receiving peer. 805 * Challenge to be signed by the receiving peer.
771 */ 806 */
772 struct GNUNET_ShortHashCode challenge; 807 struct ChallengeNonceP challenge;
773 808
774 /** 809 /**
775 * Timestamp of the sender, to be copied into the reply 810 * Timestamp of the sender, to be copied into the reply
@@ -800,7 +835,7 @@ struct TransportValidationPS
800 /** 835 /**
801 * Challenge signed by the receiving peer. 836 * Challenge signed by the receiving peer.
802 */ 837 */
803 struct GNUNET_ShortHashCode challenge; 838 struct ChallengeNonceP challenge;
804}; 839};
805 840
806 841
@@ -808,7 +843,7 @@ struct TransportValidationPS
808 * Message send to a peer to respond to a 843 * Message send to a peer to respond to a
809 * #GNUNET_MESSAGE_TYPE_ADDRESS_VALIDATION_CHALLENGE 844 * #GNUNET_MESSAGE_TYPE_ADDRESS_VALIDATION_CHALLENGE
810 */ 845 */
811struct TransportValidationResponse 846struct TransportValidationResponseMessage
812{ 847{
813 848
814 /** 849 /**
@@ -830,7 +865,7 @@ struct TransportValidationResponse
830 /** 865 /**
831 * The challenge that was signed by the receiving peer. 866 * The challenge that was signed by the receiving peer.
832 */ 867 */
833 struct GNUNET_ShortHashCode challenge; 868 struct ChallengeNonceP challenge;
834 869
835 /** 870 /**
836 * Original timestamp of the sender (was @code{sender_time}), 871 * Original timestamp of the sender (was @code{sender_time}),
@@ -900,7 +935,7 @@ struct LearnLaunchEntry
900 /** 935 /**
901 * Challenge that uniquely identifies this activity. 936 * Challenge that uniquely identifies this activity.
902 */ 937 */
903 struct GNUNET_ShortHashCode challenge; 938 struct ChallengeNonceP challenge;
904 939
905 /** 940 /**
906 * When did we transmit the DV learn message (used to calculate RTT) and 941 * When did we transmit the DV learn message (used to calculate RTT) and
@@ -956,17 +991,58 @@ struct EphemeralCacheEntry
956 991
957 992
958/** 993/**
994 * Information we keep per #GOODPUT_AGING_SLOTS about historic
995 * (or current) transmission performance.
996 */
997struct TransmissionHistoryEntry
998{
999 /**
1000 * Number of bytes actually sent in the interval.
1001 */
1002 uint64_t bytes_sent;
1003
1004 /**
1005 * Number of bytes received and acknowledged by the other peer in
1006 * the interval.
1007 */
1008 uint64_t bytes_received;
1009};
1010
1011
1012/**
1013 * Performance data for a transmission possibility.
1014 */
1015struct PerformanceData
1016{
1017 /**
1018 * Weighted average for the RTT.
1019 */
1020 struct GNUNET_TIME_Relative aged_rtt;
1021
1022 /**
1023 * Historic performance data, using a ring buffer of#GOODPUT_AGING_SLOTS
1024 * entries.
1025 */
1026 struct TransmissionHistoryEntry the[GOODPUT_AGING_SLOTS];
1027
1028 /**
1029 * What was the last age when we wrote to @e the? Used to clear
1030 * old entries when the age advances.
1031 */
1032 unsigned int last_age;
1033};
1034
1035
1036/**
959 * Client connected to the transport service. 1037 * Client connected to the transport service.
960 */ 1038 */
961struct TransportClient; 1039struct TransportClient;
962 1040
963
964/** 1041/**
965 * A neighbour that at least one communicator is connected to. 1042 * A neighbour that at least one communicator is connected to.
966 */ 1043 */
967struct Neighbour; 1044struct Neighbour;
968 1045
969
970/** 1046/**
971 * Entry in our #dv_routes table, representing a (set of) distance 1047 * Entry in our #dv_routes table, representing a (set of) distance
972 * vector routes to a particular peer. 1048 * vector routes to a particular peer.
@@ -974,6 +1050,118 @@ struct Neighbour;
974struct DistanceVector; 1050struct DistanceVector;
975 1051
976/** 1052/**
1053 * A queue is a message queue provided by a communicator
1054 * via which we can reach a particular neighbour.
1055 */
1056struct Queue;
1057
1058/**
1059 * Message awaiting transmission. See detailed comments below.
1060 */
1061struct PendingMessage;
1062
1063/**
1064 * One possible hop towards a DV target.
1065 */
1066struct DistanceVectorHop;
1067
1068
1069/**
1070 * Data structure kept when we are waiting for an acknowledgement.
1071 */
1072struct PendingAcknowledgement
1073{
1074
1075 /**
1076 * If @e pm is non-NULL, this is the DLL in which this acknowledgement
1077 * is kept in relation to its pending message.
1078 */
1079 struct PendingAcknowledgement *next_pm;
1080
1081 /**
1082 * If @e pm is non-NULL, this is the DLL in which this acknowledgement
1083 * is kept in relation to its pending message.
1084 */
1085 struct PendingAcknowledgement *prev_pm;
1086
1087 /**
1088 * If @e queue is non-NULL, this is the DLL in which this acknowledgement
1089 * is kept in relation to the queue that was used to transmit the
1090 * @a pm.
1091 */
1092 struct PendingAcknowledgement *next_queue;
1093
1094 /**
1095 * If @e queue is non-NULL, this is the DLL in which this acknowledgement
1096 * is kept in relation to the queue that was used to transmit the
1097 * @a pm.
1098 */
1099 struct PendingAcknowledgement *prev_queue;
1100
1101 /**
1102 * If @e dvh is non-NULL, this is the DLL in which this acknowledgement
1103 * is kept in relation to the DVH that was used to transmit the
1104 * @a pm.
1105 */
1106 struct PendingAcknowledgement *next_dvh;
1107
1108 /**
1109 * If @e dvh is non-NULL, this is the DLL in which this acknowledgement
1110 * is kept in relation to the DVH that was used to transmit the
1111 * @a pm.
1112 */
1113 struct PendingAcknowledgement *prev_dvh;
1114
1115 /**
1116 * Pointers for the DLL of all pending acknowledgements.
1117 * This list is sorted by @e transmission time. If the list gets too
1118 * long, the oldest entries are discarded.
1119 */
1120 struct PendingAcknowledgement *next_pa;
1121
1122 /**
1123 * Pointers for the DLL of all pending acknowledgements.
1124 * This list is sorted by @e transmission time. If the list gets too
1125 * long, the oldest entries are discarded.
1126 */
1127 struct PendingAcknowledgement *prev_pa;
1128
1129 /**
1130 * Unique identifier for this transmission operation.
1131 */
1132 struct AcknowledgementUUIDP ack_uuid;
1133
1134 /**
1135 * Message that was transmitted, may be NULL if the message was ACKed
1136 * via another channel.
1137 */
1138 struct PendingMessage *pm;
1139
1140 /**
1141 * Distance vector path chosen for this transmission, NULL if transmission
1142 * was to a direct neighbour OR if the path was forgotten in the meantime.
1143 */
1144 struct DistanceVectorHop *dvh;
1145
1146 /**
1147 * Queue used for transmission, NULL if the queue has been destroyed
1148 * (which may happen before we get an acknowledgement).
1149 */
1150 struct Queue *queue;
1151
1152 /**
1153 * Time of the transmission, for RTT calculation.
1154 */
1155 struct GNUNET_TIME_Absolute transmission_time;
1156
1157 /**
1158 * Number of bytes of the original message (to calculate bandwidth).
1159 */
1160 uint16_t message_size;
1161};
1162
1163
1164/**
977 * One possible hop towards a DV target. 1165 * One possible hop towards a DV target.
978 */ 1166 */
979struct DistanceVectorHop 1167struct DistanceVectorHop
@@ -1000,6 +1188,16 @@ struct DistanceVectorHop
1000 struct DistanceVectorHop *prev_neighbour; 1188 struct DistanceVectorHop *prev_neighbour;
1001 1189
1002 /** 1190 /**
1191 * Head of DLL of PAs that used our @a path.
1192 */
1193 struct PendingAcknowledgement *pa_head;
1194
1195 /**
1196 * Tail of DLL of PAs that used our @a path.
1197 */
1198 struct PendingAcknowledgement *pa_tail;
1199
1200 /**
1003 * What would be the next hop to @e target? 1201 * What would be the next hop to @e target?
1004 */ 1202 */
1005 struct Neighbour *next_hop; 1203 struct Neighbour *next_hop;
@@ -1032,6 +1230,11 @@ struct DistanceVectorHop
1032 struct GNUNET_TIME_Absolute path_valid_until; 1230 struct GNUNET_TIME_Absolute path_valid_until;
1033 1231
1034 /** 1232 /**
1233 * Performance data for this transmission possibility.
1234 */
1235 struct PerformanceData pd;
1236
1237 /**
1035 * Number of hops in total to the `target` (excluding @e next_hop and `target` 1238 * Number of hops in total to the `target` (excluding @e next_hop and `target`
1036 * itself). Thus 0 still means a distance of 2 hops (to @e next_hop and then 1239 * itself). Thus 0 still means a distance of 2 hops (to @e next_hop and then
1037 * to `target`). 1240 * to `target`).
@@ -1097,17 +1300,6 @@ struct DistanceVector
1097 1300
1098 1301
1099/** 1302/**
1100 * A queue is a message queue provided by a communicator
1101 * via which we can reach a particular neighbour.
1102 */
1103struct Queue;
1104
1105/**
1106 * Message awaiting transmission. See detailed comments below.
1107 */
1108struct PendingMessage;
1109
1110/**
1111 * Entry identifying transmission in one of our `struct 1303 * Entry identifying transmission in one of our `struct
1112 * Queue` which still awaits an ACK. This is used to 1304 * Queue` which still awaits an ACK. This is used to
1113 * ensure we do not overwhelm a communicator and limit the number of 1305 * ensure we do not overwhelm a communicator and limit the number of
@@ -1173,6 +1365,16 @@ struct Queue
1173 struct Queue *next_client; 1365 struct Queue *next_client;
1174 1366
1175 /** 1367 /**
1368 * Head of DLL of PAs that used this queue.
1369 */
1370 struct PendingAcknowledgement *pa_head;
1371
1372 /**
1373 * Tail of DLL of PAs that used this queue.
1374 */
1375 struct PendingAcknowledgement *pa_tail;
1376
1377 /**
1176 * Head of DLL of unacked transmission requests. 1378 * Head of DLL of unacked transmission requests.
1177 */ 1379 */
1178 struct QueueEntry *queue_head; 1380 struct QueueEntry *queue_head;
@@ -1210,11 +1412,6 @@ struct Queue
1210 struct GNUNET_SCHEDULER_Task *visibility_task; 1412 struct GNUNET_SCHEDULER_Task *visibility_task;
1211 1413
1212 /** 1414 /**
1213 * Our current RTT estimate for this queue.
1214 */
1215 struct GNUNET_TIME_Relative rtt;
1216
1217 /**
1218 * How long do *we* consider this @e address to be valid? In the past or 1415 * How long do *we* consider this @e address to be valid? In the past or
1219 * zero if we have not yet validated it. Can be updated based on 1416 * zero if we have not yet validated it. Can be updated based on
1220 * challenge-response validations (via address validation logic), or when we 1417 * challenge-response validations (via address validation logic), or when we
@@ -1224,7 +1421,13 @@ struct Queue
1224 struct GNUNET_TIME_Absolute validated_until; 1421 struct GNUNET_TIME_Absolute validated_until;
1225 1422
1226 /** 1423 /**
1227 * Message ID generator for transmissions on this queue. 1424 * Performance data for this queue.
1425 */
1426 struct PerformanceData pd;
1427
1428 /**
1429 * Message ID generator for transmissions on this queue to the
1430 * communicator.
1228 */ 1431 */
1229 uint64_t mid_gen; 1432 uint64_t mid_gen;
1230 1433
@@ -1282,10 +1485,10 @@ struct ReassemblyContext
1282{ 1485{
1283 1486
1284 /** 1487 /**
1285 * Original message ID for of the message that all the 1488 * Original message ID for of the message that all the fragments
1286 * fragments belong to. 1489 * belong to.
1287 */ 1490 */
1288 struct GNUNET_ShortHashCode msg_uuid; 1491 struct MessageUUIDP msg_uuid;
1289 1492
1290 /** 1493 /**
1291 * Which neighbour is this context for? 1494 * Which neighbour is this context for?
@@ -1319,36 +1522,12 @@ struct ReassemblyContext
1319 struct GNUNET_TIME_Absolute reassembly_timeout; 1522 struct GNUNET_TIME_Absolute reassembly_timeout;
1320 1523
1321 /** 1524 /**
1322 * Average delay of all acks in @e extra_acks and @e frag_uuid.
1323 * Should be reset to zero when @e num_acks is set to 0.
1324 */
1325 struct GNUNET_TIME_Relative avg_ack_delay;
1326
1327 /**
1328 * Time we received the last fragment. @e avg_ack_delay must be 1525 * Time we received the last fragment. @e avg_ack_delay must be
1329 * incremented by now - @e last_frag multiplied by @e num_acks. 1526 * incremented by now - @e last_frag multiplied by @e num_acks.
1330 */ 1527 */
1331 struct GNUNET_TIME_Absolute last_frag; 1528 struct GNUNET_TIME_Absolute last_frag;
1332 1529
1333 /** 1530 /**
1334 * Bitfield of up to 64 additional fragments following @e frag_uuid
1335 * to be acknowledged in the next cummulative ACK.
1336 */
1337 uint64_t extra_acks;
1338
1339 /**
1340 * Unique ID of the lowest fragment UUID to be acknowledged in the
1341 * next cummulative ACK. Only valid if @e num_acks > 0.
1342 */
1343 uint32_t frag_uuid;
1344
1345 /**
1346 * Number of ACKs we have accumulated so far. Reset to 0
1347 * whenever we send a #GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT_ACK.
1348 */
1349 unsigned int num_acks;
1350
1351 /**
1352 * How big is the message we are reassembling in total? 1531 * How big is the message we are reassembling in total?
1353 */ 1532 */
1354 uint16_t msg_size; 1533 uint16_t msg_size;
@@ -1382,7 +1561,7 @@ struct Neighbour
1382 * reassembly. May be NULL if we currently have no fragments from 1561 * reassembly. May be NULL if we currently have no fragments from
1383 * this @e pid (lazy initialization). 1562 * this @e pid (lazy initialization).
1384 */ 1563 */
1385 struct GNUNET_CONTAINER_MultiShortmap *reassembly_map; 1564 struct GNUNET_CONTAINER_MultiHashMap32 *reassembly_map;
1386 1565
1387 /** 1566 /**
1388 * Heap with `struct ReassemblyContext` structs for fragments under 1567 * Heap with `struct ReassemblyContext` structs for fragments under
@@ -1588,6 +1767,16 @@ struct PendingMessage
1588 struct PendingMessage *prev_frag; 1767 struct PendingMessage *prev_frag;
1589 1768
1590 /** 1769 /**
1770 * Head of DLL of PAs for this pending message.
1771 */
1772 struct PendingAcknowledgement *pa_head;
1773
1774 /**
1775 * Tail of DLL of PAs for this pending message.
1776 */
1777 struct PendingAcknowledgement *pa_tail;
1778
1779 /**
1591 * This message, reliability boxed. Only possibly available if @e pmt is 1780 * This message, reliability boxed. Only possibly available if @e pmt is
1592 * #PMT_CORE. 1781 * #PMT_CORE.
1593 */ 1782 */
@@ -1642,12 +1831,7 @@ struct PendingMessage
1642 * UUID to use for this message (used for reassembly of fragments, only 1831 * UUID to use for this message (used for reassembly of fragments, only
1643 * initialized if @e msg_uuid_set is #GNUNET_YES). 1832 * initialized if @e msg_uuid_set is #GNUNET_YES).
1644 */ 1833 */
1645 struct GNUNET_ShortHashCode msg_uuid; 1834 struct MessageUUIDP msg_uuid;
1646
1647 /**
1648 * Counter incremented per generated fragment.
1649 */
1650 uint32_t frag_uuidgen;
1651 1835
1652 /** 1836 /**
1653 * Type of the pending message. 1837 * Type of the pending message.
@@ -1674,6 +1858,66 @@ struct PendingMessage
1674 1858
1675 1859
1676/** 1860/**
1861 * Acknowledgement payload.
1862 */
1863struct TransportCummulativeAckPayload
1864{
1865 /**
1866 * When did we receive the message we are ACKing? Used to calculate
1867 * the delay we introduced by cummulating ACKs.
1868 */
1869 struct GNUNET_TIME_Absolute receive_time;
1870
1871 /**
1872 * UUID of a message being acknowledged.
1873 */
1874 struct AcknowledgementUUIDP ack_uuid;
1875};
1876
1877
1878/**
1879 * Data structure in which we track acknowledgements still to
1880 * be sent to the
1881 */
1882struct AcknowledgementCummulator
1883{
1884 /**
1885 * Target peer for which we are accumulating ACKs here.
1886 */
1887 struct GNUNET_PeerIdentity target;
1888
1889 /**
1890 * ACK data being accumulated. Only @e num_acks slots are valid.
1891 */
1892 struct TransportCummulativeAckPayload ack_uuids[MAX_CUMMULATIVE_ACKS];
1893
1894 /**
1895 * Task scheduled either to transmit the cummulative ACK message,
1896 * or to clean up this data structure after extended periods of
1897 * inactivity (if @e num_acks is zero).
1898 */
1899 struct GNUNET_SCHEDULER_Task *task;
1900
1901 /**
1902 * When is @e task run (only used if @e num_acks is non-zero)?
1903 */
1904 struct GNUNET_TIME_Absolute min_transmission_time;
1905
1906 /**
1907 * Counter to produce the `ack_counter` in the `struct
1908 * TransportReliabilityAckMessage`. Allows the receiver to detect
1909 * lost ACK messages. Incremented by @e num_acks upon transmission.
1910 */
1911 uint32_t ack_counter;
1912
1913 /**
1914 * Number of entries used in @e ack_uuids. Reset to 0 upon transmission.
1915 */
1916 unsigned int num_acks;
1917};
1918
1919
1920/**
1677 * One of the addresses of this peer. 1921 * One of the addresses of this peer.
1678 */ 1922 */
1679struct AddressListEntry 1923struct AddressListEntry
@@ -1941,7 +2185,7 @@ struct ValidationState
1941 * (We must not rotate more often as otherwise we may discard valid answers 2185 * (We must not rotate more often as otherwise we may discard valid answers
1942 * due to packet losses, latency and reorderings on the network). 2186 * due to packet losses, latency and reorderings on the network).
1943 */ 2187 */
1944 struct GNUNET_ShortHashCode challenge; 2188 struct ChallengeNonceP challenge;
1945 2189
1946 /** 2190 /**
1947 * Claimed address of the peer. 2191 * Claimed address of the peer.
@@ -2071,6 +2315,18 @@ static struct GNUNET_CONTAINER_MultiPeerMap *neighbours;
2071static struct GNUNET_CONTAINER_MultiPeerMap *backtalkers; 2315static struct GNUNET_CONTAINER_MultiPeerMap *backtalkers;
2072 2316
2073/** 2317/**
2318 * Map from PIDs to `struct AcknowledgementCummulator`s.
2319 * Here we track the cummulative ACKs for transmission.
2320 */
2321static struct GNUNET_CONTAINER_MultiPeerMap *ack_cummulators;
2322
2323/**
2324 * Map of pending acknowledgements, mapping `struct AcknowledgementUUID` to
2325 * a `struct PendingAcknowledgement`.
2326 */
2327static struct GNUNET_CONTAINER_MultiShortmap *pending_acks;
2328
2329/**
2074 * Map from PIDs to `struct DistanceVector` entries describing 2330 * Map from PIDs to `struct DistanceVector` entries describing
2075 * known paths to the peer. 2331 * known paths to the peer.
2076 */ 2332 */
@@ -2139,6 +2395,81 @@ static struct GNUNET_SCHEDULER_Task *dvlearn_task;
2139 */ 2395 */
2140static struct GNUNET_SCHEDULER_Task *validation_task; 2396static struct GNUNET_SCHEDULER_Task *validation_task;
2141 2397
2398/**
2399 * The most recent PA we have created, head of DLL.
2400 * The length of the DLL is kept in #pa_count.
2401 */
2402static struct PendingAcknowledgement *pa_head;
2403
2404/**
2405 * The oldest PA we have created, tail of DLL.
2406 * The length of the DLL is kept in #pa_count.
2407 */
2408static struct PendingAcknowledgement *pa_tail;
2409
2410/**
2411 * Number of entries in the #pa_head/#pa_tail DLL. Used to
2412 * limit the size of the data structure.
2413 */
2414static unsigned int pa_count;
2415
2416
2417/**
2418 * Get an offset into the transmission history buffer for `struct
2419 * PerformanceData`. Note that the caller must perform the required
2420 * modulo #GOODPUT_AGING_SLOTS operation before indexing into the
2421 * array!
2422 *
2423 * An 'age' lasts 15 minute slots.
2424 *
2425 * @return current age of the world
2426 */
2427static unsigned int
2428get_age ()
2429{
2430 struct GNUNET_TIME_Absolute now;
2431
2432 now = GNUNET_TIME_absolute_get ();
2433 return now.abs_value_us / GNUNET_TIME_UNIT_MINUTES.rel_value_us / 15;
2434}
2435
2436
2437/**
2438 * Release @a pa data structure.
2439 *
2440 * @param pa data structure to release
2441 */
2442static void
2443free_pending_acknowledgement (struct PendingAcknowledgement *pa)
2444{
2445 struct Queue *q = pa->queue;
2446 struct PendingMessage *pm = pa->pm;
2447 struct DistanceVectorHop *dvh = pa->dvh;
2448
2449 GNUNET_CONTAINER_MDLL_remove (pa, pa_head, pa_tail, pa);
2450 pa_count--;
2451 if (NULL != q)
2452 {
2453 GNUNET_CONTAINER_MDLL_remove (queue, q->pa_head, q->pa_tail, pa);
2454 pa->queue = NULL;
2455 }
2456 if (NULL != pm)
2457 {
2458 GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
2459 pa->pm = NULL;
2460 }
2461 if (NULL != dvh)
2462 {
2463 GNUNET_CONTAINER_MDLL_remove (dvh, dvh->pa_head, dvh->pa_tail, pa);
2464 pa->queue = NULL;
2465 }
2466 GNUNET_assert (GNUNET_YES ==
2467 GNUNET_CONTAINER_multishortmap_remove (pending_acks,
2468 &pa->ack_uuid.value,
2469 pa));
2470 GNUNET_free (pa);
2471}
2472
2142 2473
2143/** 2474/**
2144 * Free cached ephemeral key. 2475 * Free cached ephemeral key.
@@ -2235,7 +2566,13 @@ free_distance_vector_hop (struct DistanceVectorHop *dvh)
2235{ 2566{
2236 struct Neighbour *n = dvh->next_hop; 2567 struct Neighbour *n = dvh->next_hop;
2237 struct DistanceVector *dv = dvh->dv; 2568 struct DistanceVector *dv = dvh->dv;
2569 struct PendingAcknowledgement *pa;
2238 2570
2571 while (NULL != (pa = dvh->pa_head))
2572 {
2573 GNUNET_CONTAINER_MDLL_remove (dvh, dvh->pa_head, dvh->pa_tail, pa);
2574 pa->dvh = NULL;
2575 }
2239 GNUNET_CONTAINER_MDLL_remove (neighbour, n->dv_head, n->dv_tail, dvh); 2576 GNUNET_CONTAINER_MDLL_remove (neighbour, n->dv_head, n->dv_tail, dvh);
2240 GNUNET_CONTAINER_MDLL_remove (dv, dv->dv_head, dv->dv_tail, dvh); 2577 GNUNET_CONTAINER_MDLL_remove (dv, dv->dv_head, dv->dv_tail, dvh);
2241 GNUNET_free (dvh); 2578 GNUNET_free (dvh);
@@ -2377,9 +2714,9 @@ free_reassembly_context (struct ReassemblyContext *rc)
2377 2714
2378 GNUNET_assert (rc == GNUNET_CONTAINER_heap_remove_node (rc->hn)); 2715 GNUNET_assert (rc == GNUNET_CONTAINER_heap_remove_node (rc->hn));
2379 GNUNET_assert (GNUNET_OK == 2716 GNUNET_assert (GNUNET_OK ==
2380 GNUNET_CONTAINER_multishortmap_remove (n->reassembly_map, 2717 GNUNET_CONTAINER_multihashmap32_remove (n->reassembly_map,
2381 &rc->msg_uuid, 2718 rc->msg_uuid.uuid,
2382 rc)); 2719 rc));
2383 GNUNET_free (rc); 2720 GNUNET_free (rc);
2384} 2721}
2385 2722
@@ -2423,9 +2760,7 @@ reassembly_cleanup_task (void *cls)
2423 * @return #GNUNET_OK (continue iteration) 2760 * @return #GNUNET_OK (continue iteration)
2424 */ 2761 */
2425static int 2762static int
2426free_reassembly_cb (void *cls, 2763free_reassembly_cb (void *cls, uint32_t key, void *value)
2427 const struct GNUNET_ShortHashCode *key,
2428 void *value)
2429{ 2764{
2430 struct ReassemblyContext *rc = value; 2765 struct ReassemblyContext *rc = value;
2431 2766
@@ -2455,10 +2790,10 @@ free_neighbour (struct Neighbour *neighbour)
2455 GNUNET_SCHEDULER_cancel (neighbour->timeout_task); 2790 GNUNET_SCHEDULER_cancel (neighbour->timeout_task);
2456 if (NULL != neighbour->reassembly_map) 2791 if (NULL != neighbour->reassembly_map)
2457 { 2792 {
2458 GNUNET_CONTAINER_multishortmap_iterate (neighbour->reassembly_map, 2793 GNUNET_CONTAINER_multihashmap32_iterate (neighbour->reassembly_map,
2459 &free_reassembly_cb, 2794 &free_reassembly_cb,
2460 NULL); 2795 NULL);
2461 GNUNET_CONTAINER_multishortmap_destroy (neighbour->reassembly_map); 2796 GNUNET_CONTAINER_multihashmap32_destroy (neighbour->reassembly_map);
2462 neighbour->reassembly_map = NULL; 2797 neighbour->reassembly_map = NULL;
2463 GNUNET_CONTAINER_heap_destroy (neighbour->reassembly_heap); 2798 GNUNET_CONTAINER_heap_destroy (neighbour->reassembly_heap);
2464 neighbour->reassembly_heap = NULL; 2799 neighbour->reassembly_heap = NULL;
@@ -2641,6 +2976,7 @@ free_queue (struct Queue *queue)
2641 .rtt = GNUNET_TIME_UNIT_FOREVER_REL}; 2976 .rtt = GNUNET_TIME_UNIT_FOREVER_REL};
2642 struct QueueEntry *qe; 2977 struct QueueEntry *qe;
2643 int maxxed; 2978 int maxxed;
2979 struct PendingAcknowledgement *pa;
2644 2980
2645 if (NULL != queue->transmit_task) 2981 if (NULL != queue->transmit_task)
2646 { 2982 {
@@ -2652,6 +2988,12 @@ free_queue (struct Queue *queue)
2652 GNUNET_SCHEDULER_cancel (queue->visibility_task); 2988 GNUNET_SCHEDULER_cancel (queue->visibility_task);
2653 queue->visibility_task = NULL; 2989 queue->visibility_task = NULL;
2654 } 2990 }
2991 while (NULL != (pa = queue->pa_head))
2992 {
2993 GNUNET_CONTAINER_MDLL_remove (queue, queue->pa_head, queue->pa_tail, pa);
2994 pa->queue = NULL;
2995 }
2996
2655 GNUNET_CONTAINER_MDLL_remove (neighbour, 2997 GNUNET_CONTAINER_MDLL_remove (neighbour,
2656 neighbour->queue_head, 2998 neighbour->queue_head,
2657 neighbour->queue_tail, 2999 neighbour->queue_tail,
@@ -2914,6 +3256,9 @@ check_client_send (void *cls, const struct OutboundMessage *obm)
2914 3256
2915/** 3257/**
2916 * Free fragment tree below @e root, excluding @e root itself. 3258 * Free fragment tree below @e root, excluding @e root itself.
3259 * FIXME: this does NOT seem to have the intended semantics
3260 * based on how this is called. Seems we generally DO expect
3261 * @a root to be free'ed itself as well!
2917 * 3262 *
2918 * @param root root of the tree to free 3263 * @param root root of the tree to free
2919 */ 3264 */
@@ -2924,7 +3269,14 @@ free_fragment_tree (struct PendingMessage *root)
2924 3269
2925 while (NULL != (frag = root->head_frag)) 3270 while (NULL != (frag = root->head_frag))
2926 { 3271 {
3272 struct PendingAcknowledgement *pa;
3273
2927 free_fragment_tree (frag); 3274 free_fragment_tree (frag);
3275 while (NULL != (pa = frag->pa_head))
3276 {
3277 GNUNET_CONTAINER_MDLL_remove (pm, frag->pa_head, frag->pa_tail, pa);
3278 pa->pm = NULL;
3279 }
2928 GNUNET_CONTAINER_MDLL_remove (frag, root->head_frag, root->tail_frag, frag); 3280 GNUNET_CONTAINER_MDLL_remove (frag, root->head_frag, root->tail_frag, frag);
2929 GNUNET_free (frag); 3281 GNUNET_free (frag);
2930 } 3282 }
@@ -2943,6 +3295,7 @@ free_pending_message (struct PendingMessage *pm)
2943{ 3295{
2944 struct TransportClient *tc = pm->client; 3296 struct TransportClient *tc = pm->client;
2945 struct Neighbour *target = pm->target; 3297 struct Neighbour *target = pm->target;
3298 struct PendingAcknowledgement *pa;
2946 3299
2947 if (NULL != tc) 3300 if (NULL != tc)
2948 { 3301 {
@@ -2955,6 +3308,12 @@ free_pending_message (struct PendingMessage *pm)
2955 target->pending_msg_head, 3308 target->pending_msg_head,
2956 target->pending_msg_tail, 3309 target->pending_msg_tail,
2957 pm); 3310 pm);
3311 while (NULL != (pa = pm->pa_head))
3312 {
3313 GNUNET_CONTAINER_MDLL_remove (pm, pm->pa_head, pm->pa_tail, pa);
3314 pa->pm = NULL;
3315 }
3316
2958 free_fragment_tree (pm); 3317 free_fragment_tree (pm);
2959 if (NULL != pm->qe) 3318 if (NULL != pm->qe)
2960 { 3319 {
@@ -3194,7 +3553,7 @@ check_communicator_backchannel (
3194 msize = ntohs (cb->header.size) - sizeof (*cb); 3553 msize = ntohs (cb->header.size) - sizeof (*cb);
3195 if (UINT16_MAX - msize > 3554 if (UINT16_MAX - msize >
3196 sizeof (struct TransportBackchannelEncapsulationMessage) + 3555 sizeof (struct TransportBackchannelEncapsulationMessage) +
3197 sizeof (struct TransportBackchannelRequestPayload)) 3556 sizeof (struct TransportBackchannelRequestPayloadP))
3198 { 3557 {
3199 GNUNET_break (0); 3558 GNUNET_break (0);
3200 return GNUNET_SYSERR; 3559 return GNUNET_SYSERR;
@@ -3481,10 +3840,10 @@ forward_via_dvh (const struct DistanceVectorHop *dvh,
3481 enum RouteMessageOptions options) 3840 enum RouteMessageOptions options)
3482{ 3841{
3483 uint16_t mlen = ntohs (payload->size); 3842 uint16_t mlen = ntohs (payload->size);
3484 char boxram[sizeof (struct TransportDVBox) + 3843 char boxram[sizeof (struct TransportDVBoxMessage) +
3485 (dvh->distance + 1) * sizeof (struct GNUNET_PeerIdentity) + 3844 (dvh->distance + 1) * sizeof (struct GNUNET_PeerIdentity) +
3486 mlen] GNUNET_ALIGN; 3845 mlen] GNUNET_ALIGN;
3487 struct TransportDVBox *box = (struct TransportDVBox *) boxram; 3846 struct TransportDVBoxMessage *box = (struct TransportDVBoxMessage *) boxram;
3488 struct GNUNET_PeerIdentity *path = (struct GNUNET_PeerIdentity *) &box[1]; 3847 struct GNUNET_PeerIdentity *path = (struct GNUNET_PeerIdentity *) &box[1];
3489 3848
3490 box->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX); 3849 box->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX);
@@ -3659,6 +4018,14 @@ struct BackchannelKeyState
3659}; 4018};
3660 4019
3661 4020
4021/**
4022 * Given the key material in @a km and the initialization vector
4023 * @a iv, setup the key material for the backchannel in @a key.
4024 *
4025 * @param km raw master secret
4026 * @param iv initialization vector
4027 * @param key[out] symmetric cipher and HMAC state to generate
4028 */
3662static void 4029static void
3663bc_setup_key_state_from_km (const struct GNUNET_HashCode *km, 4030bc_setup_key_state_from_km (const struct GNUNET_HashCode *km,
3664 const struct GNUNET_ShortHashCode *iv, 4031 const struct GNUNET_ShortHashCode *iv,
@@ -3822,14 +4189,14 @@ handle_communicator_backchannel (
3822 struct GNUNET_CRYPTO_EcdhePrivateKey private_key; 4189 struct GNUNET_CRYPTO_EcdhePrivateKey private_key;
3823 struct GNUNET_TIME_Absolute ephemeral_validity; 4190 struct GNUNET_TIME_Absolute ephemeral_validity;
3824 struct TransportBackchannelEncapsulationMessage *enc; 4191 struct TransportBackchannelEncapsulationMessage *enc;
3825 struct TransportBackchannelRequestPayload ppay; 4192 struct TransportBackchannelRequestPayloadP ppay;
3826 struct BackchannelKeyState key; 4193 struct BackchannelKeyState key;
3827 char *mpos; 4194 char *mpos;
3828 uint16_t msize; 4195 uint16_t msize;
3829 4196
3830 /* encapsulate and encrypt message */ 4197 /* encapsulate and encrypt message */
3831 msize = ntohs (cb->header.size) - sizeof (*cb) + 4198 msize = ntohs (cb->header.size) - sizeof (*cb) +
3832 sizeof (struct TransportBackchannelRequestPayload); 4199 sizeof (struct TransportBackchannelRequestPayloadP);
3833 enc = GNUNET_malloc (sizeof (*enc) + msize); 4200 enc = GNUNET_malloc (sizeof (*enc) + msize);
3834 enc->header.type = 4201 enc->header.type =
3835 htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION); 4202 htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION);
@@ -4140,7 +4507,7 @@ handle_raw_message (void *cls, const struct GNUNET_MessageHeader *mh)
4140 * @return #GNUNET_YES if message is well-formed 4507 * @return #GNUNET_YES if message is well-formed
4141 */ 4508 */
4142static int 4509static int
4143check_fragment_box (void *cls, const struct TransportFragmentBox *fb) 4510check_fragment_box (void *cls, const struct TransportFragmentBoxMessage *fb)
4144{ 4511{
4145 uint16_t size = ntohs (fb->header.size); 4512 uint16_t size = ntohs (fb->header.size);
4146 uint16_t bsize = size - sizeof (*fb); 4513 uint16_t bsize = size - sizeof (*fb);
@@ -4165,32 +4532,150 @@ check_fragment_box (void *cls, const struct TransportFragmentBox *fb)
4165 4532
4166 4533
4167/** 4534/**
4168 * Generate a fragment acknowledgement for an @a rc. 4535 * Clean up an idle cummulative acknowledgement data structure.
4169 * 4536 *
4170 * @param rc context to generate ACK for, @a rc ACK state is reset 4537 * @param cls a `struct AcknowledgementCummulator *`
4171 */ 4538 */
4172static void 4539static void
4173send_fragment_ack (struct ReassemblyContext *rc) 4540destroy_ack_cummulator (void *cls)
4174{ 4541{
4175 struct TransportFragmentAckMessage *ack; 4542 struct AcknowledgementCummulator *ac = cls;
4176 4543
4177 ack = GNUNET_new (struct TransportFragmentAckMessage); 4544 ac->task = NULL;
4178 ack->header.size = htons (sizeof (struct TransportFragmentAckMessage)); 4545 GNUNET_assert (0 == ac->num_acks);
4179 ack->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT_ACK); 4546 GNUNET_assert (
4180 ack->frag_uuid = htonl (rc->frag_uuid); 4547 GNUNET_YES ==
4181 ack->extra_acks = GNUNET_htonll (rc->extra_acks); 4548 GNUNET_CONTAINER_multipeermap_remove (ack_cummulators, &ac->target, ac));
4182 ack->msg_uuid = rc->msg_uuid; 4549 GNUNET_free (ac);
4183 ack->avg_ack_delay = GNUNET_TIME_relative_hton (rc->avg_ack_delay); 4550}
4184 if (0 == rc->msg_missing) 4551
4185 ack->reassembly_timeout = GNUNET_TIME_relative_hton ( 4552
4186 GNUNET_TIME_UNIT_FOREVER_REL); /* signal completion */ 4553/**
4554 * Do the transmission of a cummulative acknowledgement now.
4555 *
4556 * @param cls a `struct AcknowledgementCummulator *`
4557 */
4558static void
4559transmit_cummulative_ack_cb (void *cls)
4560{
4561 struct AcknowledgementCummulator *ac = cls;
4562 struct TransportReliabilityAckMessage *ack;
4563 struct TransportCummulativeAckPayloadP *ap;
4564
4565 ac->task = NULL;
4566 GNUNET_assert (0 < ac->ack_counter);
4567 ack = GNUNET_malloc (sizeof (*ack) +
4568 ac->ack_counter *
4569 sizeof (struct TransportCummulativeAckPayloadP));
4570 ack->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK);
4571 ack->header.size =
4572 htons (sizeof (*ack) +
4573 ac->ack_counter * sizeof (struct TransportCummulativeAckPayloadP));
4574 ack->ack_counter = htonl (ac->ack_counter++);
4575 ap = (struct TransportCummulativeAckPayloadP *) &ack[1];
4576 for (unsigned int i = 0; i < ac->ack_counter; i++)
4577 {
4578 ap[i].ack_uuid = ac->ack_uuids[i].ack_uuid;
4579 ap[i].ack_delay = GNUNET_TIME_relative_hton (
4580 GNUNET_TIME_absolute_get_duration (ac->ack_uuids[i].receive_time));
4581 }
4582 route_message (&ac->target, &ack->header, RMO_DV_ALLOWED);
4583 ac->num_acks = 0;
4584 ac->task = GNUNET_SCHEDULER_add_delayed (ACK_CUMMULATOR_TIMEOUT,
4585 &destroy_ack_cummulator,
4586 ac);
4587}
4588
4589
4590/**
4591 * Transmit an acknowledgement for @a ack_uuid to @a pid delaying
4592 * transmission by at most @a ack_delay.
4593 *
4594 * @param pid target peer
4595 * @param ack_uuid UUID to ack
4596 * @param max_delay how long can the ACK wait
4597 */
4598static void
4599cummulative_ack (const struct GNUNET_PeerIdentity *pid,
4600 const struct AcknowledgementUUIDP *ack_uuid,
4601 struct GNUNET_TIME_Absolute max_delay)
4602{
4603 struct AcknowledgementCummulator *ac;
4604
4605 ac = GNUNET_CONTAINER_multipeermap_get (ack_cummulators, pid);
4606 if (NULL == ac)
4607 {
4608 ac = GNUNET_new (struct AcknowledgementCummulator);
4609 ac->target = *pid;
4610 ac->min_transmission_time = max_delay;
4611 GNUNET_assert (GNUNET_YES ==
4612 GNUNET_CONTAINER_multipeermap_put (
4613 ack_cummulators,
4614 &ac->target,
4615 ac,
4616 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
4617 }
4187 else 4618 else
4188 ack->reassembly_timeout = GNUNET_TIME_relative_hton ( 4619 {
4189 GNUNET_TIME_absolute_get_remaining (rc->reassembly_timeout)); 4620 if (MAX_CUMMULATIVE_ACKS == ac->num_acks)
4190 route_message (&rc->neighbour->pid, &ack->header, RMO_DV_ALLOWED); 4621 {
4191 rc->avg_ack_delay = GNUNET_TIME_UNIT_ZERO; 4622 /* must run immediately, ack buffer full! */
4192 rc->num_acks = 0; 4623 GNUNET_SCHEDULER_cancel (ac->task);
4193 rc->extra_acks = 0LLU; 4624 transmit_cummulative_ack_cb (ac);
4625 }
4626 GNUNET_SCHEDULER_cancel (ac->task);
4627 ac->min_transmission_time =
4628 GNUNET_TIME_absolute_min (ac->min_transmission_time, max_delay);
4629 }
4630 GNUNET_assert (ac->num_acks < MAX_CUMMULATIVE_ACKS);
4631 ac->ack_uuids[ac->num_acks].receive_time = GNUNET_TIME_absolute_get ();
4632 ac->ack_uuids[ac->num_acks].ack_uuid = *ack_uuid;
4633 ac->num_acks++;
4634 ac->task = GNUNET_SCHEDULER_add_at (ac->min_transmission_time,
4635 &transmit_cummulative_ack_cb,
4636 ac);
4637}
4638
4639
4640/**
4641 * Closure for #find_by_message_uuid.
4642 */
4643struct FindByMessageUuidContext
4644{
4645 /**
4646 * UUID to look for.
4647 */
4648 struct MessageUUIDP message_uuid;
4649
4650 /**
4651 * Set to the reassembly context if found.
4652 */
4653 struct ReassemblyContext *rc;
4654};
4655
4656
4657/**
4658 * Iterator called to find a reassembly context by the message UUID in the
4659 * multihashmap32.
4660 *
4661 * @param cls a `struct FindByMessageUuidContext`
4662 * @param key a key (unused)
4663 * @param value a `struct ReassemblyContext`
4664 * @return #GNUNET_YES if not found, #GNUNET_NO if found
4665 */
4666static int
4667find_by_message_uuid (void *cls, uint32_t key, void *value)
4668{
4669 struct FindByMessageUuidContext *fc = cls;
4670 struct ReassemblyContext *rc = value;
4671
4672 (void) key;
4673 if (0 == GNUNET_memcmp (&fc->message_uuid, &rc->msg_uuid))
4674 {
4675 fc->rc = rc;
4676 return GNUNET_NO;
4677 }
4678 return GNUNET_YES;
4194} 4679}
4195 4680
4196 4681
@@ -4202,7 +4687,7 @@ send_fragment_ack (struct ReassemblyContext *rc)
4202 * @param fb the message that was received 4687 * @param fb the message that was received
4203 */ 4688 */
4204static void 4689static void
4205handle_fragment_box (void *cls, const struct TransportFragmentBox *fb) 4690handle_fragment_box (void *cls, const struct TransportFragmentBoxMessage *fb)
4206{ 4691{
4207 struct CommunicatorMessageContext *cmc = cls; 4692 struct CommunicatorMessageContext *cmc = cls;
4208 struct Neighbour *n; 4693 struct Neighbour *n;
@@ -4211,10 +4696,9 @@ handle_fragment_box (void *cls, const struct TransportFragmentBox *fb)
4211 uint16_t msize; 4696 uint16_t msize;
4212 uint16_t fsize; 4697 uint16_t fsize;
4213 uint16_t frag_off; 4698 uint16_t frag_off;
4214 uint32_t frag_uuid;
4215 char *target; 4699 char *target;
4216 struct GNUNET_TIME_Relative cdelay; 4700 struct GNUNET_TIME_Relative cdelay;
4217 int ack_now; 4701 struct FindByMessageUuidContext fc;
4218 4702
4219 n = GNUNET_CONTAINER_multipeermap_get (neighbours, &cmc->im.sender); 4703 n = GNUNET_CONTAINER_multipeermap_get (neighbours, &cmc->im.sender);
4220 if (NULL == n) 4704 if (NULL == n)
@@ -4228,7 +4712,7 @@ handle_fragment_box (void *cls, const struct TransportFragmentBox *fb)
4228 } 4712 }
4229 if (NULL == n->reassembly_map) 4713 if (NULL == n->reassembly_map)
4230 { 4714 {
4231 n->reassembly_map = GNUNET_CONTAINER_multishortmap_create (8, GNUNET_YES); 4715 n->reassembly_map = GNUNET_CONTAINER_multihashmap32_create (8);
4232 n->reassembly_heap = 4716 n->reassembly_heap =
4233 GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); 4717 GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
4234 n->reassembly_timeout_task = 4718 n->reassembly_timeout_task =
@@ -4237,8 +4721,13 @@ handle_fragment_box (void *cls, const struct TransportFragmentBox *fb)
4237 n); 4721 n);
4238 } 4722 }
4239 msize = ntohs (fb->msg_size); 4723 msize = ntohs (fb->msg_size);
4240 rc = GNUNET_CONTAINER_multishortmap_get (n->reassembly_map, &fb->msg_uuid); 4724 fc.message_uuid = fb->msg_uuid;
4241 if (NULL == rc) 4725 fc.rc = NULL;
4726 GNUNET_CONTAINER_multihashmap32_get_multiple (n->reassembly_map,
4727 fb->msg_uuid.uuid,
4728 &find_by_message_uuid,
4729 &fc);
4730 if (NULL == (rc = fc.rc))
4242 { 4731 {
4243 rc = GNUNET_malloc (sizeof (*rc) + msize + /* reassembly payload buffer */ 4732 rc = GNUNET_malloc (sizeof (*rc) + msize + /* reassembly payload buffer */
4244 (msize + 7) / 8 * sizeof (uint8_t) /* bitfield */); 4733 (msize + 7) / 8 * sizeof (uint8_t) /* bitfield */);
@@ -4252,11 +4741,11 @@ handle_fragment_box (void *cls, const struct TransportFragmentBox *fb)
4252 rc, 4741 rc,
4253 rc->reassembly_timeout.abs_value_us); 4742 rc->reassembly_timeout.abs_value_us);
4254 GNUNET_assert (GNUNET_OK == 4743 GNUNET_assert (GNUNET_OK ==
4255 GNUNET_CONTAINER_multishortmap_put ( 4744 GNUNET_CONTAINER_multihashmap32_put (
4256 n->reassembly_map, 4745 n->reassembly_map,
4257 &rc->msg_uuid, 4746 rc->msg_uuid.uuid,
4258 rc, 4747 rc,
4259 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); 4748 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
4260 target = (char *) &rc[1]; 4749 target = (char *) &rc[1];
4261 rc->bitfield = (uint8_t *) (target + rc->msg_size); 4750 rc->bitfield = (uint8_t *) (target + rc->msg_size);
4262 rc->msg_missing = rc->msg_size; 4751 rc->msg_missing = rc->msg_size;
@@ -4274,6 +4763,12 @@ handle_fragment_box (void *cls, const struct TransportFragmentBox *fb)
4274 4763
4275 /* reassemble */ 4764 /* reassemble */
4276 fsize = ntohs (fb->header.size) - sizeof (*fb); 4765 fsize = ntohs (fb->header.size) - sizeof (*fb);
4766 if (0 == fsize)
4767 {
4768 GNUNET_break (0);
4769 finish_cmc_handling (cmc);
4770 return;
4771 }
4277 frag_off = ntohs (fb->frag_off); 4772 frag_off = ntohs (fb->frag_off);
4278 memcpy (&target[frag_off], &fb[1], fsize); 4773 memcpy (&target[frag_off], &fb[1], fsize);
4279 /* update bitfield and msg_missing */ 4774 /* update bitfield and msg_missing */
@@ -4287,60 +4782,17 @@ handle_fragment_box (void *cls, const struct TransportFragmentBox *fb)
4287 } 4782 }
4288 4783
4289 /* Compute cummulative ACK */ 4784 /* Compute cummulative ACK */
4290 frag_uuid = ntohl (fb->frag_uuid);
4291 cdelay = GNUNET_TIME_absolute_get_duration (rc->last_frag); 4785 cdelay = GNUNET_TIME_absolute_get_duration (rc->last_frag);
4292 cdelay = GNUNET_TIME_relative_multiply (cdelay, rc->num_acks); 4786 cdelay = GNUNET_TIME_relative_multiply (cdelay, rc->msg_missing / fsize);
4787 if (0 == rc->msg_missing)
4788 cdelay = GNUNET_TIME_UNIT_ZERO;
4789 cummulative_ack (&cmc->im.sender,
4790 &fb->ack_uuid,
4791 GNUNET_TIME_relative_to_absolute (cdelay));
4293 rc->last_frag = GNUNET_TIME_absolute_get (); 4792 rc->last_frag = GNUNET_TIME_absolute_get ();
4294 rc->avg_ack_delay = GNUNET_TIME_relative_add (rc->avg_ack_delay, cdelay);
4295 ack_now = GNUNET_NO;
4296 if (0 == rc->num_acks)
4297 {
4298 /* case one: first ack */
4299 rc->frag_uuid = frag_uuid;
4300 rc->extra_acks = 0LLU;
4301 rc->num_acks = 1;
4302 }
4303 else if ((frag_uuid >= rc->frag_uuid) && (frag_uuid <= rc->frag_uuid + 64))
4304 {
4305 /* case two: ack fits after existing min UUID */
4306 if ((frag_uuid == rc->frag_uuid) ||
4307 (0 != (rc->extra_acks & (1LLU << (frag_uuid - rc->frag_uuid - 1)))))
4308 {
4309 /* duplicate fragment, ack now! */
4310 ack_now = GNUNET_YES;
4311 }
4312 else
4313 {
4314 rc->extra_acks |= (1LLU << (frag_uuid - rc->frag_uuid - 1));
4315 rc->num_acks++;
4316 }
4317 }
4318 else if ((rc->frag_uuid > frag_uuid) &&
4319 (((rc->frag_uuid == frag_uuid + 64) && (0 == rc->extra_acks)) ||
4320 ((rc->frag_uuid < frag_uuid + 64) &&
4321 (rc->extra_acks ==
4322 (rc->extra_acks &
4323 ~((1LLU << (64 - (rc->frag_uuid - frag_uuid))) - 1LLU))))))
4324 {
4325 /* can fit ack by shifting extra acks and starting at
4326 frag_uid, test above esured that the bits we will
4327 shift 'extra_acks' by are all zero. */
4328 rc->extra_acks <<= (rc->frag_uuid - frag_uuid);
4329 rc->extra_acks |= (1LLU << (rc->frag_uuid - frag_uuid - 1));
4330 rc->frag_uuid = frag_uuid;
4331 rc->num_acks++;
4332 }
4333 if (65 == rc->num_acks) /* OPTIMIZE-FIXME: maybe use smaller threshold? This
4334 is very aggressive. */
4335 ack_now = GNUNET_YES; /* maximum acks received */
4336 // FIXME: possibly also ACK based on RTT (but for that we'd need to
4337 // determine the queue used for the ACK first!)
4338
4339 /* is reassembly complete? */ 4793 /* is reassembly complete? */
4340 if (0 != rc->msg_missing) 4794 if (0 != rc->msg_missing)
4341 { 4795 {
4342 if (ack_now)
4343 send_fragment_ack (rc);
4344 finish_cmc_handling (cmc); 4796 finish_cmc_handling (cmc);
4345 return; 4797 return;
4346 } 4798 }
@@ -4354,7 +4806,6 @@ handle_fragment_box (void *cls, const struct TransportFragmentBox *fb)
4354 return; 4806 return;
4355 } 4807 }
4356 /* successful reassembly */ 4808 /* successful reassembly */
4357 send_fragment_ack (rc);
4358 demultiplex_with_cmc (cmc, msg); 4809 demultiplex_with_cmc (cmc, msg);
4359 /* FIXME-OPTIMIZE: really free here? Might be bad if fragments are still 4810 /* FIXME-OPTIMIZE: really free here? Might be bad if fragments are still
4360 en-route and we forget that we finished this reassembly immediately! 4811 en-route and we forget that we finished this reassembly immediately!
@@ -4365,171 +4816,203 @@ handle_fragment_box (void *cls, const struct TransportFragmentBox *fb)
4365 4816
4366 4817
4367/** 4818/**
4368 * Check the @a fa against the fragments associated with @a pm. 4819 * Communicator gave us a reliability box. Check the message.
4369 * If it matches, remove the matching fragments from the transmission
4370 * list.
4371 * 4820 *
4372 * @param pm pending message to check against the ack 4821 * @param cls a `struct CommunicatorMessageContext`
4373 * @param fa the ack that was received 4822 * @param rb the send message that was sent
4374 * @return #GNUNET_YES if @a fa matched, #GNUNET_NO if not 4823 * @return #GNUNET_YES if message is well-formed
4375 */ 4824 */
4376static int 4825static int
4377check_ack_against_pm (struct PendingMessage *pm, 4826check_reliability_box (void *cls,
4378 const struct TransportFragmentAckMessage *fa) 4827 const struct TransportReliabilityBoxMessage *rb)
4379{ 4828{
4380 int match; 4829 GNUNET_MQ_check_boxed_message (rb);
4381 struct PendingMessage *nxt; 4830 return GNUNET_YES;
4382 uint32_t fs = ntohl (fa->frag_uuid);
4383 uint64_t xtra = GNUNET_ntohll (fa->extra_acks);
4384
4385 match = GNUNET_NO;
4386 for (struct PendingMessage *frag = pm->head_frag; NULL != frag; frag = nxt)
4387 {
4388 const struct TransportFragmentBox *tfb =
4389 (const struct TransportFragmentBox *) &pm[1];
4390 uint32_t fu = ntohl (tfb->frag_uuid);
4391
4392 GNUNET_assert (PMT_FRAGMENT_BOX == frag->pmt);
4393 nxt = frag->next_frag;
4394 /* Check for exact match or match in the 'xtra' bitmask */
4395 if ((fu == fs) ||
4396 ((fu > fs) && (fu <= fs + 64) && (0 != (1LLU << (fu - fs - 1) & xtra))))
4397 {
4398 match = GNUNET_YES;
4399 free_fragment_tree (frag);
4400 }
4401 }
4402 return match;
4403} 4831}
4404 4832
4405 4833
4406/** 4834/**
4407 * Communicator gave us a fragment acknowledgement. Process the request. 4835 * Communicator gave us a reliability box. Process the request.
4408 * 4836 *
4409 * @param cls a `struct CommunicatorMessageContext` (must call 4837 * @param cls a `struct CommunicatorMessageContext` (must call
4410 * #finish_cmc_handling() when done) 4838 * #finish_cmc_handling() when done)
4411 * @param fa the message that was received 4839 * @param rb the message that was received
4412 */ 4840 */
4413static void 4841static void
4414handle_fragment_ack (void *cls, const struct TransportFragmentAckMessage *fa) 4842handle_reliability_box (void *cls,
4843 const struct TransportReliabilityBoxMessage *rb)
4415{ 4844{
4416 struct CommunicatorMessageContext *cmc = cls; 4845 struct CommunicatorMessageContext *cmc = cls;
4417 struct Neighbour *n; 4846 const struct GNUNET_MessageHeader *inbox =
4418 int matched; 4847 (const struct GNUNET_MessageHeader *) &rb[1];
4419 4848
4420 n = GNUNET_CONTAINER_multipeermap_get (neighbours, &cmc->im.sender); 4849 // FIXME: call cummulative_ack(), have ack_countdown influence max_delay!
4421 if (NULL == n) 4850 (void) (0 == ntohl (rb->ack_countdown));
4422 { 4851 /* continue with inner message */
4423 struct GNUNET_SERVICE_Client *client = cmc->tc->client; 4852 demultiplex_with_cmc (cmc, inbox);
4853}
4424 4854
4425 GNUNET_break (0); 4855
4426 finish_cmc_handling (cmc); 4856/**
4427 GNUNET_SERVICE_client_drop (client); 4857 * Check if we have advanced to another age since the last time. If
4428 return; 4858 * so, purge ancient statistics (more than GOODPUT_AGING_SLOTS before
4429 } 4859 * the current age)
4430 /* FIXME-OPTIMIZE: maybe use another hash map here? */ 4860 *
4431 matched = GNUNET_NO; 4861 * @param pd[in,out] data to update
4432 for (struct PendingMessage *pm = n->pending_msg_head; NULL != pm; 4862 * @param age current age
4433 pm = pm->prev_neighbour) 4863 */
4434 { 4864static void
4435 if (0 != GNUNET_memcmp (&fa->msg_uuid, &pm->msg_uuid)) 4865update_pd_age (struct PerformanceData *pd, unsigned int age)
4436 continue; 4866{
4437 matched = GNUNET_YES; 4867 unsigned int sage;
4438 if (GNUNET_YES == check_ack_against_pm (pm, fa)) 4868
4439 { 4869 if (age == pd->last_age)
4440 struct GNUNET_TIME_Relative avg_ack_delay = 4870 return; /* nothing to do */
4441 GNUNET_TIME_relative_ntoh (fa->avg_ack_delay); 4871 sage = GNUNET_MAX (pd->last_age, age - 2 * GOODPUT_AGING_SLOTS);
4442 // FIXME: update RTT and other reliability data! 4872 for (unsigned int i = sage; i <= age - GOODPUT_AGING_SLOTS; i++)
4443 // ISSUE: we don't know which of n's queues the message(s)
4444 // took (and in fact the different messages might have gone
4445 // over different queues and possibly over multiple).
4446 // => track queues with PendingMessages, and update RTT only if
4447 // the queue used is unique?
4448 // -> how can we get loss rates?
4449 // -> or, add extra state to Box and ACK to identify queue?
4450 // IDEA: generate MULTIPLE frag-uuids per fragment and track
4451 // the queue with the fragment! (-> this logic must
4452 // be moved into check_ack_against_pm!)
4453 (void) avg_ack_delay;
4454 }
4455 else
4456 {
4457 GNUNET_STATISTICS_update (GST_stats,
4458 "# FRAGMENT_ACKS dropped, no matching fragment",
4459 1,
4460 GNUNET_NO);
4461 }
4462 if (NULL == pm->head_frag)
4463 {
4464 // if entire message is ACKed, handle that as well.
4465 // => clean up PM, any post actions?
4466 free_pending_message (pm);
4467 }
4468 else
4469 {
4470 struct GNUNET_TIME_Relative reassembly_timeout =
4471 GNUNET_TIME_relative_ntoh (fa->reassembly_timeout);
4472 // OPTIMIZE-FIXME: adjust retransmission strategy based on
4473 // reassembly_timeout!
4474 (void) reassembly_timeout;
4475 }
4476 break;
4477 }
4478 if (GNUNET_NO == matched)
4479 { 4873 {
4480 GNUNET_STATISTICS_update (GST_stats, 4874 struct TransmissionHistoryEntry *the = &pd->the[i % GOODPUT_AGING_SLOTS];
4481 "# FRAGMENT_ACKS dropped, no matching pending message", 4875
4482 1, 4876 the->bytes_sent = 0;
4483 GNUNET_NO); 4877 the->bytes_received = 0;
4484 } 4878 }
4485 finish_cmc_handling (cmc); 4879 pd->last_age = age;
4486} 4880}
4487 4881
4488 4882
4489/** 4883/**
4490 * Communicator gave us a reliability box. Check the message. 4884 * Update @a pd based on the latest @a rtt and the number of bytes
4885 * that were confirmed to be successfully transmitted.
4491 * 4886 *
4492 * @param cls a `struct CommunicatorMessageContext` 4887 * @param pd[in,out] data to update
4493 * @param rb the send message that was sent 4888 * @param rtt latest round-trip time
4494 * @return #GNUNET_YES if message is well-formed 4889 * @param bytes_transmitted_ok number of bytes receiver confirmed as received
4495 */ 4890 */
4496static int 4891static void
4497check_reliability_box (void *cls, const struct TransportReliabilityBox *rb) 4892update_performance_data (struct PerformanceData *pd,
4893 struct GNUNET_TIME_Relative rtt,
4894 uint16_t bytes_transmitted_ok)
4498{ 4895{
4499 GNUNET_MQ_check_boxed_message (rb); 4896 uint64_t nval = rtt.rel_value_us;
4500 return GNUNET_YES; 4897 uint64_t oval = pd->aged_rtt.rel_value_us;
4898 unsigned int age = get_age ();
4899 struct TransmissionHistoryEntry *the = &pd->the[age % GOODPUT_AGING_SLOTS];
4900
4901 if (oval == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
4902 pd->aged_rtt = rtt;
4903 else
4904 pd->aged_rtt.rel_value_us = (nval + 7 * oval) / 8;
4905 update_pd_age (pd, age);
4906 the->bytes_received += bytes_transmitted_ok;
4501} 4907}
4502 4908
4503 4909
4504/** 4910/**
4505 * Communicator gave us a reliability box. Process the request. 4911 * We have successfully transmitted data via @a q, update metrics.
4506 * 4912 *
4507 * @param cls a `struct CommunicatorMessageContext` (must call 4913 * @param q queue to update
4508 * #finish_cmc_handling() when done) 4914 * @param rtt round trip time observed
4509 * @param rb the message that was received 4915 * @param bytes_transmitted_ok number of bytes successfully transmitted
4510 */ 4916 */
4511static void 4917static void
4512handle_reliability_box (void *cls, const struct TransportReliabilityBox *rb) 4918update_queue_performance (struct Queue *q,
4919 struct GNUNET_TIME_Relative rtt,
4920 uint16_t bytes_transmitted_ok)
4513{ 4921{
4514 struct CommunicatorMessageContext *cmc = cls; 4922 update_performance_data (&q->pd, rtt, bytes_transmitted_ok);
4515 const struct GNUNET_MessageHeader *inbox = 4923}
4516 (const struct GNUNET_MessageHeader *) &rb[1];
4517 4924
4518 if (0 == ntohl (rb->ack_countdown))
4519 {
4520 struct TransportReliabilityAckMessage *ack;
4521 4925
4522 /* FIXME-OPTIMIZE: implement cummulative ACKs and ack_countdown, 4926/**
4523 then setting the avg_ack_delay field below: */ 4927 * We have successfully transmitted data via @a dvh, update metrics.
4524 ack = GNUNET_malloc (sizeof (*ack) + sizeof (struct GNUNET_ShortHashCode)); 4928 *
4525 ack->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK); 4929 * @param dvh distance vector path data to update
4526 ack->header.size = 4930 * @param rtt round trip time observed
4527 htons (sizeof (*ack) + sizeof (struct GNUNET_ShortHashCode)); 4931 * @param bytes_transmitted_ok number of bytes successfully transmitted
4528 memcpy (&ack[1], &rb->msg_uuid, sizeof (struct GNUNET_ShortHashCode)); 4932 */
4529 route_message (&cmc->im.sender, &ack->header, RMO_DV_ALLOWED); 4933static void
4934update_dvh_performance (struct DistanceVectorHop *dvh,
4935 struct GNUNET_TIME_Relative rtt,
4936 uint16_t bytes_transmitted_ok)
4937{
4938 update_performance_data (&dvh->pd, rtt, bytes_transmitted_ok);
4939}
4940
4941
4942/**
4943 * The @a pa was acknowledged, process the acknowledgement.
4944 *
4945 * @param pa the pending acknowledgement that was satisfied
4946 * @param ack_delay artificial delay from cummulative acks created by the other
4947 * peer
4948 */
4949static void
4950handle_acknowledged (struct PendingAcknowledgement *pa,
4951 struct GNUNET_TIME_Relative ack_delay)
4952{
4953 struct PendingMessage *pm = pa->pm;
4954 struct GNUNET_TIME_Relative delay;
4955
4956 delay = GNUNET_TIME_absolute_get_duration (pa->transmission_time);
4957 if (delay.rel_value_us > ack_delay.rel_value_us)
4958 delay = GNUNET_TIME_UNIT_ZERO;
4959 else
4960 delay = GNUNET_TIME_relative_subtract (delay, ack_delay);
4961 if (NULL != pa->queue)
4962 update_queue_performance (pa->queue, delay, pa->message_size);
4963 if (NULL != pa->dvh)
4964 update_dvh_performance (pa->dvh, delay, pa->message_size);
4965 if (NULL != pm)
4966 {
4967 if (NULL != pm->frag_parent)
4968 {
4969 pm = pm->frag_parent;
4970 free_fragment_tree (pa->pm);
4971 }
4972 while ((NULL != pm->frag_parent) && (NULL == pm->head_frag))
4973 {
4974 struct PendingMessage *parent = pm->frag_parent;
4975
4976 free_fragment_tree (pm);
4977 pm = parent;
4978 }
4979 if (NULL != pm->head_frag)
4980 pm = NULL; /* we are done, otherwise free 'pm' below */
4530 } 4981 }
4531 /* continue with inner message */ 4982 if (NULL != pm)
4532 demultiplex_with_cmc (cmc, inbox); 4983 free_pending_message (pm);
4984 free_pending_acknowledgement (pa);
4985}
4986
4987
4988/**
4989 * Communicator gave us a reliability ack. Check it is well-formed.
4990 *
4991 * @param cls a `struct CommunicatorMessageContext` (unused)
4992 * @param ra the message that was received
4993 * @return #GNUNET_Ok if @a ra is well-formed
4994 */
4995static int
4996check_reliability_ack (void *cls,
4997 const struct TransportReliabilityAckMessage *ra)
4998{
4999 unsigned int n_acks;
5000
5001 (void) cls;
5002 n_acks = (ntohs (ra->header.size) - sizeof (*ra)) /
5003 sizeof (struct TransportCummulativeAckPayloadP);
5004 if (0 == n_acks)
5005 {
5006 GNUNET_break_op (0);
5007 return GNUNET_SYSERR;
5008 }
5009 if ((ntohs (ra->header.size) - sizeof (*ra)) !=
5010 n_acks * sizeof (struct TransportCummulativeAckPayloadP))
5011 {
5012 GNUNET_break_op (0);
5013 return GNUNET_SYSERR;
5014 }
5015 return GNUNET_OK;
4533} 5016}
4534 5017
4535 5018
@@ -4545,70 +5028,33 @@ handle_reliability_ack (void *cls,
4545 const struct TransportReliabilityAckMessage *ra) 5028 const struct TransportReliabilityAckMessage *ra)
4546{ 5029{
4547 struct CommunicatorMessageContext *cmc = cls; 5030 struct CommunicatorMessageContext *cmc = cls;
4548 struct Neighbour *n; 5031 const struct TransportCummulativeAckPayloadP *ack;
5032 struct PendingAcknowledgement *pa;
4549 unsigned int n_acks; 5033 unsigned int n_acks;
4550 const struct GNUNET_ShortHashCode *msg_uuids; 5034 uint32_t ack_counter;
4551 struct PendingMessage *nxt;
4552 int matched;
4553 5035
4554 n = GNUNET_CONTAINER_multipeermap_get (neighbours, &cmc->im.sender);
4555 if (NULL == n)
4556 {
4557 struct GNUNET_SERVICE_Client *client = cmc->tc->client;
4558
4559 GNUNET_break (0);
4560 finish_cmc_handling (cmc);
4561 GNUNET_SERVICE_client_drop (client);
4562 return;
4563 }
4564 n_acks = (ntohs (ra->header.size) - sizeof (*ra)) / 5036 n_acks = (ntohs (ra->header.size) - sizeof (*ra)) /
4565 sizeof (struct GNUNET_ShortHashCode); 5037 sizeof (struct TransportCummulativeAckPayloadP);
4566 msg_uuids = (const struct GNUNET_ShortHashCode *) &ra[1]; 5038 ack = (const struct TransportCummulativeAckPayloadP *) &ra[1];
4567 5039 for (unsigned int i = 0; i < n_acks; i++)
4568 /* FIXME-OPTIMIZE: maybe use another hash map here? */
4569 matched = GNUNET_NO;
4570 for (struct PendingMessage *pm = n->pending_msg_head; NULL != pm; pm = nxt)
4571 { 5040 {
4572 int in_list; 5041 pa =
4573 5042 GNUNET_CONTAINER_multishortmap_get (pending_acks, &ack[i].ack_uuid.value);
4574 nxt = pm->next_neighbour; 5043 if (NULL == pa)
4575 in_list = GNUNET_NO;
4576 for (unsigned int i = 0; i < n_acks; i++)
4577 { 5044 {
4578 if (0 != GNUNET_memcmp (&msg_uuids[i], &pm->msg_uuid)) 5045 GNUNET_STATISTICS_update (
4579 continue; 5046 GST_stats,
4580 in_list = GNUNET_YES; 5047 "# FRAGMENT_ACKS dropped, no matching pending message",
4581 break; 5048 1,
4582 } 5049 GNUNET_NO);
4583 if (GNUNET_NO == in_list)
4584 continue; 5050 continue;
4585
4586 /* this pm was acked! */
4587 matched = GNUNET_YES;
4588 free_pending_message (pm);
4589
4590 {
4591 struct GNUNET_TIME_Relative avg_ack_delay =
4592 GNUNET_TIME_relative_ntoh (ra->avg_ack_delay);
4593 // FIXME: update RTT and other reliability data!
4594 // ISSUE: we don't know which of n's queues the message(s)
4595 // took (and in fact the different messages might have gone
4596 // over different queues and possibly over multiple).
4597 // => track queues with PendingMessages, and update RTT only if
4598 // the queue used is unique?
4599 // -> how can we get loss rates?
4600 // -> or, add extra state to MSG and ACKs to identify queue?
4601 // -> if we do this, might just do the same for the avg_ack_delay!
4602 (void) avg_ack_delay;
4603 } 5051 }
5052 handle_acknowledged (pa, GNUNET_TIME_relative_ntoh (ack[i].ack_delay));
4604 } 5053 }
4605 if (GNUNET_NO == matched) 5054
4606 { 5055 ack_counter = htonl (ra->ack_counter);
4607 GNUNET_STATISTICS_update (GST_stats, 5056 // FIXME: track ACK losses based on ack_counter somewhere!
4608 "# FRAGMENT_ACKS dropped, no matching pending message", 5057 // (DV and/or Neighbour?)
4609 1,
4610 GNUNET_NO);
4611 }
4612 finish_cmc_handling (cmc); 5058 finish_cmc_handling (cmc);
4613} 5059}
4614 5060
@@ -4629,7 +5075,7 @@ check_backchannel_encapsulation (
4629 5075
4630 (void) cls; 5076 (void) cls;
4631 if ((size - sizeof (*be)) < 5077 if ((size - sizeof (*be)) <
4632 (sizeof (struct TransportBackchannelRequestPayload) + 5078 (sizeof (struct TransportBackchannelRequestPayloadP) +
4633 sizeof (struct GNUNET_MessageHeader))) 5079 sizeof (struct GNUNET_MessageHeader)))
4634 { 5080 {
4635 GNUNET_break_op (0); 5081 GNUNET_break_op (0);
@@ -4824,7 +5270,8 @@ backtalker_monotime_cb (void *cls,
4824 1, 5270 1,
4825 GNUNET_NO); 5271 GNUNET_NO);
4826 b->monotonic_time = mt; 5272 b->monotonic_time = mt;
4827 /* Setting body_size to 0 prevents call to #forward_backchannel_payload() */ 5273 /* Setting body_size to 0 prevents call to #forward_backchannel_payload()
5274 */
4828 b->body_size = 0; 5275 b->body_size = 0;
4829 return; 5276 return;
4830 } 5277 }
@@ -4932,7 +5379,7 @@ handle_backchannel_encapsulation (
4932 { 5379 {
4933 struct Backtalker *b; 5380 struct Backtalker *b;
4934 struct GNUNET_TIME_Absolute monotime; 5381 struct GNUNET_TIME_Absolute monotime;
4935 struct TransportBackchannelRequestPayload ppay; 5382 struct TransportBackchannelRequestPayloadP ppay;
4936 char body[hdr_len - sizeof (ppay)]; 5383 char body[hdr_len - sizeof (ppay)];
4937 5384
4938 GNUNET_assert (hdr_len >= 5385 GNUNET_assert (hdr_len >=
@@ -5124,13 +5571,13 @@ activate_core_visible_dv_path (struct DistanceVectorHop *hop)
5124 * non-first hop is in our neighbour list (returning #GNUNET_SYSERR). 5571 * non-first hop is in our neighbour list (returning #GNUNET_SYSERR).
5125 * 5572 *
5126 * @param path the path we learned, path[0] should be us, 5573 * @param path the path we learned, path[0] should be us,
5127 * and then path contains a valid path from us to `path[path_len-1]` 5574 * and then path contains a valid path from us to
5128 * path[1] should be a direct neighbour (we should check!) 5575 * `path[path_len-1]` path[1] should be a direct neighbour (we should check!)
5129 * @param path_len number of entries on the @a path, at least three! 5576 * @param path_len number of entries on the @a path, at least three!
5130 * @param network_latency how long does the message take from us to 5577 * @param network_latency how long does the message take from us to
5131 * `path[path_len-1]`? set to "forever" if unknown 5578 * `path[path_len-1]`? set to "forever" if unknown
5132 * @param path_valid_until how long is this path considered validated? Maybe be 5579 * @param path_valid_until how long is this path considered validated? Maybe
5133 * zero. 5580 * be zero.
5134 * @return #GNUNET_YES on success, 5581 * @return #GNUNET_YES on success,
5135 * #GNUNET_NO if we have better path(s) to the target 5582 * #GNUNET_NO if we have better path(s) to the target
5136 * #GNUNET_SYSERR if the path is useless and/or invalid 5583 * #GNUNET_SYSERR if the path is useless and/or invalid
@@ -5279,7 +5726,7 @@ learn_dv_path (const struct GNUNET_PeerIdentity *path,
5279 * @return #GNUNET_YES if message is well-formed 5726 * @return #GNUNET_YES if message is well-formed
5280 */ 5727 */
5281static int 5728static int
5282check_dv_learn (void *cls, const struct TransportDVLearn *dvl) 5729check_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
5283{ 5730{
5284 uint16_t size = ntohs (dvl->header.size); 5731 uint16_t size = ntohs (dvl->header.size);
5285 uint16_t num_hops = ntohs (dvl->num_hops); 5732 uint16_t num_hops = ntohs (dvl->num_hops);
@@ -5326,22 +5773,22 @@ check_dv_learn (void *cls, const struct TransportDVLearn *dvl)
5326 */ 5773 */
5327static void 5774static void
5328forward_dv_learn (const struct GNUNET_PeerIdentity *next_hop, 5775forward_dv_learn (const struct GNUNET_PeerIdentity *next_hop,
5329 const struct TransportDVLearn *msg, 5776 const struct TransportDVLearnMessage *msg,
5330 uint16_t bi_history, 5777 uint16_t bi_history,
5331 uint16_t nhops, 5778 uint16_t nhops,
5332 const struct DVPathEntryP *hops, 5779 const struct DVPathEntryP *hops,
5333 struct GNUNET_TIME_Absolute in_time) 5780 struct GNUNET_TIME_Absolute in_time)
5334{ 5781{
5335 struct DVPathEntryP *dhops; 5782 struct DVPathEntryP *dhops;
5336 struct TransportDVLearn *fwd; 5783 struct TransportDVLearnMessage *fwd;
5337 struct GNUNET_TIME_Relative nnd; 5784 struct GNUNET_TIME_Relative nnd;
5338 5785
5339 /* compute message for forwarding */ 5786 /* compute message for forwarding */
5340 GNUNET_assert (nhops < MAX_DV_HOPS_ALLOWED); 5787 GNUNET_assert (nhops < MAX_DV_HOPS_ALLOWED);
5341 fwd = GNUNET_malloc (sizeof (struct TransportDVLearn) + 5788 fwd = GNUNET_malloc (sizeof (struct TransportDVLearnMessage) +
5342 (nhops + 1) * sizeof (struct DVPathEntryP)); 5789 (nhops + 1) * sizeof (struct DVPathEntryP));
5343 fwd->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN); 5790 fwd->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN);
5344 fwd->header.size = htons (sizeof (struct TransportDVLearn) + 5791 fwd->header.size = htons (sizeof (struct TransportDVLearnMessage) +
5345 (nhops + 1) * sizeof (struct DVPathEntryP)); 5792 (nhops + 1) * sizeof (struct DVPathEntryP));
5346 fwd->num_hops = htons (nhops + 1); 5793 fwd->num_hops = htons (nhops + 1);
5347 fwd->bidirectional = htons (bi_history); 5794 fwd->bidirectional = htons (bi_history);
@@ -5383,7 +5830,7 @@ forward_dv_learn (const struct GNUNET_PeerIdentity *next_hop,
5383static int 5830static int
5384validate_dv_initiator_signature ( 5831validate_dv_initiator_signature (
5385 const struct GNUNET_PeerIdentity *init, 5832 const struct GNUNET_PeerIdentity *init,
5386 const struct GNUNET_ShortHashCode *challenge, 5833 const struct ChallengeNonceP *challenge,
5387 const struct GNUNET_CRYPTO_EddsaSignature *init_sig) 5834 const struct GNUNET_CRYPTO_EddsaSignature *init_sig)
5388{ 5835{
5389 struct DvInitPS ip = {.purpose.purpose = htonl ( 5836 struct DvInitPS ip = {.purpose.purpose = htonl (
@@ -5413,7 +5860,7 @@ validate_dv_initiator_signature (
5413 * @param dvl the message that was received 5860 * @param dvl the message that was received
5414 */ 5861 */
5415static void 5862static void
5416handle_dv_learn (void *cls, const struct TransportDVLearn *dvl) 5863handle_dv_learn (void *cls, const struct TransportDVLearnMessage *dvl)
5417{ 5864{
5418 struct CommunicatorMessageContext *cmc = cls; 5865 struct CommunicatorMessageContext *cmc = cls;
5419 enum GNUNET_TRANSPORT_CommunicatorCharacteristics cc; 5866 enum GNUNET_TRANSPORT_CommunicatorCharacteristics cc;
@@ -5459,7 +5906,8 @@ handle_dv_learn (void *cls, const struct TransportDVLearn *dvl)
5459 finish_cmc_handling (cmc); 5906 finish_cmc_handling (cmc);
5460 5907
5461 /* OPTIMIZE-FIXME: Technically, we only need to bother checking 5908 /* OPTIMIZE-FIXME: Technically, we only need to bother checking
5462 the initiator signature if we send the message back to the initiator... */ 5909 the initiator signature if we send the message back to the initiator...
5910 */
5463 if (GNUNET_OK != validate_dv_initiator_signature (&dvl->initiator, 5911 if (GNUNET_OK != validate_dv_initiator_signature (&dvl->initiator,
5464 &dvl->challenge, 5912 &dvl->challenge,
5465 &dvl->init_sig)) 5913 &dvl->init_sig))
@@ -5611,7 +6059,7 @@ handle_dv_learn (void *cls, const struct TransportDVLearn *dvl)
5611 * @return #GNUNET_YES if message is well-formed 6059 * @return #GNUNET_YES if message is well-formed
5612 */ 6060 */
5613static int 6061static int
5614check_dv_box (void *cls, const struct TransportDVBox *dvb) 6062check_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
5615{ 6063{
5616 uint16_t size = ntohs (dvb->header.size); 6064 uint16_t size = ntohs (dvb->header.size);
5617 uint16_t num_hops = ntohs (dvb->num_hops); 6065 uint16_t num_hops = ntohs (dvb->num_hops);
@@ -5673,17 +6121,17 @@ forward_dv_box (struct Neighbour *next_hop,
5673 const void *payload, 6121 const void *payload,
5674 uint16_t payload_size) 6122 uint16_t payload_size)
5675{ 6123{
5676 struct TransportDVBox *dvb; 6124 struct TransportDVBoxMessage *dvb;
5677 struct GNUNET_PeerIdentity *dhops; 6125 struct GNUNET_PeerIdentity *dhops;
5678 6126
5679 GNUNET_assert (UINT16_MAX < sizeof (struct TransportDVBox) + 6127 GNUNET_assert (UINT16_MAX < sizeof (struct TransportDVBoxMessage) +
5680 sizeof (struct GNUNET_PeerIdentity) * num_hops + 6128 sizeof (struct GNUNET_PeerIdentity) * num_hops +
5681 payload_size); 6129 payload_size);
5682 dvb = GNUNET_malloc (sizeof (struct TransportDVBox) + 6130 dvb = GNUNET_malloc (sizeof (struct TransportDVBoxMessage) +
5683 sizeof (struct GNUNET_PeerIdentity) * num_hops + 6131 sizeof (struct GNUNET_PeerIdentity) * num_hops +
5684 payload_size); 6132 payload_size);
5685 dvb->header.size = 6133 dvb->header.size =
5686 htons (sizeof (struct TransportDVBox) + 6134 htons (sizeof (struct TransportDVBoxMessage) +
5687 sizeof (struct GNUNET_PeerIdentity) * num_hops + payload_size); 6135 sizeof (struct GNUNET_PeerIdentity) * num_hops + payload_size);
5688 dvb->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX); 6136 dvb->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX);
5689 dvb->total_hops = htons (total_hops); 6137 dvb->total_hops = htons (total_hops);
@@ -5704,7 +6152,7 @@ forward_dv_box (struct Neighbour *next_hop,
5704 * @param dvb the message that was received 6152 * @param dvb the message that was received
5705 */ 6153 */
5706static void 6154static void
5707handle_dv_box (void *cls, const struct TransportDVBox *dvb) 6155handle_dv_box (void *cls, const struct TransportDVBoxMessage *dvb)
5708{ 6156{
5709 struct CommunicatorMessageContext *cmc = cls; 6157 struct CommunicatorMessageContext *cmc = cls;
5710 uint16_t size = ntohs (dvb->header.size) - sizeof (*dvb); 6158 uint16_t size = ntohs (dvb->header.size) - sizeof (*dvb);
@@ -5788,11 +6236,12 @@ check_incoming_msg (void *cls,
5788 * @param tvc the message that was received 6236 * @param tvc the message that was received
5789 */ 6237 */
5790static void 6238static void
5791handle_validation_challenge (void *cls, 6239handle_validation_challenge (
5792 const struct TransportValidationChallenge *tvc) 6240 void *cls,
6241 const struct TransportValidationChallengeMessage *tvc)
5793{ 6242{
5794 struct CommunicatorMessageContext *cmc = cls; 6243 struct CommunicatorMessageContext *cmc = cls;
5795 struct TransportValidationResponse *tvr; 6244 struct TransportValidationResponseMessage *tvr;
5796 6245
5797 if (cmc->total_hops > 0) 6246 if (cmc->total_hops > 0)
5798 { 6247 {
@@ -5801,7 +6250,7 @@ handle_validation_challenge (void *cls,
5801 finish_cmc_handling (cmc); 6250 finish_cmc_handling (cmc);
5802 return; 6251 return;
5803 } 6252 }
5804 tvr = GNUNET_new (struct TransportValidationResponse); 6253 tvr = GNUNET_new (struct TransportValidationResponseMessage);
5805 tvr->header.type = 6254 tvr->header.type =
5806 htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE); 6255 htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE);
5807 tvr->header.size = htons (sizeof (*tvr)); 6256 tvr->header.size = htons (sizeof (*tvr));
@@ -5835,7 +6284,7 @@ struct CheckKnownChallengeContext
5835 /** 6284 /**
5836 * Set to the challenge we are looking for. 6285 * Set to the challenge we are looking for.
5837 */ 6286 */
5838 const struct GNUNET_ShortHashCode *challenge; 6287 const struct ChallengeNonceP *challenge;
5839 6288
5840 /** 6289 /**
5841 * Set to a matching validation state, if one was found. 6290 * Set to a matching validation state, if one was found.
@@ -6039,8 +6488,9 @@ update_neighbour_core_visibility (struct Neighbour *n)
6039 * @param tvr the message that was received 6488 * @param tvr the message that was received
6040 */ 6489 */
6041static void 6490static void
6042handle_validation_response (void *cls, 6491handle_validation_response (
6043 const struct TransportValidationResponse *tvr) 6492 void *cls,
6493 const struct TransportValidationResponseMessage *tvr)
6044{ 6494{
6045 struct CommunicatorMessageContext *cmc = cls; 6495 struct CommunicatorMessageContext *cmc = cls;
6046 struct ValidationState *vs; 6496 struct ValidationState *vs;
@@ -6145,7 +6595,7 @@ handle_validation_response (void *cls,
6145 return; 6595 return;
6146 } 6596 }
6147 q->validated_until = vs->validated_until; 6597 q->validated_until = vs->validated_until;
6148 q->rtt = vs->validation_rtt; 6598 q->pd.aged_rtt = vs->validation_rtt;
6149 n = q->neighbour; 6599 n = q->neighbour;
6150 if (GNUNET_NO != n->core_visible) 6600 if (GNUNET_NO != n->core_visible)
6151 return; /* nothing changed, we are done here */ 6601 return; /* nothing changed, we are done here */
@@ -6201,41 +6651,37 @@ demultiplex_with_cmc (struct CommunicatorMessageContext *cmc,
6201 struct GNUNET_MQ_MessageHandler handlers[] = 6651 struct GNUNET_MQ_MessageHandler handlers[] =
6202 {GNUNET_MQ_hd_var_size (fragment_box, 6652 {GNUNET_MQ_hd_var_size (fragment_box,
6203 GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT, 6653 GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT,
6204 struct TransportFragmentBox, 6654 struct TransportFragmentBoxMessage,
6205 &cmc), 6655 &cmc),
6206 GNUNET_MQ_hd_fixed_size (fragment_ack,
6207 GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT_ACK,
6208 struct TransportFragmentAckMessage,
6209 &cmc),
6210 GNUNET_MQ_hd_var_size (reliability_box, 6656 GNUNET_MQ_hd_var_size (reliability_box,
6211 GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX, 6657 GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX,
6212 struct TransportReliabilityBox, 6658 struct TransportReliabilityBoxMessage,
6659 &cmc),
6660 GNUNET_MQ_hd_var_size (reliability_ack,
6661 GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK,
6662 struct TransportReliabilityAckMessage,
6213 &cmc), 6663 &cmc),
6214 GNUNET_MQ_hd_fixed_size (reliability_ack,
6215 GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK,
6216 struct TransportReliabilityAckMessage,
6217 &cmc),
6218 GNUNET_MQ_hd_var_size (backchannel_encapsulation, 6664 GNUNET_MQ_hd_var_size (backchannel_encapsulation,
6219 GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION, 6665 GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION,
6220 struct TransportBackchannelEncapsulationMessage, 6666 struct TransportBackchannelEncapsulationMessage,
6221 &cmc), 6667 &cmc),
6222 GNUNET_MQ_hd_var_size (dv_learn, 6668 GNUNET_MQ_hd_var_size (dv_learn,
6223 GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN, 6669 GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN,
6224 struct TransportDVLearn, 6670 struct TransportDVLearnMessage,
6225 &cmc), 6671 &cmc),
6226 GNUNET_MQ_hd_var_size (dv_box, 6672 GNUNET_MQ_hd_var_size (dv_box,
6227 GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX, 6673 GNUNET_MESSAGE_TYPE_TRANSPORT_DV_BOX,
6228 struct TransportDVBox, 6674 struct TransportDVBoxMessage,
6229 &cmc), 6675 &cmc),
6230 GNUNET_MQ_hd_fixed_size ( 6676 GNUNET_MQ_hd_fixed_size (
6231 validation_challenge, 6677 validation_challenge,
6232 GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE, 6678 GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE,
6233 struct TransportValidationChallenge, 6679 struct TransportValidationChallengeMessage,
6234 &cmc), 6680 &cmc),
6235 GNUNET_MQ_hd_fixed_size ( 6681 GNUNET_MQ_hd_fixed_size (
6236 validation_response, 6682 validation_response,
6237 GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE, 6683 GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE,
6238 struct TransportValidationResponse, 6684 struct TransportValidationResponseMessage,
6239 &cmc), 6685 &cmc),
6240 GNUNET_MQ_handler_end ()}; 6686 GNUNET_MQ_handler_end ()};
6241 int ret; 6687 int ret;
@@ -6315,27 +6761,76 @@ set_pending_message_uuid (struct PendingMessage *pm)
6315 6761
6316 6762
6317/** 6763/**
6764 * Setup data structure waiting for acknowledgements.
6765 *
6766 * @param queue queue the @a pm will be sent over
6767 * @param dvh path the message will take, may be NULL
6768 * @param pm the pending message for transmission
6769 * @return corresponding fresh pending acknowledgement
6770 */
6771static struct PendingAcknowledgement *
6772prepare_pending_acknowledgement (struct Queue *queue,
6773 struct DistanceVectorHop *dvh,
6774 struct PendingMessage *pm)
6775{
6776 struct PendingAcknowledgement *pa;
6777
6778 pa = GNUNET_new (struct PendingAcknowledgement);
6779 pa->queue = queue;
6780 pa->dvh = dvh;
6781 pa->pm = pm;
6782 do
6783 {
6784 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
6785 &pa->ack_uuid,
6786 sizeof (pa->ack_uuid));
6787 } while (GNUNET_YES != GNUNET_CONTAINER_multishortmap_put (
6788 pending_acks,
6789 &pa->ack_uuid.value,
6790 pa,
6791 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
6792 GNUNET_CONTAINER_MDLL_insert (queue, queue->pa_head, queue->pa_tail, pa);
6793 GNUNET_CONTAINER_MDLL_insert (pm, pm->pa_head, pm->pa_tail, pa);
6794 if (NULL != dvh)
6795 GNUNET_CONTAINER_MDLL_insert (dvh, dvh->pa_head, dvh->pa_tail, pa);
6796 pa->transmission_time = GNUNET_TIME_absolute_get ();
6797 pa->message_size = pm->bytes_msg;
6798 return pa;
6799}
6800
6801
6802/**
6318 * Fragment the given @a pm to the given @a mtu. Adds 6803 * Fragment the given @a pm to the given @a mtu. Adds
6319 * additional fragments to the neighbour as well. If the 6804 * additional fragments to the neighbour as well. If the
6320 * @a mtu is too small, generates and error for the @a pm 6805 * @a mtu is too small, generates and error for the @a pm
6321 * and returns NULL. 6806 * and returns NULL.
6322 * 6807 *
6808 * @param queue which queue to fragment for
6809 * @param dvh path the message will take, or NULL
6323 * @param pm pending message to fragment for transmission 6810 * @param pm pending message to fragment for transmission
6324 * @param mtu MTU to apply
6325 * @return new message to transmit 6811 * @return new message to transmit
6326 */ 6812 */
6327static struct PendingMessage * 6813static struct PendingMessage *
6328fragment_message (struct PendingMessage *pm, uint16_t mtu) 6814fragment_message (struct Queue *queue,
6815 struct DistanceVectorHop *dvh,
6816 struct PendingMessage *pm)
6329{ 6817{
6818 struct PendingAcknowledgement *pa;
6330 struct PendingMessage *ff; 6819 struct PendingMessage *ff;
6820 uint16_t mtu;
6331 6821
6822 pa = prepare_pending_acknowledgement (queue, dvh, pm);
6823 mtu = (0 == queue->mtu)
6824 ? UINT16_MAX - sizeof (struct GNUNET_TRANSPORT_SendMessageTo)
6825 : queue->mtu;
6332 set_pending_message_uuid (pm); 6826 set_pending_message_uuid (pm);
6333 6827
6334 /* This invariant is established in #handle_add_queue_message() */ 6828 /* This invariant is established in #handle_add_queue_message() */
6335 GNUNET_assert (mtu > sizeof (struct TransportFragmentBox)); 6829 GNUNET_assert (mtu > sizeof (struct TransportFragmentBoxMessage));
6336 6830
6337 /* select fragment for transmission, descending the tree if it has 6831 /* select fragment for transmission, descending the tree if it has
6338 been expanded until we are at a leaf or at a fragment that is small enough 6832 been expanded until we are at a leaf or at a fragment that is small
6833 enough
6339 */ 6834 */
6340 ff = pm; 6835 ff = pm;
6341 while (((ff->bytes_msg > mtu) || (pm == ff)) && 6836 while (((ff->bytes_msg > mtu) || (pm == ff)) &&
@@ -6348,7 +6843,7 @@ fragment_message (struct PendingMessage *pm, uint16_t mtu)
6348 { 6843 {
6349 /* Did not yet calculate all fragments, calculate next fragment */ 6844 /* Did not yet calculate all fragments, calculate next fragment */
6350 struct PendingMessage *frag; 6845 struct PendingMessage *frag;
6351 struct TransportFragmentBox tfb; 6846 struct TransportFragmentBoxMessage tfb;
6352 const char *orig; 6847 const char *orig;
6353 char *msg; 6848 char *msg;
6354 uint16_t fragmax; 6849 uint16_t fragmax;
@@ -6360,26 +6855,28 @@ fragment_message (struct PendingMessage *pm, uint16_t mtu)
6360 msize = ff->bytes_msg; 6855 msize = ff->bytes_msg;
6361 if (pm != ff) 6856 if (pm != ff)
6362 { 6857 {
6363 const struct TransportFragmentBox *tfbo; 6858 const struct TransportFragmentBoxMessage *tfbo;
6364 6859
6365 tfbo = (const struct TransportFragmentBox *) orig; 6860 tfbo = (const struct TransportFragmentBoxMessage *) orig;
6366 orig += sizeof (struct TransportFragmentBox); 6861 orig += sizeof (struct TransportFragmentBoxMessage);
6367 msize -= sizeof (struct TransportFragmentBox); 6862 msize -= sizeof (struct TransportFragmentBoxMessage);
6368 xoff = ntohs (tfbo->frag_off); 6863 xoff = ntohs (tfbo->frag_off);
6369 } 6864 }
6370 fragmax = mtu - sizeof (struct TransportFragmentBox); 6865 fragmax = mtu - sizeof (struct TransportFragmentBoxMessage);
6371 fragsize = GNUNET_MIN (msize - ff->frag_off, fragmax); 6866 fragsize = GNUNET_MIN (msize - ff->frag_off, fragmax);
6372 frag = GNUNET_malloc (sizeof (struct PendingMessage) + 6867 frag =
6373 sizeof (struct TransportFragmentBox) + fragsize); 6868 GNUNET_malloc (sizeof (struct PendingMessage) +
6869 sizeof (struct TransportFragmentBoxMessage) + fragsize);
6374 frag->target = pm->target; 6870 frag->target = pm->target;
6375 frag->frag_parent = ff; 6871 frag->frag_parent = ff;
6376 frag->timeout = pm->timeout; 6872 frag->timeout = pm->timeout;
6377 frag->bytes_msg = sizeof (struct TransportFragmentBox) + fragsize; 6873 frag->bytes_msg = sizeof (struct TransportFragmentBoxMessage) + fragsize;
6378 frag->pmt = PMT_FRAGMENT_BOX; 6874 frag->pmt = PMT_FRAGMENT_BOX;
6379 msg = (char *) &frag[1]; 6875 msg = (char *) &frag[1];
6380 tfb.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT); 6876 tfb.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT);
6381 tfb.header.size = htons (sizeof (struct TransportFragmentBox) + fragsize); 6877 tfb.header.size =
6382 tfb.frag_uuid = htonl (pm->frag_uuidgen++); 6878 htons (sizeof (struct TransportFragmentBoxMessage) + fragsize);
6879 tfb.ack_uuid = pa->ack_uuid;
6383 tfb.msg_uuid = pm->msg_uuid; 6880 tfb.msg_uuid = pm->msg_uuid;
6384 tfb.frag_off = htons (ff->frag_off + xoff); 6881 tfb.frag_off = htons (ff->frag_off + xoff);
6385 tfb.msg_size = htons (pm->bytes_msg); 6882 tfb.msg_size = htons (pm->bytes_msg);
@@ -6410,13 +6907,18 @@ fragment_message (struct PendingMessage *pm, uint16_t mtu)
6410 * @a pm). If the @a pm is already fragmented or reliability boxed, 6907 * @a pm). If the @a pm is already fragmented or reliability boxed,
6411 * or itself an ACK, this function simply returns @a pm. 6908 * or itself an ACK, this function simply returns @a pm.
6412 * 6909 *
6910 * @param queue which queue to prepare transmission for
6911 * @param dvh path the message will take, or NULL
6413 * @param pm pending message to box for transmission over unreliabile queue 6912 * @param pm pending message to box for transmission over unreliabile queue
6414 * @return new message to transmit 6913 * @return new message to transmit
6415 */ 6914 */
6416static struct PendingMessage * 6915static struct PendingMessage *
6417reliability_box_message (struct PendingMessage *pm) 6916reliability_box_message (struct Queue *queue,
6917 struct DistanceVectorHop *dvh,
6918 struct PendingMessage *pm)
6418{ 6919{
6419 struct TransportReliabilityBox rbox; 6920 struct TransportReliabilityBoxMessage rbox;
6921 struct PendingAcknowledgement *pa;
6420 struct PendingMessage *bpm; 6922 struct PendingMessage *bpm;
6421 char *msg; 6923 char *msg;
6422 6924
@@ -6433,6 +6935,8 @@ reliability_box_message (struct PendingMessage *pm)
6433 client_send_response (pm, GNUNET_NO, 0); 6935 client_send_response (pm, GNUNET_NO, 0);
6434 return NULL; 6936 return NULL;
6435 } 6937 }
6938 pa = prepare_pending_acknowledgement (queue, dvh, pm);
6939
6436 bpm = GNUNET_malloc (sizeof (struct PendingMessage) + sizeof (rbox) + 6940 bpm = GNUNET_malloc (sizeof (struct PendingMessage) + sizeof (rbox) +
6437 pm->bytes_msg); 6941 pm->bytes_msg);
6438 bpm->target = pm->target; 6942 bpm->target = pm->target;
@@ -6445,7 +6949,8 @@ reliability_box_message (struct PendingMessage *pm)
6445 rbox.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX); 6949 rbox.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX);
6446 rbox.header.size = htons (sizeof (rbox) + pm->bytes_msg); 6950 rbox.header.size = htons (sizeof (rbox) + pm->bytes_msg);
6447 rbox.ack_countdown = htonl (0); // FIXME: implement ACK countdown support 6951 rbox.ack_countdown = htonl (0); // FIXME: implement ACK countdown support
6448 rbox.msg_uuid = pm->msg_uuid; 6952
6953 rbox.ack_uuid = pa->ack_uuid;
6449 msg = (char *) &bpm[1]; 6954 msg = (char *) &bpm[1];
6450 memcpy (msg, &rbox, sizeof (rbox)); 6955 memcpy (msg, &rbox, sizeof (rbox));
6451 memcpy (&msg[sizeof (rbox)], &pm[1], pm->bytes_msg); 6956 memcpy (&msg[sizeof (rbox)], &pm[1], pm->bytes_msg);
@@ -6542,7 +7047,7 @@ transmit_on_queue (void *cls)
6542 return; /* do it later */ 7047 return; /* do it later */
6543 overhead = 0; 7048 overhead = 0;
6544 if (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc) 7049 if (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc)
6545 overhead += sizeof (struct TransportReliabilityBox); 7050 overhead += sizeof (struct TransportReliabilityBoxMessage);
6546 s = pm; 7051 s = pm;
6547 if ( ( (0 != queue->mtu) && 7052 if ( ( (0 != queue->mtu) &&
6548 (pm->bytes_msg + overhead > queue->mtu) ) || 7053 (pm->bytes_msg + overhead > queue->mtu) ) ||
@@ -6550,11 +7055,7 @@ transmit_on_queue (void *cls)
6550 (NULL != pm->head_frag /* fragments already exist, should 7055 (NULL != pm->head_frag /* fragments already exist, should
6551 respect that even if MTU is 0 for 7056 respect that even if MTU is 0 for
6552 this queue */) ) 7057 this queue */) )
6553 s = fragment_message (s, 7058 s = fragment_message (queue, NULL /*FIXME! */, s);
6554 (0 == queue->mtu)
6555 ? UINT16_MAX -
6556 sizeof (struct GNUNET_TRANSPORT_SendMessageTo)
6557 : queue->mtu);
6558 if (NULL == s) 7059 if (NULL == s)
6559 { 7060 {
6560 /* Fragmentation failed, try next message... */ 7061 /* Fragmentation failed, try next message... */
@@ -6562,7 +7063,7 @@ transmit_on_queue (void *cls)
6562 return; 7063 return;
6563 } 7064 }
6564 if (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc) 7065 if (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc)
6565 s = reliability_box_message (s); 7066 s = reliability_box_message (queue, NULL /* FIXME! */, s);
6566 if (NULL == s) 7067 if (NULL == s)
6567 { 7068 {
6568 /* Reliability boxing failed, try next message... */ 7069 /* Reliability boxing failed, try next message... */
@@ -6628,7 +7129,8 @@ transmit_on_queue (void *cls)
6628 message urgency and size when delaying ACKs, etc.) */ 7129 message urgency and size when delaying ACKs, etc.) */
6629 update_pm_next_attempt (s, 7130 update_pm_next_attempt (s,
6630 GNUNET_TIME_relative_to_absolute ( 7131 GNUNET_TIME_relative_to_absolute (
6631 GNUNET_TIME_relative_multiply (queue->rtt, 4))); 7132 GNUNET_TIME_relative_multiply (queue->pd.aged_rtt,
7133 4)));
6632 } 7134 }
6633 7135
6634 /* finally, re-schedule queue transmission task itself */ 7136 /* finally, re-schedule queue transmission task itself */
@@ -6865,7 +7367,7 @@ notify_client_queues (void *cls,
6865 for (struct Queue *q = neighbour->queue_head; NULL != q; 7367 for (struct Queue *q = neighbour->queue_head; NULL != q;
6866 q = q->next_neighbour) 7368 q = q->next_neighbour)
6867 { 7369 {
6868 struct MonitorEvent me = {.rtt = q->rtt, 7370 struct MonitorEvent me = {.rtt = q->pd.aged_rtt,
6869 .cs = q->cs, 7371 .cs = q->cs,
6870 .num_msg_pending = q->num_msg_pending, 7372 .num_msg_pending = q->num_msg_pending,
6871 .num_bytes_pending = q->num_bytes_pending}; 7373 .num_bytes_pending = q->num_bytes_pending};
@@ -6986,7 +7488,7 @@ suggest_to_connect (const struct GNUNET_PeerIdentity *pid, const char *address)
6986static void 7488static void
6987validation_transmit_on_queue (struct Queue *q, struct ValidationState *vs) 7489validation_transmit_on_queue (struct Queue *q, struct ValidationState *vs)
6988{ 7490{
6989 struct TransportValidationChallenge tvc; 7491 struct TransportValidationChallengeMessage tvc;
6990 7492
6991 vs->last_challenge_use = GNUNET_TIME_absolute_get (); 7493 vs->last_challenge_use = GNUNET_TIME_absolute_get ();
6992 tvc.header.type = 7494 tvc.header.type =
@@ -7099,7 +7601,7 @@ check_connection_quality (void *cls,
7099 ctx->q = q; 7601 ctx->q = q;
7100 /* OPTIMIZE-FIXME: in the future, add reliability / goodput 7602 /* OPTIMIZE-FIXME: in the future, add reliability / goodput
7101 statistics and consider those as well here? */ 7603 statistics and consider those as well here? */
7102 if (q->rtt.rel_value_us < DV_QUALITY_RTT_THRESHOLD.rel_value_us) 7604 if (q->pd.aged_rtt.rel_value_us < DV_QUALITY_RTT_THRESHOLD.rel_value_us)
7103 do_inc = GNUNET_YES; 7605 do_inc = GNUNET_YES;
7104 } 7606 }
7105 if (GNUNET_YES == do_inc) 7607 if (GNUNET_YES == do_inc)
@@ -7124,7 +7626,7 @@ start_dv_learn (void *cls)
7124{ 7626{
7125 struct LearnLaunchEntry *lle; 7627 struct LearnLaunchEntry *lle;
7126 struct QueueQualityContext qqc; 7628 struct QueueQualityContext qqc;
7127 struct TransportDVLearn dvl; 7629 struct TransportDVLearnMessage dvl;
7128 7630
7129 (void) cls; 7631 (void) cls;
7130 dvlearn_task = NULL; 7632 dvlearn_task = NULL;
@@ -7153,7 +7655,7 @@ start_dv_learn (void *cls)
7153 lle = lle_tail; 7655 lle = lle_tail;
7154 GNUNET_assert (GNUNET_YES == 7656 GNUNET_assert (GNUNET_YES ==
7155 GNUNET_CONTAINER_multishortmap_remove (dvlearn_map, 7657 GNUNET_CONTAINER_multishortmap_remove (dvlearn_map,
7156 &lle->challenge, 7658 &lle->challenge.value,
7157 lle)); 7659 lle));
7158 GNUNET_CONTAINER_DLL_remove (lle_head, lle_tail, lle); 7660 GNUNET_CONTAINER_DLL_remove (lle_head, lle_tail, lle);
7159 GNUNET_free (lle); 7661 GNUNET_free (lle);
@@ -7167,7 +7669,7 @@ start_dv_learn (void *cls)
7167 GNUNET_break (GNUNET_YES == 7669 GNUNET_break (GNUNET_YES ==
7168 GNUNET_CONTAINER_multishortmap_put ( 7670 GNUNET_CONTAINER_multishortmap_put (
7169 dvlearn_map, 7671 dvlearn_map,
7170 &lle->challenge, 7672 &lle->challenge.value,
7171 lle, 7673 lle,
7172 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); 7674 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
7173 dvl.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN); 7675 dvl.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN);
@@ -7255,7 +7757,7 @@ handle_add_queue_message (void *cls,
7255 const char *addr; 7757 const char *addr;
7256 uint16_t addr_len; 7758 uint16_t addr_len;
7257 7759
7258 if (ntohl (aqm->mtu) <= sizeof (struct TransportFragmentBox)) 7760 if (ntohl (aqm->mtu) <= sizeof (struct TransportFragmentBoxMessage))
7259 { 7761 {
7260 /* MTU so small as to be useless for transmissions, 7762 /* MTU so small as to be useless for transmissions,
7261 required for #fragment_message()! */ 7763 required for #fragment_message()! */
@@ -7282,7 +7784,7 @@ handle_add_queue_message (void *cls,
7282 queue = GNUNET_malloc (sizeof (struct Queue) + addr_len); 7784 queue = GNUNET_malloc (sizeof (struct Queue) + addr_len);
7283 queue->tc = tc; 7785 queue->tc = tc;
7284 queue->address = (const char *) &queue[1]; 7786 queue->address = (const char *) &queue[1];
7285 queue->rtt = GNUNET_TIME_UNIT_FOREVER_REL; 7787 queue->pd.aged_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
7286 queue->qid = aqm->qid; 7788 queue->qid = aqm->qid;
7287 queue->mtu = ntohl (aqm->mtu); 7789 queue->mtu = ntohl (aqm->mtu);
7288 queue->nt = (enum GNUNET_NetworkType) ntohl (aqm->nt); 7790 queue->nt = (enum GNUNET_NetworkType) ntohl (aqm->nt);
@@ -7305,7 +7807,7 @@ handle_add_queue_message (void *cls,
7305 memcpy (&queue[1], addr, addr_len); 7807 memcpy (&queue[1], addr, addr_len);
7306 /* notify monitors about new queue */ 7808 /* notify monitors about new queue */
7307 { 7809 {
7308 struct MonitorEvent me = {.rtt = queue->rtt, .cs = queue->cs}; 7810 struct MonitorEvent me = {.rtt = queue->pd.aged_rtt, .cs = queue->cs};
7309 7811
7310 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me); 7812 notify_monitors (&neighbour->pid, queue->address, queue->nt, &me);
7311 } 7813 }
@@ -7361,8 +7863,8 @@ handle_queue_create_ok (void *cls,
7361 7863
7362 7864
7363/** 7865/**
7364 * Communicator tells us that our request to create a queue failed. This usually 7866 * Communicator tells us that our request to create a queue failed. This
7365 * indicates that the provided address is simply invalid or that the 7867 * usually indicates that the provided address is simply invalid or that the
7366 * communicator's resources are exhausted. 7868 * communicator's resources are exhausted.
7367 * 7869 *
7368 * @param cls the `struct TransportClient` 7870 * @param cls the `struct TransportClient`
@@ -7655,7 +8157,8 @@ handle_address_consider_verify (
7655 (void) cls; 8157 (void) cls;
7656 // OPTIMIZE-FIXME: checking that we know this address already should 8158 // OPTIMIZE-FIXME: checking that we know this address already should
7657 // be done BEFORE checking the signature => HELLO API change! 8159 // be done BEFORE checking the signature => HELLO API change!
7658 // OPTIMIZE-FIXME: pre-check: rate-limit signature verification / validation?! 8160 // OPTIMIZE-FIXME: pre-check: rate-limit signature verification /
8161 // validation?!
7659 address = 8162 address =
7660 GNUNET_HELLO_extract_address (&hdr[1], 8163 GNUNET_HELLO_extract_address (&hdr[1],
7661 ntohs (hdr->header.size) - sizeof (*hdr), 8164 ntohs (hdr->header.size) - sizeof (*hdr),
@@ -7803,6 +8306,50 @@ free_validation_state_cb (void *cls,
7803 8306
7804 8307
7805/** 8308/**
8309 * Free pending acknowledgement.
8310 *
8311 * @param cls NULL
8312 * @param key unused
8313 * @param value a `struct PendingAcknowledgement`
8314 * @return #GNUNET_OK (always)
8315 */
8316static int
8317free_pending_ack_cb (void *cls,
8318 const struct GNUNET_ShortHashCode *key,
8319 void *value)
8320{
8321 struct PendingAcknowledgement *pa = value;
8322
8323 (void) cls;
8324 (void) key;
8325 free_pending_acknowledgement (pa);
8326 return GNUNET_OK;
8327}
8328
8329
8330/**
8331 * Free acknowledgement cummulator.
8332 *
8333 * @param cls NULL
8334 * @param pid unused
8335 * @param value a `struct AcknowledgementCummulator`
8336 * @return #GNUNET_OK (always)
8337 */
8338static int
8339free_ack_cummulator_cb (void *cls,
8340 const struct GNUNET_PeerIdentity *pid,
8341 void *value)
8342{
8343 struct AcknowledgementCummulator *ac = value;
8344
8345 (void) cls;
8346 (void) pid;
8347 GNUNET_free (ac);
8348 return GNUNET_OK;
8349}
8350
8351
8352/**
7806 * Function called when the service shuts down. Unloads our plugins 8353 * Function called when the service shuts down. Unloads our plugins
7807 * and cancels pending validations. 8354 * and cancels pending validations.
7808 * 8355 *
@@ -7835,6 +8382,16 @@ do_shutdown (void *cls)
7835 GNUNET_free (GST_my_private_key); 8382 GNUNET_free (GST_my_private_key);
7836 GST_my_private_key = NULL; 8383 GST_my_private_key = NULL;
7837 } 8384 }
8385 GNUNET_CONTAINER_multipeermap_iterate (ack_cummulators,
8386 &free_ack_cummulator_cb,
8387 NULL);
8388 GNUNET_CONTAINER_multipeermap_destroy (ack_cummulators);
8389 ack_cummulators = NULL;
8390 GNUNET_CONTAINER_multishortmap_iterate (pending_acks,
8391 &free_pending_ack_cb,
8392 NULL);
8393 GNUNET_CONTAINER_multishortmap_destroy (pending_acks);
8394 pending_acks = NULL;
7838 GNUNET_CONTAINER_multipeermap_destroy (neighbours); 8395 GNUNET_CONTAINER_multipeermap_destroy (neighbours);
7839 neighbours = NULL; 8396 neighbours = NULL;
7840 GNUNET_CONTAINER_multipeermap_iterate (backtalkers, 8397 GNUNET_CONTAINER_multipeermap_iterate (backtalkers,
@@ -7886,6 +8443,8 @@ run (void *cls,
7886 /* setup globals */ 8443 /* setup globals */
7887 GST_cfg = c; 8444 GST_cfg = c;
7888 backtalkers = GNUNET_CONTAINER_multipeermap_create (16, GNUNET_YES); 8445 backtalkers = GNUNET_CONTAINER_multipeermap_create (16, GNUNET_YES);
8446 pending_acks = GNUNET_CONTAINER_multishortmap_create (32768, GNUNET_YES);
8447 ack_cummulators = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_YES);
7889 neighbours = GNUNET_CONTAINER_multipeermap_create (1024, GNUNET_YES); 8448 neighbours = GNUNET_CONTAINER_multipeermap_create (1024, GNUNET_YES);
7890 dv_routes = GNUNET_CONTAINER_multipeermap_create (1024, GNUNET_YES); 8449 dv_routes = GNUNET_CONTAINER_multipeermap_create (1024, GNUNET_YES);
7891 ephemeral_map = GNUNET_CONTAINER_multipeermap_create (32, GNUNET_YES); 8450 ephemeral_map = GNUNET_CONTAINER_multipeermap_create (32, GNUNET_YES);