* TODO:
* Implement next:
* - track RTT, distance, loss, etc. => requires extra data structures!
+ * => fragment UUIDs should be 'sequential' 32-bit numbers, for cummulative
+ * acks with Bitmask
+ * => fragments carry their own offsets, so receiver will NOT require
+ * seeing all the possible values
+ * => can generate 'fresh' UUIDs for each retransmission to track it
+ * => but need to keep 'map' of 32-bit UUID to queue!
+ * => message UUIDs are currently overkill with 256 bits
+ * => cummulative acks for messages include full UUID list
+ * => message UUID size should be chosen to result in 8 byte alignment
+ * => could encode 32-bit counter + 32-bit queue UUID in 64-bit message
+ * UUID?
+ * => Use multihashmap32 on counter for lookup in hashmap?
+ * => FIXME: 2x32 bit introduced, but still set to random value
+ * instead of using the generators!
+ * (and generators not initialized to random starting values either)
* - consider replacing random `struct GNUNET_ShortHashCode` message UUIDs
* with (incrementing) 64-bit numbers (compacting both
* `struct TransportReliabilityBox` and `struct
struct MessageUUIDP
{
/**
- * Unique value.
+ * Unique value, generated by incrementing the
+ * `message_uuid_ctr` of `struct Neighbour`.
*/
- struct GNUNET_ShortHashCode uuid; // FIXME: change to 8 bytes
+ uint32_t uuid GNUNET_PACKED;
+
+ /**
+ * UUID of the queue that was used to transmit this message.
+ * Used to map acknowledgements back to the respective queue.
+ */
+ uint32_t queue_uuid GNUNET_PACKED;
};
/**
* Unique value identifying a fragment, in NBO.
*/
- uint32_t uuid GNUNET_PACKED; // FIXME: change to 2x 2 bytes?
+ uint32_t uuid GNUNET_PACKED;
};
*/
uint32_t qid;
+ /**
+ * UUID used to map acknowledgements back to the queue that
+ * was used for transmission. Note that @e queue_uuid-s are
+ * only unique per neighbour (generated via `queue_uuid_gen`
+ * of `struct Neighbour`).
+ */
+ uint32_t queue_uuid;
+
/**
* Maximum transmission unit supported by this queue.
*/
* reassembly. May be NULL if we currently have no fragments from
* this @e pid (lazy initialization).
*/
- struct GNUNET_CONTAINER_MultiShortmap *reassembly_map;
+ struct GNUNET_CONTAINER_MultiHashMap32 *reassembly_map;
/**
* Heap with `struct ReassemblyContext` structs for fragments under
*/
struct GNUNET_TIME_Absolute earliest_timeout;
+ /**
+ * Incremented by one for each queue to generate
+ * unique queue identifiers. Initially set to a random value.
+ *
+ * FIXME: Deal with wrap around (might be triggered by very
+ * persistent adversary).
+ */
+ uint32_t queue_uuid_gen;
+
+ /**
+ * Incremented by one for each message sent to this neighbour, to
+ * uniquely identify that message in replies (note that fragments
+ * use another additional counter). Initially set to a random value.
+ *
+ * It should be safe to assume that by the time this value may wrap
+ * around, the original message is long "gone" and no longer
+ * relevant.
+ */
+ uint32_t message_uuid_ctr;
+
/**
* Do we have a confirmed working queue and are thus visible to
* CORE?
GNUNET_assert (rc == GNUNET_CONTAINER_heap_remove_node (rc->hn));
GNUNET_assert (GNUNET_OK ==
- GNUNET_CONTAINER_multishortmap_remove (n->reassembly_map,
- &rc->msg_uuid.uuid,
- rc));
+ GNUNET_CONTAINER_multihashmap32_remove (n->reassembly_map,
+ rc->msg_uuid.uuid,
+ rc));
GNUNET_free (rc);
}
* @return #GNUNET_OK (continue iteration)
*/
static int
-free_reassembly_cb (void *cls,
- const struct GNUNET_ShortHashCode *key,
- void *value)
+free_reassembly_cb (void *cls, uint32_t key, void *value)
{
struct ReassemblyContext *rc = value;
GNUNET_SCHEDULER_cancel (neighbour->timeout_task);
if (NULL != neighbour->reassembly_map)
{
- GNUNET_CONTAINER_multishortmap_iterate (neighbour->reassembly_map,
- &free_reassembly_cb,
- NULL);
- GNUNET_CONTAINER_multishortmap_destroy (neighbour->reassembly_map);
+ GNUNET_CONTAINER_multihashmap32_iterate (neighbour->reassembly_map,
+ &free_reassembly_cb,
+ NULL);
+ GNUNET_CONTAINER_multihashmap32_destroy (neighbour->reassembly_map);
neighbour->reassembly_map = NULL;
GNUNET_CONTAINER_heap_destroy (neighbour->reassembly_heap);
neighbour->reassembly_heap = NULL;
}
+/**
+ * Closure for #find_by_message_uuid.
+ */
+struct FindByMessageUuidContext
+{
+ /**
+ * UUID to look for.
+ */
+ struct MessageUUIDP message_uuid;
+
+ /**
+ * Set to the reassembly context if found.
+ */
+ struct ReassemblyContext *rc;
+};
+
+
+/**
+ * Iterator called to find a reassembly context by the message UUID in the
+ * multihashmap32.
+ *
+ * @param cls a `struct FindByMessageUuidContext`
+ * @param key a key (unused)
+ * @param value a `struct ReassemblyContext`
+ * @return #GNUNET_YES if not found, #GNUNET_NO if found
+ */
+static int
+find_by_message_uuid (void *cls, uint32_t key, void *value)
+{
+ struct FindByMessageUuidContext *fc = cls;
+ struct ReassemblyContext *rc = value;
+
+ (void) key;
+ if (0 == GNUNET_memcmp (&fc->message_uuid, &rc->msg_uuid))
+ {
+ fc->rc = rc;
+ return GNUNET_NO;
+ }
+ return GNUNET_YES;
+}
+
+
/**
* Communicator gave us a fragment. Process the request.
*
char *target;
struct GNUNET_TIME_Relative cdelay;
int ack_now;
+ struct FindByMessageUuidContext fc;
n = GNUNET_CONTAINER_multipeermap_get (neighbours, &cmc->im.sender);
if (NULL == n)
}
if (NULL == n->reassembly_map)
{
- n->reassembly_map = GNUNET_CONTAINER_multishortmap_create (8, GNUNET_YES);
+ n->reassembly_map = GNUNET_CONTAINER_multihashmap32_create (8);
n->reassembly_heap =
GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
n->reassembly_timeout_task =
n);
}
msize = ntohs (fb->msg_size);
- rc =
- GNUNET_CONTAINER_multishortmap_get (n->reassembly_map, &fb->msg_uuid.uuid);
- if (NULL == rc)
+ fc.message_uuid = fb->msg_uuid;
+ fc.rc = NULL;
+ GNUNET_CONTAINER_multihashmap32_get_multiple (n->reassembly_map,
+ fb->msg_uuid.uuid,
+ &find_by_message_uuid,
+ &fc);
+ if (NULL == (rc = fc.rc))
{
rc = GNUNET_malloc (sizeof (*rc) + msize + /* reassembly payload buffer */
(msize + 7) / 8 * sizeof (uint8_t) /* bitfield */);
rc,
rc->reassembly_timeout.abs_value_us);
GNUNET_assert (GNUNET_OK ==
- GNUNET_CONTAINER_multishortmap_put (
+ GNUNET_CONTAINER_multihashmap32_put (
n->reassembly_map,
- &rc->msg_uuid.uuid,
+ rc->msg_uuid.uuid,
rc,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
target = (char *) &rc[1];
rc->bitfield = (uint8_t *) (target + rc->msg_size);
rc->msg_missing = rc->msg_size;