aboutsummaryrefslogtreecommitdiff
path: root/src/transport/gnunet-service-tng.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/transport/gnunet-service-tng.c')
-rw-r--r--src/transport/gnunet-service-tng.c623
1 files changed, 595 insertions, 28 deletions
diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c
index cb6fcebdc..ac4a262d7 100644
--- a/src/transport/gnunet-service-tng.c
+++ b/src/transport/gnunet-service-tng.c
@@ -33,8 +33,11 @@
33 * transport-to-transport traffic) 33 * transport-to-transport traffic)
34 * 34 *
35 * Implement: 35 * Implement:
36 * - manage defragmentation, retransmission, track RTT, loss, etc. 36 * - data structures for defragmentation
37 * - DV data structures, learning, forgetting, using them! 37 * - manage defragmentation
38 * - ACK handling / retransmission
39 * - track RTT, distance, loss, etc.
40 * - DV data structures, learning, forgetting & using them!
38 * 41 *
39 * Easy: 42 * Easy:
40 * - use ATS bandwidth allocation callback and schedule transmissions! 43 * - use ATS bandwidth allocation callback and schedule transmissions!
@@ -83,6 +86,7 @@
83#include "gnunet_peerstore_service.h" 86#include "gnunet_peerstore_service.h"
84#include "gnunet_hello_lib.h" 87#include "gnunet_hello_lib.h"
85#include "gnunet_ats_transport_service.h" 88#include "gnunet_ats_transport_service.h"
89#include "gnunet_signatures.h"
86#include "transport.h" 90#include "transport.h"
87 91
88 92
@@ -100,6 +104,16 @@
100#define DELAY_WARN_THRESHOLD GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) 104#define DELAY_WARN_THRESHOLD GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
101 105
102/** 106/**
107 * How long are ephemeral keys valid?
108 */
109#define EPHEMERAL_VALIDITY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
110
111/**
112 * How long do we keep partially reassembled messages around before giving up?
113 */
114#define REASSEMBLY_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 4)
115
116/**
103 * How many messages can we have pending for a given communicator 117 * How many messages can we have pending for a given communicator
104 * process before we start to throttle that communicator? 118 * process before we start to throttle that communicator?
105 * 119 *
@@ -169,8 +183,7 @@ struct TransportBackchannelEncapsulationMessage
169 183
170 184
171/** 185/**
172 * Body by which a peqer confirms that it is using an ephemeral 186 * Body by which a peer confirms that it is using an ephemeral key.
173 * key.
174 */ 187 */
175struct EphemeralConfirmation 188struct EphemeralConfirmation
176{ 189{
@@ -182,10 +195,24 @@ struct EphemeralConfirmation
182 195
183 /** 196 /**
184 * How long is this signature over the ephemeral key valid? 197 * How long is this signature over the ephemeral key valid?
198 * Note that the receiver MUST IGNORE the absolute time, and
199 * only interpret the value as a mononic time and reject
200 * "older" values than the last one observed. Even with this,
201 * there is no real guarantee against replay achieved here,
202 * as the latest timestamp is not persisted. This is
203 * necessary as we do not want to require synchronized
204 * clocks and may not have a bidirectional communication
205 * channel. Communicators must protect against replay
206 * attacks when using backchannel communication!
185 */ 207 */
186 struct GNUNET_TIME_AbsoluteNBO ephemeral_validity; 208 struct GNUNET_TIME_AbsoluteNBO ephemeral_validity;
187 209
188 /** 210 /**
211 * Target's peer identity.
212 */
213 struct GNUNET_PeerIdentity target;
214
215 /**
189 * Ephemeral key setup by the sender for @e target, used 216 * Ephemeral key setup by the sender for @e target, used
190 * to encrypt the payload. 217 * to encrypt the payload.
191 */ 218 */
@@ -376,6 +403,12 @@ struct TransportFragmentAckMessage
376 * average transmission time of the sender minus this value. 403 * average transmission time of the sender minus this value.
377 */ 404 */
378 struct GNUNET_TIME_RelativeNBO avg_ack_delay; 405 struct GNUNET_TIME_RelativeNBO avg_ack_delay;
406
407 /**
408 * How long until the receiver will stop trying reassembly
409 * of this message?
410 */
411 struct GNUNET_TIME_RelativeNBO reassembly_timeout;
379}; 412};
380 413
381 414
@@ -549,6 +582,11 @@ struct EphemeralCacheEntry
549 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key; 582 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
550 583
551 /** 584 /**
585 * Our private ephemeral key.
586 */
587 struct GNUNET_CRYPTO_EcdhePrivateKey private_key;
588
589 /**
552 * Node in the ephemeral cache for this entry. 590 * Node in the ephemeral cache for this entry.
553 * Used for expiration. 591 * Used for expiration.
554 */ 592 */
@@ -727,6 +765,96 @@ struct GNUNET_ATS_Session
727 765
728 766
729/** 767/**
768 * Information we keep for a message that we are reassembling.
769 */
770struct ReassemblyContext
771{
772
773 /**
774 * Original message ID for of the message that all the
775 * fragments belong to.
776 */
777 struct GNUNET_ShortHashCode msg_uuid;
778
779 /**
780 * Which neighbour is this context for?
781 */
782 struct Neighbour *neighbour;
783
784 /**
785 * Entry in the reassembly heap (sorted by expiration).
786 */
787 struct GNUNET_CONTAINER_HeapNode *hn;
788
789 /**
790 * Bitfield with @e msg_size bits representing the positions
791 * where we have received fragments. When we receive a fragment,
792 * we check the bits in @e bitfield before incrementing @e msg_missing.
793 *
794 * Allocated after the reassembled message.
795 */
796 uint8_t *bitfield;
797
798 /**
799 * Task for sending ACK. We may send ACKs either because of hitting
800 * the @e extra_acks limit, or based on time and @e num_acks. This
801 * task is for the latter case.
802 */
803 struct GNUNET_SCHEDULER_Task *ack_task;
804
805 /**
806 * At what time will we give up reassembly of this message?
807 */
808 struct GNUNET_TIME_Absolute reassembly_timeout;
809
810 /**
811 * Average delay of all acks in @e extra_acks and @e frag_uuid.
812 * Should be reset to zero when @e num_acks is set to 0.
813 */
814 struct GNUNET_TIME_Relative avg_ack_delay;
815
816 /**
817 * Time we received the last fragment. @e avg_ack_delay must be
818 * incremented by now - @e last_frag multiplied by @e num_acks.
819 */
820 struct GNUNET_TIME_Absolute last_frag;
821
822 /**
823 * Bitfield of up to 64 additional fragments following @e frag_uuid
824 * to be acknowledged in the next cummulative ACK.
825 */
826 uint64_t extra_acks;
827
828 /**
829 * Unique ID of the lowest fragment UUID to be acknowledged in the
830 * next cummulative ACK. Only valid if @e num_acks > 0.
831 */
832 uint32_t frag_uuid;
833
834 /**
835 * Number of ACKs we have accumulated so far. Reset to 0
836 * whenever we send a #GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT_ACK.
837 */
838 unsigned int num_acks;
839
840 /**
841 * How big is the message we are reassembling in total?
842 */
843 uint16_t msg_size;
844
845 /**
846 * How many bytes of the message are still missing? Defragmentation
847 * is complete when @e msg_missing == 0.
848 */
849 uint16_t msg_missing;
850
851 /* Followed by @e msg_size bytes of the (partially) defragmented original message */
852
853 /* Followed by @e bitfield data */
854};
855
856
857/**
730 * A neighbour that at least one communicator is connected to. 858 * A neighbour that at least one communicator is connected to.
731 */ 859 */
732struct Neighbour 860struct Neighbour
@@ -738,6 +866,25 @@ struct Neighbour
738 struct GNUNET_PeerIdentity pid; 866 struct GNUNET_PeerIdentity pid;
739 867
740 /** 868 /**
869 * Map with `struct ReassemblyContext` structs for fragments under
870 * reassembly. May be NULL if we currently have no fragments from
871 * this @e pid (lazy initialization).
872 */
873 struct GNUNET_CONTAINER_MultiShortmap *reassembly_map;
874
875 /**
876 * Heap with `struct ReassemblyContext` structs for fragments under
877 * reassembly. May be NULL if we currently have no fragments from
878 * this @e pid (lazy initialization).
879 */
880 struct GNUNET_CONTAINER_Heap *reassembly_heap;
881
882 /**
883 * Task to free old entries from the @e reassembly_heap and @e reassembly_map.
884 */
885 struct GNUNET_SCHEDULER_Task *reassembly_timeout_task;
886
887 /**
741 * Head of list of messages pending for this neighbour. 888 * Head of list of messages pending for this neighbour.
742 */ 889 */
743 struct PendingMessage *pending_msg_head; 890 struct PendingMessage *pending_msg_head;
@@ -1178,6 +1325,11 @@ static struct GNUNET_CONTAINER_Heap *ephemeral_heap;
1178static struct GNUNET_CONTAINER_MultiPeerMap *ephemeral_map; 1325static struct GNUNET_CONTAINER_MultiPeerMap *ephemeral_map;
1179 1326
1180/** 1327/**
1328 * Task to free expired ephemerals.
1329 */
1330static struct GNUNET_SCHEDULER_Task *ephemeral_task;
1331
1332/**
1181 * Our connection to ATS for allocation and bootstrapping. 1333 * Our connection to ATS for allocation and bootstrapping.
1182 */ 1334 */
1183static struct GNUNET_ATS_TransportHandle *ats; 1335static struct GNUNET_ATS_TransportHandle *ats;
@@ -1364,6 +1516,76 @@ client_connect_cb (void *cls,
1364 1516
1365 1517
1366/** 1518/**
1519 * Free @a rc
1520 *
1521 * @param rc data structure to free
1522 */
1523static void
1524free_reassembly_context (struct ReassemblyContext *rc)
1525{
1526 struct Neighbour *n = rc->neighbour;
1527
1528 GNUNET_assert (rc ==
1529 GNUNET_CONTAINER_heap_remove_node (rc->hn));
1530 GNUNET_assert (GNUNET_OK ==
1531 GNUNET_CONTAINER_multishortmap_remove (n->reassembly_map,
1532 &rc->msg_uuid,
1533 rc));
1534 GNUNET_free (rc);
1535}
1536
1537
1538/**
1539 * Task run to clean up reassembly context of a neighbour that have expired.
1540 *
1541 * @param cls a `struct Neighbour`
1542 */
1543static void
1544reassembly_cleanup_task (void *cls)
1545{
1546 struct Neighbour *n = cls;
1547 struct ReassemblyContext *rc;
1548
1549 n->reassembly_timeout_task = NULL;
1550 while (NULL != (rc = GNUNET_CONTAINER_heap_peek (n->reassembly_heap)))
1551 {
1552 if (0 == GNUNET_TIME_absolute_get_remaining (rc->reassembly_timeout).rel_value_us)
1553 {
1554 free_reassembly_context (rc);
1555 continue;
1556 }
1557 GNUNET_assert (NULL == n->reassembly_timeout_task);
1558 n->reassembly_timeout_task = GNUNET_SCHEDULER_add_at (rc->reassembly_timeout,
1559 &reassembly_cleanup_task,
1560 n);
1561 return;
1562 }
1563}
1564
1565
1566/**
1567 * function called to #free_reassembly_context().
1568 *
1569 * @param cls NULL
1570 * @param key unused
1571 * @param value a `struct ReassemblyContext` to free
1572 * @return #GNUNET_OK (continue iteration)
1573 */
1574static int
1575free_reassembly_cb (void *cls,
1576 const struct GNUNET_ShortHashCode *key,
1577 void *value)
1578{
1579 struct ReassemblyContext *rc = value;
1580 (void) cls;
1581 (void) key;
1582
1583 free_reassembly_context (rc);
1584 return GNUNET_OK;
1585}
1586
1587
1588/**
1367 * Release memory used by @a neighbour. 1589 * Release memory used by @a neighbour.
1368 * 1590 *
1369 * @param neighbour neighbour entry to free 1591 * @param neighbour neighbour entry to free
@@ -1378,6 +1600,18 @@ free_neighbour (struct Neighbour *neighbour)
1378 neighbour)); 1600 neighbour));
1379 if (NULL != neighbour->timeout_task) 1601 if (NULL != neighbour->timeout_task)
1380 GNUNET_SCHEDULER_cancel (neighbour->timeout_task); 1602 GNUNET_SCHEDULER_cancel (neighbour->timeout_task);
1603 if (NULL != neighbour->reassembly_map)
1604 {
1605 GNUNET_CONTAINER_multishortmap_iterate (neighbour->reassembly_map,
1606 &free_reassembly_cb,
1607 NULL);
1608 GNUNET_CONTAINER_multishortmap_destroy (neighbour->reassembly_map);
1609 neighbour->reassembly_map = NULL;
1610 GNUNET_CONTAINER_heap_destroy (neighbour->reassembly_heap);
1611 neighbour->reassembly_heap = NULL;
1612 }
1613 if (NULL != neighbour->reassembly_timeout_task)
1614 GNUNET_SCHEDULER_cancel (neighbour->reassembly_timeout_task);
1381 GNUNET_free (neighbour); 1615 GNUNET_free (neighbour);
1382} 1616}
1383 1617
@@ -2054,11 +2288,147 @@ static int
2054check_communicator_backchannel (void *cls, 2288check_communicator_backchannel (void *cls,
2055 const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb) 2289 const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb)
2056{ 2290{
2057 // FIXME: check encapsulated message 2291 const struct GNUNET_MessageHeader *inbox;
2058 // FIXME: check 0-termination of communcator at target 2292 const char *is;
2293 uint16_t msize;
2294 uint16_t isize;
2295
2296 msize = ntohs (cb->header.size) - sizeof (*cb);
2297 if (UINT16_MAX - msize >
2298 sizeof (struct TransportBackchannelEncapsulationMessage) +
2299 sizeof (struct TransportBackchannelRequestPayload) )
2300 {
2301 GNUNET_break (0);
2302 return GNUNET_SYSERR;
2303 }
2304 inbox = (const struct GNUNET_MessageHeader *) &cb[1];
2305 isize = ntohs (inbox->size);
2306 if (isize >= msize)
2307 {
2308 GNUNET_break (0);
2309 return GNUNET_SYSERR;
2310 }
2311 is = (const char *) inbox;
2312 is += isize;
2313 msize -= isize;
2314 GNUNET_assert (msize > 0);
2315 if ('\0' != is[msize-1])
2316 {
2317 GNUNET_break (0);
2318 return GNUNET_SYSERR;
2319 }
2059 return GNUNET_OK; 2320 return GNUNET_OK;
2060} 2321}
2061 2322
2323
2324/**
2325 * Remove memory used by expired ephemeral keys.
2326 *
2327 * @param cls NULL
2328 */
2329static void
2330expire_ephemerals (void *cls)
2331{
2332 struct EphemeralCacheEntry *ece;
2333
2334 (void) cls;
2335 ephemeral_task = NULL;
2336 while (NULL != (ece = GNUNET_CONTAINER_heap_peek (ephemeral_heap)))
2337 {
2338 if (0 == GNUNET_TIME_absolute_get_remaining (ece->ephemeral_validity).rel_value_us)
2339 {
2340 free_ephemeral (ece);
2341 continue;
2342 }
2343 ephemeral_task = GNUNET_SCHEDULER_add_at (ece->ephemeral_validity,
2344 &expire_ephemerals,
2345 NULL);
2346 return;
2347 }
2348}
2349
2350
2351/**
2352 * Lookup ephemeral key in our #ephemeral_map. If no valid one exists, generate
2353 * one, cache it and return it.
2354 *
2355 * @param pid peer to look up ephemeral for
2356 * @param private_key[out] set to the private key
2357 * @param ephemeral_key[out] set to the key
2358 * @param ephemeral_sender_sig[out] set to the signature
2359 * @param ephemeral_validity[out] set to the validity expiration time
2360 */
2361static void
2362lookup_ephemeral (const struct GNUNET_PeerIdentity *pid,
2363 struct GNUNET_CRYPTO_EcdhePrivateKey *private_key,
2364 struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral_key,
2365 struct GNUNET_CRYPTO_EddsaSignature *ephemeral_sender_sig,
2366 struct GNUNET_TIME_Absolute *ephemeral_validity)
2367{
2368 struct EphemeralCacheEntry *ece;
2369 struct EphemeralConfirmation ec;
2370
2371 ece = GNUNET_CONTAINER_multipeermap_get (ephemeral_map,
2372 pid);
2373 if ( (NULL != ece) &&
2374 (0 == GNUNET_TIME_absolute_get_remaining (ece->ephemeral_validity).rel_value_us) )
2375 {
2376 free_ephemeral (ece);
2377 ece = NULL;
2378 }
2379 if (NULL == ece)
2380 {
2381 ece = GNUNET_new (struct EphemeralCacheEntry);
2382 ece->target = *pid;
2383 ece->ephemeral_validity = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get_monotonic (GST_cfg),
2384 EPHEMERAL_VALIDITY);
2385 GNUNET_assert (GNUNET_OK ==
2386 GNUNET_CRYPTO_ecdhe_key_create2 (&ece->private_key));
2387 GNUNET_CRYPTO_ecdhe_key_get_public (&ece->private_key,
2388 &ece->ephemeral_key);
2389 ec.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_EPHEMERAL);
2390 ec.purpose.size = htonl (sizeof (ec));
2391 ec.target = *pid;
2392 ec.ephemeral_key = ece->ephemeral_key;
2393 GNUNET_assert (GNUNET_OK ==
2394 GNUNET_CRYPTO_eddsa_sign (GST_my_private_key,
2395 &ec.purpose,
2396 &ece->sender_sig));
2397 ece->hn = GNUNET_CONTAINER_heap_insert (ephemeral_heap,
2398 ece,
2399 ece->ephemeral_validity.abs_value_us);
2400 GNUNET_assert (GNUNET_OK ==
2401 GNUNET_CONTAINER_multipeermap_put (ephemeral_map,
2402 &ece->target,
2403 ece,
2404 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
2405 if (NULL == ephemeral_task)
2406 ephemeral_task = GNUNET_SCHEDULER_add_at (ece->ephemeral_validity,
2407 &expire_ephemerals,
2408 NULL);
2409 }
2410 *private_key = ece->private_key;
2411 *ephemeral_key = ece->ephemeral_key;
2412 *ephemeral_sender_sig = ece->sender_sig;
2413 *ephemeral_validity = ece->ephemeral_validity;
2414}
2415
2416
2417/**
2418 * We need to transmit @a hdr to @a target. If necessary, this may
2419 * involve DV routing or even broadcasting and fragmentation.
2420 *
2421 * @param target peer to receive @a hdr
2422 * @param hdr header of the message to route
2423 */
2424static void
2425route_message (const struct GNUNET_PeerIdentity *target,
2426 struct GNUNET_MessageHeader *hdr)
2427{
2428 // FIXME: send hdr to target, free hdr (possibly using DV, possibly broadcasting)
2429 GNUNET_free (hdr);
2430}
2431
2062 2432
2063/** 2433/**
2064 * Communicator requests backchannel transmission. Process the request. 2434 * Communicator requests backchannel transmission. Process the request.
@@ -2071,11 +2441,48 @@ handle_communicator_backchannel (void *cls,
2071 const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb) 2441 const struct GNUNET_TRANSPORT_CommunicatorBackchannel *cb)
2072{ 2442{
2073 struct TransportClient *tc = cls; 2443 struct TransportClient *tc = cls;
2074 2444 struct GNUNET_CRYPTO_EcdhePrivateKey private_key;
2075 // FIXME: determine path (possibly DV)! to target peer 2445 struct GNUNET_TIME_Absolute ephemeral_validity;
2076 // FIXME: encapsulate message, encrypt message! 2446 struct TransportBackchannelEncapsulationMessage *enc;
2077 // FIXME: possibly fragment message 2447 struct TransportBackchannelRequestPayload ppay;
2078 // FIXME: possibly DV-route message! 2448 char *mpos;
2449 uint16_t msize;
2450
2451 /* encapsulate and encrypt message */
2452 msize = ntohs (cb->header.size) - sizeof (*cb) + sizeof (struct TransportBackchannelRequestPayload);
2453 enc = GNUNET_malloc (sizeof (*enc) + msize);
2454 enc->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION);
2455 enc->header.size = htons (sizeof (*enc) + msize);
2456 enc->target = cb->pid;
2457 lookup_ephemeral (&cb->pid,
2458 &private_key,
2459 &enc->ephemeral_key,
2460 &ppay.sender_sig,
2461 &ephemeral_validity);
2462 // FIXME: setup 'iv'
2463#if FIXME
2464 dh_key_derive (&private_key,
2465 &cb->pid,
2466 &enc->iv,
2467 &key);
2468#endif
2469 ppay.ephemeral_validity = GNUNET_TIME_absolute_hton (ephemeral_validity);
2470 ppay.monotonic_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (GST_cfg));
2471 mpos = (char *) &enc[1];
2472#if FIXME
2473 encrypt (key,
2474 &ppay,
2475 &mpos,
2476 sizeof (ppay));
2477 encrypt (key,
2478 &cb[1],
2479 &mpos,
2480 ntohs (cb->header.size) - sizeof (*cb));
2481 hmac (key,
2482 &enc->hmac);
2483#endif
2484 route_message (&cb->pid,
2485 &enc->header);
2079 GNUNET_SERVICE_client_continue (tc->client); 2486 GNUNET_SERVICE_client_continue (tc->client);
2080} 2487}
2081 2488
@@ -2260,10 +2667,28 @@ struct CommunicatorMessageContext
2260 * Additional information for flow control and about the sender. 2667 * Additional information for flow control and about the sender.
2261 */ 2668 */
2262 struct GNUNET_TRANSPORT_IncomingMessage im; 2669 struct GNUNET_TRANSPORT_IncomingMessage im;
2670
2671 /**
2672 * Number of hops the message has travelled (if DV-routed).
2673 * FIXME: make use of this in ACK handling!
2674 */
2675 uint16_t total_hops;
2263}; 2676};
2264 2677
2265 2678
2266/** 2679/**
2680 * Given an inbound message @a msg from a communicator @a cmc,
2681 * demultiplex it based on the type calling the right handler.
2682 *
2683 * @param cmc context for demultiplexing
2684 * @param msg message to demultiplex
2685 */
2686static void
2687demultiplex_with_cmc (struct CommunicatorMessageContext *cmc,
2688 const struct GNUNET_MessageHeader *msg);
2689
2690
2691/**
2267 * Send ACK to communicator (if requested) and free @a cmc. 2692 * Send ACK to communicator (if requested) and free @a cmc.
2268 * 2693 *
2269 * @param cmc context for which we are done handling the message 2694 * @param cmc context for which we are done handling the message
@@ -2385,9 +2810,89 @@ handle_fragment_box (void *cls,
2385 const struct TransportFragmentBox *fb) 2810 const struct TransportFragmentBox *fb)
2386{ 2811{
2387 struct CommunicatorMessageContext *cmc = cls; 2812 struct CommunicatorMessageContext *cmc = cls;
2813 struct Neighbour *n;
2814 struct ReassemblyContext *rc;
2815 const struct GNUNET_MessageHeader *msg;
2816 uint16_t msize;
2817
2818 n = GNUNET_CONTAINER_multipeermap_get (neighbours,
2819 &cmc->im.sender);
2820 if (NULL == n)
2821 {
2822 struct GNUNET_SERVICE_Client *client = cmc->tc->client;
2823
2824 GNUNET_break (0);
2825 finish_cmc_handling (cmc);
2826 GNUNET_SERVICE_client_drop (client);
2827 return;
2828 }
2829 if (NULL == n->reassembly_map)
2830 {
2831 n->reassembly_map = GNUNET_CONTAINER_multishortmap_create (8,
2832 GNUNET_YES);
2833 n->reassembly_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2834 n->reassembly_timeout_task = GNUNET_SCHEDULER_add_delayed (REASSEMBLY_EXPIRATION,
2835 &reassembly_cleanup_task,
2836 n);
2837 }
2838 msize = ntohs (fb->msg_size);
2839 rc = GNUNET_CONTAINER_multishortmap_get (n->reassembly_map,
2840 &fb->msg_uuid);
2841 if (NULL == rc)
2842 {
2843 rc = GNUNET_malloc (sizeof (*rc) +
2844 msize + /* reassembly payload buffer */
2845 (msize + 7) / 8 * sizeof (uint8_t) /* bitfield */);
2846 rc->msg_uuid = fb->msg_uuid;
2847 rc->neighbour = n;
2848 rc->msg_size = msize;
2849 rc->reassembly_timeout = GNUNET_TIME_relative_to_absolute (REASSEMBLY_EXPIRATION);
2850 rc->last_frag = GNUNET_TIME_absolute_get ();
2851 rc->hn = GNUNET_CONTAINER_heap_insert (n->reassembly_heap,
2852 rc,
2853 rc->reassembly_timeout.abs_value_us);
2854 GNUNET_assert (GNUNET_OK ==
2855 GNUNET_CONTAINER_multishortmap_put (n->reassembly_map,
2856 &rc->msg_uuid,
2857 rc,
2858 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
2859 rc->bitfield = (uint8_t *) (((char *) &rc[1]) + rc->msg_size);
2860 rc->msg_missing = rc->msg_size;
2861 }
2862 if (msize != rc->msg_size)
2863 {
2864 GNUNET_break (0);
2865 finish_cmc_handling (cmc);
2866 return;
2867 }
2388 2868
2389 // FIXME: do work! 2869 // FIXME: do work: reassemble
2390 finish_cmc_handling (cmc); 2870
2871 /* is reassembly complete? */
2872 if (0 != rc->msg_missing)
2873 {
2874 /* FIXME: possibly send ACK! */
2875 finish_cmc_handling (cmc);
2876 return;
2877 }
2878 /* reassembly is complete, verify result */
2879 msg = (const struct GNUNET_MessageHeader *) &rc[1];
2880 if (ntohs (msg->size) != rc->msg_size)
2881 {
2882 GNUNET_break (0);
2883 free_reassembly_context (rc);
2884 finish_cmc_handling (cmc);
2885 return;
2886 }
2887 /* successful reassembly */
2888 /* FIXME: definitively send ACK! */
2889 demultiplex_with_cmc (cmc,
2890 msg);
2891 /* FIXME: really free here? Might be bad if fragments are still
2892 en-route and we forget that we finished this reassembly immediately!
2893 -> keep around until timeout?
2894 -> shorten timeout based on ACK? */
2895 free_reassembly_context (rc);
2391} 2896}
2392 2897
2393 2898
@@ -2436,11 +2941,27 @@ handle_reliability_box (void *cls,
2436{ 2941{
2437 struct CommunicatorMessageContext *cmc = cls; 2942 struct CommunicatorMessageContext *cmc = cls;
2438 const struct GNUNET_MessageHeader *inbox = (const struct GNUNET_MessageHeader *) &rb[1]; 2943 const struct GNUNET_MessageHeader *inbox = (const struct GNUNET_MessageHeader *) &rb[1];
2439 2944
2440 // FIXME: send back reliability ACK (possibly conditional) 2945 if (0 == ntohl (rb->ack_countdown))
2441 /* forward encapsulated message to CORE */ 2946 {
2442 handle_raw_message (cmc, 2947 struct TransportReliabilityAckMessage *ack;
2443 inbox); 2948
2949 /* FIXME: implement cummulative ACKs and ack_countdown,
2950 then setting the avg_ack_delay field below: */
2951 ack = GNUNET_malloc (sizeof (*ack) +
2952 sizeof (struct GNUNET_ShortHashCode));
2953 ack->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RELIABILITY_ACK);
2954 ack->header.size = htons (sizeof (*ack) +
2955 sizeof (struct GNUNET_ShortHashCode));
2956 memcpy (&ack[1],
2957 &rb->msg_uuid,
2958 sizeof (struct GNUNET_ShortHashCode));
2959 route_message (&cmc->im.sender,
2960 &ack->header);
2961 }
2962 /* continue with inner message */
2963 demultiplex_with_cmc (cmc,
2964 inbox);
2444} 2965}
2445 2966
2446 2967
@@ -2496,7 +3017,16 @@ handle_backchannel_encapsulation (void *cls,
2496{ 3017{
2497 struct CommunicatorMessageContext *cmc = cls; 3018 struct CommunicatorMessageContext *cmc = cls;
2498 3019
2499 // FIMXE: test if it is for me, if not, try to forward to target (DV routes!) 3020 if (0 != memcmp (&be->target,
3021 &GST_my_identity,
3022 sizeof (struct GNUNET_PeerIdentity)))
3023 {
3024 /* not for me, try to route to target */
3025 route_message (&be->target,
3026 GNUNET_copy_message (&be->header));
3027 finish_cmc_handling (cmc);
3028 return;
3029 }
2500 // FIXME: compute shared secret 3030 // FIXME: compute shared secret
2501 // FIXME: check HMAC 3031 // FIXME: check HMAC
2502 // FIXME: decrypt payload 3032 // FIXME: decrypt payload
@@ -2616,10 +3146,25 @@ handle_dv_box (void *cls,
2616 const struct TransportDVBox *dvb) 3146 const struct TransportDVBox *dvb)
2617{ 3147{
2618 struct CommunicatorMessageContext *cmc = cls; 3148 struct CommunicatorMessageContext *cmc = cls;
2619 3149 uint16_t size = ntohs (dvb->header.size);
2620 // FIXME: are we the target? Then unbox and handle message. 3150 uint16_t num_hops = ntohs (dvb->num_hops);
2621 // FIXME: if we are not the target, shorten path and forward along. 3151 const struct GNUNET_PeerIdentity *hops = (const struct GNUNET_PeerIdentity *) &dvb[1];
2622 finish_cmc_handling (cmc); 3152 const struct GNUNET_MessageHeader *inbox = (const struct GNUNET_MessageHeader *) &hops[num_hops];
3153
3154 if (num_hops > 0)
3155 {
3156 // FIXME: if we are not the target, shorten path and forward along.
3157 // Try from the _end_ of hops array if we know the given
3158 // neighbour (shortening the path!).
3159 // NOTE: increment total_hops!
3160 finish_cmc_handling (cmc);
3161 return;
3162 }
3163 /* We are the target. Unbox and handle message. */
3164 cmc->im.sender = dvb->origin;
3165 cmc->total_hops = ntohs (dvb->total_hops);
3166 demultiplex_with_cmc (cmc,
3167 inbox);
2623} 3168}
2624 3169
2625 3170
@@ -2657,6 +3202,25 @@ handle_incoming_msg (void *cls,
2657{ 3202{
2658 struct TransportClient *tc = cls; 3203 struct TransportClient *tc = cls;
2659 struct CommunicatorMessageContext *cmc = GNUNET_new (struct CommunicatorMessageContext); 3204 struct CommunicatorMessageContext *cmc = GNUNET_new (struct CommunicatorMessageContext);
3205
3206 cmc->tc = tc;
3207 cmc->im = *im;
3208 demultiplex_with_cmc (cmc,
3209 (const struct GNUNET_MessageHeader *) &im[1]);
3210}
3211
3212
3213/**
3214 * Given an inbound message @a msg from a communicator @a cmc,
3215 * demultiplex it based on the type calling the right handler.
3216 *
3217 * @param cmc context for demultiplexing
3218 * @param msg message to demultiplex
3219 */
3220static void
3221demultiplex_with_cmc (struct CommunicatorMessageContext *cmc,
3222 const struct GNUNET_MessageHeader *msg)
3223{
2660 struct GNUNET_MQ_MessageHandler handlers[] = { 3224 struct GNUNET_MQ_MessageHandler handlers[] = {
2661 GNUNET_MQ_hd_var_size (fragment_box, 3225 GNUNET_MQ_hd_var_size (fragment_box,
2662 GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT, 3226 GNUNET_MESSAGE_TYPE_TRANSPORT_FRAGMENT,
@@ -2690,14 +3254,12 @@ handle_incoming_msg (void *cls,
2690 }; 3254 };
2691 int ret; 3255 int ret;
2692 3256
2693 cmc->tc = tc;
2694 cmc->im = *im;
2695 ret = GNUNET_MQ_handle_message (handlers, 3257 ret = GNUNET_MQ_handle_message (handlers,
2696 (const struct GNUNET_MessageHeader *) &im[1]); 3258 msg);
2697 if (GNUNET_SYSERR == ret) 3259 if (GNUNET_SYSERR == ret)
2698 { 3260 {
2699 GNUNET_break (0); 3261 GNUNET_break (0);
2700 GNUNET_SERVICE_client_drop (tc->client); 3262 GNUNET_SERVICE_client_drop (cmc->tc->client);
2701 GNUNET_free (cmc); 3263 GNUNET_free (cmc);
2702 return; 3264 return;
2703 } 3265 }
@@ -2705,7 +3267,7 @@ handle_incoming_msg (void *cls,
2705 { 3267 {
2706 /* unencapsulated 'raw' message */ 3268 /* unencapsulated 'raw' message */
2707 handle_raw_message (&cmc, 3269 handle_raw_message (&cmc,
2708 (const struct GNUNET_MessageHeader *) &im[1]); 3270 msg);
2709 } 3271 }
2710} 3272}
2711 3273
@@ -3731,6 +4293,11 @@ do_shutdown (void *cls)
3731{ 4293{
3732 (void) cls; 4294 (void) cls;
3733 4295
4296 if (NULL != ephemeral_task)
4297 {
4298 GNUNET_SCHEDULER_cancel (ephemeral_task);
4299 ephemeral_task = NULL;
4300 }
3734 GNUNET_CONTAINER_multipeermap_iterate (neighbours, 4301 GNUNET_CONTAINER_multipeermap_iterate (neighbours,
3735 &free_neighbour_cb, 4302 &free_neighbour_cb,
3736 NULL); 4303 NULL);