diff options
author | Christian Grothoff <christian@grothoff.org> | 2019-01-21 20:15:27 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2019-01-21 20:15:27 +0100 |
commit | 25b14e096d09acfee96219de359ecaa0b56e2a34 (patch) | |
tree | 773192bc2baf260f946b16b75da16e93fc927140 /src/transport | |
parent | 32b38707097f8dc9f7f39c526f67414f24283eca (diff) | |
download | gnunet-25b14e096d09acfee96219de359ecaa0b56e2a34.tar.gz gnunet-25b14e096d09acfee96219de359ecaa0b56e2a34.zip |
work out fragment/ack/dv messages, start implementation (tng)
Diffstat (limited to 'src/transport')
-rw-r--r-- | src/transport/gnunet-service-tng.c | 338 |
1 files changed, 329 insertions, 9 deletions
diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c index e205fa3d7..3365ea5d5 100644 --- a/src/transport/gnunet-service-tng.c +++ b/src/transport/gnunet-service-tng.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2010-2016, 2018 GNUnet e.V. | 3 | Copyright (C) 2010-2016, 2018, 2019 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software: you can redistribute it and/or modify it | 5 | GNUnet is free software: you can redistribute it and/or modify it |
6 | under the terms of the GNU Affero General Public License as published | 6 | under the terms of the GNU Affero General Public License as published |
@@ -182,6 +182,7 @@ struct EphemeralConfirmation | |||
182 | 182 | ||
183 | }; | 183 | }; |
184 | 184 | ||
185 | |||
185 | /** | 186 | /** |
186 | * Plaintext of the variable-size payload that is encrypted | 187 | * Plaintext of the variable-size payload that is encrypted |
187 | * within a `struct TransportBackchannelEncapsulationMessage` | 188 | * within a `struct TransportBackchannelEncapsulationMessage` |
@@ -225,6 +226,236 @@ struct TransportBackchannelRequestPayload | |||
225 | 226 | ||
226 | }; | 227 | }; |
227 | 228 | ||
229 | |||
230 | /** | ||
231 | * Outer layer of an encapsulated unfragmented application message sent | ||
232 | * over an unreliable channel. | ||
233 | */ | ||
234 | struct TransportReliabilityBox | ||
235 | { | ||
236 | /** | ||
237 | * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX | ||
238 | */ | ||
239 | struct GNUNET_MessageHeader header; | ||
240 | |||
241 | /** | ||
242 | * Number of messages still to be sent before a commulative | ||
243 | * ACK is requested. Zero if an ACK is requested immediately. | ||
244 | * In NBO. Note that the receiver may send the ACK faster | ||
245 | * if it believes that is reasonable. | ||
246 | */ | ||
247 | uint32_t ack_countdown GNUNET_PACKED; | ||
248 | |||
249 | /** | ||
250 | * Unique ID of the message used for signalling receipt of | ||
251 | * messages sent over possibly unreliable channels. Should | ||
252 | * be a random. | ||
253 | */ | ||
254 | struct GNUNET_ShortHashCode msg_uuid; | ||
255 | }; | ||
256 | |||
257 | |||
258 | /** | ||
259 | * Confirmation that the receiver got a | ||
260 | * #GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_BOX. Note that the | ||
261 | * confirmation may be transmitted over a completely different queue, | ||
262 | * so ACKs are identified by a combination of PID of sender and | ||
263 | * message UUID, without the queue playing any role! | ||
264 | */ | ||
265 | struct TransportReliabilityAckMessage | ||
266 | { | ||
267 | /** | ||
268 | * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK | ||
269 | */ | ||
270 | struct GNUNET_MessageHeader header; | ||
271 | |||
272 | /** | ||
273 | * Reserved. Zero. | ||
274 | */ | ||
275 | uint32_t reserved GNUNET_PACKED; | ||
276 | |||
277 | /** | ||
278 | * How long was the ACK delayed relative to the average time of | ||
279 | * receipt of the messages being acknowledged? Used to calculate | ||
280 | * the average RTT by taking the receipt time of the ack minus the | ||
281 | * average transmission time of the sender minus this value. | ||
282 | */ | ||
283 | struct GNUNET_TIME_RelativeNBO avg_ack_delay; | ||
284 | |||
285 | /* followed by any number of `struct GNUNET_ShortHashCode` | ||
286 | messages providing ACKs */ | ||
287 | }; | ||
288 | |||
289 | |||
290 | /** | ||
291 | * Outer layer of an encapsulated fragmented application message. | ||
292 | */ | ||
293 | struct TransportFragmentBox | ||
294 | { | ||
295 | /** | ||
296 | * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT | ||
297 | */ | ||
298 | struct GNUNET_MessageHeader header; | ||
299 | |||
300 | /** | ||
301 | * Unique ID of this fragment (and fragment transmission!). Will | ||
302 | * change even if a fragement is retransmitted to make each | ||
303 | * transmission attempt unique! Should be incremented by one for | ||
304 | * each fragment transmission. If a client receives a duplicate | ||
305 | * fragment (same @e frag_off), it must send | ||
306 | * #GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT_ACK immediately. | ||
307 | */ | ||
308 | uint32_t frag_uuid GNUNET_PACKED; | ||
309 | |||
310 | /** | ||
311 | * Original message ID for of the message that all the1 | ||
312 | * fragments belong to. Must be the same for all fragments. | ||
313 | */ | ||
314 | struct GNUNET_ShortHashCode msg_uuid; | ||
315 | |||
316 | /** | ||
317 | * Offset of this fragment in the overall message. | ||
318 | */ | ||
319 | uint16_t frag_off GNUNET_PACKED; | ||
320 | |||
321 | /** | ||
322 | * Total size of the message that is being fragmented. | ||
323 | */ | ||
324 | uint16_t msg_size GNUNET_PACKED; | ||
325 | |||
326 | }; | ||
327 | |||
328 | |||
329 | /** | ||
330 | * Outer layer of an fragmented application message sent over a queue | ||
331 | * with finite MTU. When a #GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT is | ||
332 | * received, the receiver has two RTTs or 64 further fragments with | ||
333 | * the same basic message time to send an acknowledgement, possibly | ||
334 | * acknowledging up to 65 fragments in one ACK. ACKs must also be | ||
335 | * sent immediately once all fragments were sent. | ||
336 | */ | ||
337 | struct TransportFragmentAckMessage | ||
338 | { | ||
339 | /** | ||
340 | * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT_ACK | ||
341 | */ | ||
342 | struct GNUNET_MessageHeader header; | ||
343 | |||
344 | /** | ||
345 | * Unique ID of the lowest fragment UUID being acknowledged. | ||
346 | */ | ||
347 | uint32_t frag_uuid GNUNET_PACKED; | ||
348 | |||
349 | /** | ||
350 | * Bitfield of up to 64 additional fragments following the | ||
351 | * @e msg_uuid being acknowledged by this message. | ||
352 | */ | ||
353 | uint64_t extra_acks GNUNET_PACKED; | ||
354 | |||
355 | /** | ||
356 | * Original message ID for of the message that all the | ||
357 | * fragments belong to. | ||
358 | */ | ||
359 | struct GNUNET_ShortHashCode msg_uuid; | ||
360 | |||
361 | /** | ||
362 | * How long was the ACK delayed relative to the average time of | ||
363 | * receipt of the fragments being acknowledged? Used to calculate | ||
364 | * the average RTT by taking the receipt time of the ack minus the | ||
365 | * average transmission time of the sender minus this value. | ||
366 | */ | ||
367 | struct GNUNET_TIME_RelativeNBO avg_ack_delay; | ||
368 | }; | ||
369 | |||
370 | |||
371 | /** | ||
372 | * Internal message used by transport for distance vector learning. | ||
373 | * If @e num_hops does not exceed the threshold, peers should append | ||
374 | * themselves to the peer list and flood the message (possibly only | ||
375 | * to a subset of their neighbours to limit discoverability of the | ||
376 | * network topology). To the extend that the @e bidirectional bits | ||
377 | * are set, peers may learn the inverse paths even if they did not | ||
378 | * initiate. | ||
379 | * | ||
380 | * Unless received on a bidirectional queue and @e num_hops just | ||
381 | * zero, peers that can forward to the initator should always try to | ||
382 | * forward to the initiator. | ||
383 | */ | ||
384 | struct TransportDVLearn | ||
385 | { | ||
386 | /** | ||
387 | * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_DV_LEARN | ||
388 | */ | ||
389 | struct GNUNET_MessageHeader header; | ||
390 | |||
391 | /** | ||
392 | * Number of hops this messages has travelled, in NBO. Zero if | ||
393 | * sent by initiator. | ||
394 | */ | ||
395 | uint16_t num_hops GNUNET_PACKED; | ||
396 | |||
397 | /** | ||
398 | * Bitmask of the last 16 hops indicating whether they are confirmed | ||
399 | * available (without DV) in both directions or not, in NBO. Used | ||
400 | * to possibly instantly learn a path in both directions. Each peer | ||
401 | * should shift this value by one to the left, and then set the | ||
402 | * lowest bit IF the current sender can be reached from it (without | ||
403 | * DV routing). | ||
404 | */ | ||
405 | uint16_t bidirectional GNUNET_PACKED; | ||
406 | |||
407 | /** | ||
408 | * Peers receiving this message and delaying forwarding to other | ||
409 | * peers for any reason should increment this value such as to | ||
410 | * enable the origin to determine the actual network-only delay | ||
411 | * in addition to the real-time delay (assuming the message loops | ||
412 | * back to the origin). | ||
413 | */ | ||
414 | struct GNUNET_TIME_Relative cummulative_non_network_delay; | ||
415 | |||
416 | /** | ||
417 | * Identity of the peer that started this learning activity. | ||
418 | */ | ||
419 | struct GNUNET_PeerIdentity initiator; | ||
420 | |||
421 | /* Followed by @e num_hops `struct GNUNET_PeerIdentity` values, | ||
422 | excluding the initiator of the DV trace; the last entry is the | ||
423 | current sender; the current peer must not be included except if | ||
424 | it is the sender. */ | ||
425 | |||
426 | }; | ||
427 | |||
428 | |||
429 | /** | ||
430 | * Outer layer of an encapsulated message send over multiple hops. | ||
431 | */ | ||
432 | struct TransportDVBox | ||
433 | { | ||
434 | /** | ||
435 | * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_DV | ||
436 | */ | ||
437 | struct GNUNET_MessageHeader header; | ||
438 | |||
439 | /** | ||
440 | * Number of hops this messages includes. In NBO. | ||
441 | */ | ||
442 | uint16_t num_hops GNUNET_PACKED; | ||
443 | |||
444 | /** | ||
445 | * Position of our peer in the sequence. | ||
446 | * To be incremented at each hop. In NBO. | ||
447 | */ | ||
448 | uint16_t current_hop GNUNET_PACKED; | ||
449 | |||
450 | /* Followed by @e num_hops `struct GNUNET_PeerIdentity` values; | ||
451 | the first is the sender, the last the receiver; the current | ||
452 | peer may be one in the middle. */ | ||
453 | |||
454 | /* Followed by the actual message, which itself may be | ||
455 | another box, but not a DV_LEARN message! */ | ||
456 | }; | ||
457 | |||
458 | |||
228 | GNUNET_NETWORK_STRUCT_END | 459 | GNUNET_NETWORK_STRUCT_END |
229 | 460 | ||
230 | 461 | ||
@@ -1780,6 +2011,68 @@ schedule_transmit_on_queue (struct GNUNET_ATS_Session *queue) | |||
1780 | 2011 | ||
1781 | 2012 | ||
1782 | /** | 2013 | /** |
2014 | * Fragment the given @a pm to the given @a mtu. Adds | ||
2015 | * additional fragments to the neighbour as well. If the | ||
2016 | * @a mtu is too small, generates and error for the @a pm | ||
2017 | * and returns NULL. | ||
2018 | * | ||
2019 | * @param pm pending message to fragment for transmission | ||
2020 | * @param mtu MTU to apply | ||
2021 | * @return new message to transmit | ||
2022 | */ | ||
2023 | static struct PendingMessage * | ||
2024 | fragment_message (struct PendingMessage *pm, | ||
2025 | uint16_t mtu) | ||
2026 | { | ||
2027 | if (0) | ||
2028 | { | ||
2029 | /* mtu too small */ | ||
2030 | // FIMXE: bitch | ||
2031 | client_send_response (pm, | ||
2032 | GNUNET_NO, | ||
2033 | 0); | ||
2034 | return NULL; | ||
2035 | } | ||
2036 | |||
2037 | /* FIXME: return first fragment here! */ | ||
2038 | return NULL; | ||
2039 | } | ||
2040 | |||
2041 | |||
2042 | /** | ||
2043 | * Reliability-box the given @a pm. On error (can there be any), NULL | ||
2044 | * may be returned, otherwise the "replacement" for @a pm (which | ||
2045 | * should then be added to the respective neighbour's queue instead of | ||
2046 | * @a pm). If the @a pm is already fragmented or reliability boxed, | ||
2047 | * or itself an ACK, this function simply returns @a pm. | ||
2048 | * | ||
2049 | * @param pm pending message to box for transmission over unreliabile queue | ||
2050 | * @return new message to transmit | ||
2051 | */ | ||
2052 | static struct PendingMessage * | ||
2053 | reliability_box_message (struct PendingMessage *pm) | ||
2054 | { | ||
2055 | if (0) // FIXME | ||
2056 | { | ||
2057 | /* already fragmented or reliability boxed, do nothing */ | ||
2058 | return pm; | ||
2059 | } | ||
2060 | if (0) // FIXME | ||
2061 | { | ||
2062 | /* failed hard */ | ||
2063 | // FIMXE: bitch | ||
2064 | client_send_response (pm, | ||
2065 | GNUNET_NO, | ||
2066 | 0); | ||
2067 | return NULL; | ||
2068 | } | ||
2069 | |||
2070 | /* FIXME: return boxed PM here! */ | ||
2071 | return NULL; | ||
2072 | } | ||
2073 | |||
2074 | |||
2075 | /** | ||
1783 | * We believe we are ready to transmit a message on a queue. Double-checks | 2076 | * We believe we are ready to transmit a message on a queue. Double-checks |
1784 | * with the queue's "tracker_out" and then gives the message to the | 2077 | * with the queue's "tracker_out" and then gives the message to the |
1785 | * communicator for transmission (updating the tracker, and re-scheduling | 2078 | * communicator for transmission (updating the tracker, and re-scheduling |
@@ -1793,6 +2086,7 @@ transmit_on_queue (void *cls) | |||
1793 | struct GNUNET_ATS_Session *queue = cls; | 2086 | struct GNUNET_ATS_Session *queue = cls; |
1794 | struct Neighbour *n = queue->neighbour; | 2087 | struct Neighbour *n = queue->neighbour; |
1795 | struct PendingMessage *pm; | 2088 | struct PendingMessage *pm; |
2089 | uint32_t overhead; | ||
1796 | 2090 | ||
1797 | queue->transmit_task = NULL; | 2091 | queue->transmit_task = NULL; |
1798 | if (NULL == (pm = n->pending_msg_head)) | 2092 | if (NULL == (pm = n->pending_msg_head)) |
@@ -1803,15 +2097,41 @@ transmit_on_queue (void *cls) | |||
1803 | schedule_transmit_on_queue (queue); | 2097 | schedule_transmit_on_queue (queue); |
1804 | if (NULL != queue->transmit_task) | 2098 | if (NULL != queue->transmit_task) |
1805 | return; /* do it later */ | 2099 | return; /* do it later */ |
2100 | overhead = 0; | ||
2101 | if (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc) | ||
2102 | overhead += sizeof (struct TransportReliabilityBox); | ||
2103 | if ( (0 != queue->mtu) && | ||
2104 | (pm->bytes_msg + overhead > queue->mtu) ) | ||
2105 | pm = fragment_message (pm, | ||
2106 | queue->mtu); | ||
2107 | if (NULL == pm) | ||
2108 | { | ||
2109 | /* Fragmentation failed, try next message... */ | ||
2110 | schedule_transmit_on_queue (queue); | ||
2111 | return; | ||
2112 | } | ||
2113 | if (GNUNET_TRANSPORT_CC_RELIABLE != queue->tc->details.communicator.cc) | ||
2114 | pm = reliability_box_message (pm); | ||
2115 | if (NULL == pm) | ||
2116 | { | ||
2117 | /* Reliability boxing failed, try next message... */ | ||
2118 | schedule_transmit_on_queue (queue); | ||
2119 | return; | ||
2120 | } | ||
2121 | |||
2122 | // FIXME: actually do transmission | ||
1806 | 2123 | ||
1807 | // FIXME: do transmission (fragmentation, adding signalling / RTT tracking logic, etc.) | 2124 | // FIXME: unless 'pm' is an ACK or control, move 'pm' back in the |
1808 | // FIXME: upon success, do (not here in continuation!) | 2125 | // transmission queue (simplistic: to the end, better: with position |
1809 | if (0) | 2126 | // depending on type, timeout, etc.) |
1810 | { | 2127 | |
1811 | client_send_response (pm, | 2128 | // FIXME: do something similar in defragmentation / reliability ACK handling! |
1812 | GNUNET_YES, | 2129 | if (GNUNET_TRANSPORT_CC_RELIABLE == queue->tc->details.communicator.cc) |
1813 | 0); | 2130 | { |
1814 | } | 2131 | client_send_response (pm, |
2132 | GNUNET_YES, | ||
2133 | pm->bytes_msg); | ||
2134 | } | ||
1815 | /* finally, re-schedule self */ | 2135 | /* finally, re-schedule self */ |
1816 | schedule_transmit_on_queue (queue); | 2136 | schedule_transmit_on_queue (queue); |
1817 | } | 2137 | } |