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.c542
1 files changed, 434 insertions, 108 deletions
diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c
index 6c9e0589c..937ae249e 100644
--- a/src/transport/gnunet-service-tng.c
+++ b/src/transport/gnunet-service-tng.c
@@ -40,7 +40,7 @@
40 * #3 only validated addresses are selected for scheduling; that 40 * #3 only validated addresses are selected for scheduling; that
41 * also ensures we know the RTT 41 * also ensures we know the RTT
42 * #4 to ensure flow control and RTT are OK, we always do the 42 * #4 to ensure flow control and RTT are OK, we always do the
43 * 'validation', even if address comes from PEERSTORE 43 * 'validation', even if address comes from PEERSTORE???
44 * - ACK handling / retransmission 44 * - ACK handling / retransmission
45 * - track RTT, distance, loss, etc. 45 * - track RTT, distance, loss, etc.
46 * - DV data structures: 46 * - DV data structures:
@@ -140,6 +140,14 @@
140#define MAX_ADDRESS_VALID_UNTIL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MONTHS, 1) 140#define MAX_ADDRESS_VALID_UNTIL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MONTHS, 1)
141 141
142/** 142/**
143 * What is the maximum frequency at which we do address validation?
144 * A random value between 0 and this value is added when scheduling
145 * the #validation_task (both to ensure we do not validate too often,
146 * and to randomize a bit).
147 */
148#define MIN_DELAY_ADDRESS_VALIDATION GNUNET_TIME_UNIT_MILLISECONDS
149
150/**
143 * How many messages can we have pending for a given communicator 151 * How many messages can we have pending for a given communicator
144 * process before we start to throttle that communicator? 152 * process before we start to throttle that communicator?
145 * 153 *
@@ -1642,6 +1650,12 @@ struct ValidationState
1642 */ 1650 */
1643 enum GNUNET_NetworkType nt; 1651 enum GNUNET_NetworkType nt;
1644 1652
1653 /**
1654 * We are technically ready to send the challenge, but we are waiting for
1655 * the respective queue to become available for transmission.
1656 */
1657 int awaiting_queue;
1658
1645}; 1659};
1646 1660
1647 1661
@@ -1727,6 +1741,11 @@ static struct GNUNET_CONTAINER_MultiPeerMap *ephemeral_map;
1727 */ 1741 */
1728static struct GNUNET_SCHEDULER_Task *ephemeral_task; 1742static struct GNUNET_SCHEDULER_Task *ephemeral_task;
1729 1743
1744/**
1745 * Task to run address validation.
1746 */
1747static struct GNUNET_SCHEDULER_Task *validation_task;
1748
1730 1749
1731/** 1750/**
1732 * Free cached ephemeral key. 1751 * Free cached ephemeral key.
@@ -1745,6 +1764,29 @@ free_ephemeral (struct EphemeralCacheEntry *ece)
1745 1764
1746 1765
1747/** 1766/**
1767 * Free validation state.
1768 *
1769 * @param vs validation state to free
1770 */
1771static void
1772free_validation_state (struct ValidationState *vs)
1773{
1774 GNUNET_CONTAINER_multipeermap_remove (validation_map,
1775 &vs->pid,
1776 vs);
1777 GNUNET_CONTAINER_heap_remove_node (vs->hn);
1778 vs->hn = NULL;
1779 if (NULL != vs->sc)
1780 {
1781 GNUNET_PEERSTORE_store_cancel (vs->sc);
1782 vs->sc = NULL;
1783 }
1784 GNUNET_free (vs->address);
1785 GNUNET_free (vs);
1786}
1787
1788
1789/**
1748 * Lookup neighbour record for peer @a pid. 1790 * Lookup neighbour record for peer @a pid.
1749 * 1791 *
1750 * @param pid neighbour to look for 1792 * @param pid neighbour to look for
@@ -2011,8 +2053,8 @@ reassembly_cleanup_task (void *cls)
2011 */ 2053 */
2012static int 2054static int
2013free_reassembly_cb (void *cls, 2055free_reassembly_cb (void *cls,
2014 const struct GNUNET_ShortHashCode *key, 2056 const struct GNUNET_ShortHashCode *key,
2015 void *value) 2057 void *value)
2016{ 2058{
2017 struct ReassemblyContext *rc = value; 2059 struct ReassemblyContext *rc = value;
2018 (void) cls; 2060 (void) cls;
@@ -2911,7 +2953,7 @@ lookup_ephemeral (const struct GNUNET_PeerIdentity *pid,
2911 */ 2953 */
2912static void 2954static void
2913route_message (const struct GNUNET_PeerIdentity *target, 2955route_message (const struct GNUNET_PeerIdentity *target,
2914 struct GNUNET_MessageHeader *hdr) 2956 struct GNUNET_MessageHeader *hdr)
2915{ 2957{
2916 // FIXME: send hdr to target, free hdr (possibly using DV, possibly broadcasting) 2958 // FIXME: send hdr to target, free hdr (possibly using DV, possibly broadcasting)
2917 GNUNET_free (hdr); 2959 GNUNET_free (hdr);
@@ -3326,7 +3368,7 @@ send_fragment_ack (struct ReassemblyContext *rc)
3326 */ 3368 */
3327static void 3369static void
3328handle_fragment_box (void *cls, 3370handle_fragment_box (void *cls,
3329 const struct TransportFragmentBox *fb) 3371 const struct TransportFragmentBox *fb)
3330{ 3372{
3331 struct CommunicatorMessageContext *cmc = cls; 3373 struct CommunicatorMessageContext *cmc = cls;
3332 struct Neighbour *n; 3374 struct Neighbour *n;
@@ -3500,7 +3542,7 @@ handle_fragment_box (void *cls,
3500 */ 3542 */
3501static void 3543static void
3502handle_fragment_ack (void *cls, 3544handle_fragment_ack (void *cls,
3503 const struct TransportFragmentAckMessage *fa) 3545 const struct TransportFragmentAckMessage *fa)
3504{ 3546{
3505 struct CommunicatorMessageContext *cmc = cls; 3547 struct CommunicatorMessageContext *cmc = cls;
3506 3548
@@ -3739,7 +3781,7 @@ check_dv_box (void *cls,
3739 */ 3781 */
3740static void 3782static void
3741handle_dv_box (void *cls, 3783handle_dv_box (void *cls,
3742 const struct TransportDVBox *dvb) 3784 const struct TransportDVBox *dvb)
3743{ 3785{
3744 struct CommunicatorMessageContext *cmc = cls; 3786 struct CommunicatorMessageContext *cmc = cls;
3745 uint16_t size = ntohs (dvb->header.size) - sizeof (*dvb); 3787 uint16_t size = ntohs (dvb->header.size) - sizeof (*dvb);
@@ -4348,97 +4390,6 @@ tracker_excess_in_cb (void *cls)
4348 4390
4349 4391
4350/** 4392/**
4351 * New queue became available. Process the request.
4352 *
4353 * @param cls the client
4354 * @param aqm the send message that was sent
4355 */
4356static void
4357handle_add_queue_message (void *cls,
4358 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
4359{
4360 struct TransportClient *tc = cls;
4361 struct Queue *queue;
4362 struct Neighbour *neighbour;
4363 const char *addr;
4364 uint16_t addr_len;
4365
4366 if (ntohl (aqm->mtu) <= sizeof (struct TransportFragmentBox))
4367 {
4368 /* MTU so small as to be useless for transmissions,
4369 required for #fragment_message()! */
4370 GNUNET_break_op (0);
4371 GNUNET_SERVICE_client_drop (tc->client);
4372 return;
4373 }
4374 neighbour = lookup_neighbour (&aqm->receiver);
4375 if (NULL == neighbour)
4376 {
4377 neighbour = GNUNET_new (struct Neighbour);
4378 neighbour->earliest_timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
4379 neighbour->pid = aqm->receiver;
4380 GNUNET_assert (GNUNET_OK ==
4381 GNUNET_CONTAINER_multipeermap_put (neighbours,
4382 &neighbour->pid,
4383 neighbour,
4384 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
4385 cores_send_connect_info (&neighbour->pid,
4386 GNUNET_BANDWIDTH_ZERO);
4387 }
4388 addr_len = ntohs (aqm->header.size) - sizeof (*aqm);
4389 addr = (const char *) &aqm[1];
4390
4391 queue = GNUNET_malloc (sizeof (struct Queue) + addr_len);
4392 queue->tc = tc;
4393 queue->address = (const char *) &queue[1];
4394 queue->rtt = GNUNET_TIME_UNIT_FOREVER_REL;
4395 queue->qid = aqm->qid;
4396 queue->mtu = ntohl (aqm->mtu);
4397 queue->nt = (enum GNUNET_NetworkType) ntohl (aqm->nt);
4398 queue->cs = (enum GNUNET_TRANSPORT_ConnectionStatus) ntohl (aqm->cs);
4399 queue->neighbour = neighbour;
4400 GNUNET_BANDWIDTH_tracker_init2 (&queue->tracker_in,
4401 &tracker_update_in_cb,
4402 queue,
4403 GNUNET_BANDWIDTH_ZERO,
4404 GNUNET_CONSTANTS_MAX_BANDWIDTH_CARRY_S,
4405 &tracker_excess_in_cb,
4406 queue);
4407 GNUNET_BANDWIDTH_tracker_init2 (&queue->tracker_out,
4408 &tracker_update_out_cb,
4409 queue,
4410 GNUNET_BANDWIDTH_ZERO,
4411 GNUNET_CONSTANTS_MAX_BANDWIDTH_CARRY_S,
4412 &tracker_excess_out_cb,
4413 queue);
4414 memcpy (&queue[1],
4415 addr,
4416 addr_len);
4417 /* notify monitors about new queue */
4418 {
4419 struct MonitorEvent me = {
4420 .rtt = queue->rtt,
4421 .cs = queue->cs
4422 };
4423
4424 notify_monitors (&neighbour->pid,
4425 queue->address,
4426 queue->nt,
4427 &me);
4428 }
4429 GNUNET_CONTAINER_MDLL_insert (neighbour,
4430 neighbour->queue_head,
4431 neighbour->queue_tail,
4432 queue);
4433 GNUNET_CONTAINER_MDLL_insert (client,
4434 tc->details.communicator.queue_head,
4435 tc->details.communicator.queue_tail,
4436 queue);
4437 GNUNET_SERVICE_client_continue (tc->client);
4438}
4439
4440
4441/**
4442 * Queue to a peer went down. Process the request. 4393 * Queue to a peer went down. Process the request.
4443 * 4394 *
4444 * @param cls the client 4395 * @param cls the client
@@ -4608,7 +4559,7 @@ notify_client_queues (void *cls,
4608 */ 4559 */
4609static void 4560static void
4610handle_monitor_start (void *cls, 4561handle_monitor_start (void *cls,
4611 const struct GNUNET_TRANSPORT_MonitorStart *start) 4562 const struct GNUNET_TRANSPORT_MonitorStart *start)
4612{ 4563{
4613 struct TransportClient *tc = cls; 4564 struct TransportClient *tc = cls;
4614 4565
@@ -4710,6 +4661,261 @@ suggest_to_connect (const struct GNUNET_PeerIdentity *pid,
4710 4661
4711 4662
4712/** 4663/**
4664 * Task run periodically to validate some address based on #validation_heap.
4665 *
4666 * @param cls NULL
4667 */
4668static void
4669validation_start_cb (void *cls);
4670
4671
4672/**
4673 * Set the time for next_challenge of @a vs to @a new_time.
4674 * Updates the heap and if necessary reschedules the job.
4675 *
4676 * @param vs validation state to update
4677 * @param new_time new time for revalidation
4678 */
4679static void
4680update_next_challenge_time (struct ValidationState *vs,
4681 struct GNUNET_TIME_Absolute new_time)
4682{
4683 struct GNUNET_TIME_Relative delta;
4684
4685 if (new_time.abs_value_us == vs->next_challenge.abs_value_us)
4686 return; /* be lazy */
4687 vs->next_challenge = new_time;
4688 if (NULL == vs->hn)
4689 vs->hn = GNUNET_CONTAINER_heap_insert (validation_heap,
4690 vs,
4691 new_time.abs_value_us);
4692 else
4693 GNUNET_CONTAINER_heap_update_cost (vs->hn,
4694 new_time.abs_value_us);
4695 if ( (vs != GNUNET_CONTAINER_heap_peek (validation_heap)) &&
4696 (NULL != validation_task) )
4697 return;
4698 if (NULL != validation_task)
4699 GNUNET_SCHEDULER_cancel (validation_task);
4700 /* randomize a bit */
4701 delta.rel_value_us = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
4702 MIN_DELAY_ADDRESS_VALIDATION.rel_value_us);
4703 new_time = GNUNET_TIME_absolute_add (new_time,
4704 delta);
4705 validation_task = GNUNET_SCHEDULER_add_at (new_time,
4706 &validation_start_cb,
4707 NULL);
4708}
4709
4710
4711/**
4712 * The queue @a q (which matches the peer and address in @a vs) is
4713 * ready for queueing. We should now queue the validation request.
4714 *
4715 * @param q queue to send on
4716 * @param vs state to derive validation challenge from
4717 */
4718static void
4719validation_transmit_on_queue (struct Queue *q,
4720 struct ValidationState *vs)
4721{
4722 struct TransportValidationChallenge tvc;
4723
4724 vs->last_challenge_use = GNUNET_TIME_absolute_get ();
4725 tvc.reserved = htonl (0);
4726 tvc.challenge = vs->challenge;
4727 tvc.sender_time = GNUNET_TIME_absolute_hton (vs->last_challenge_use);
4728 // FIXME: actually send on queue!
4729}
4730
4731
4732/**
4733 * Task run periodically to validate some address based on #validation_heap.
4734 *
4735 * @param cls NULL
4736 */
4737static void
4738validation_start_cb (void *cls)
4739{
4740 struct ValidationState *vs;
4741 struct Neighbour *n;
4742 struct Queue *q;
4743
4744 (void) cls;
4745 validation_task = NULL;
4746 vs = GNUNET_CONTAINER_heap_peek (validation_heap);
4747 /* drop validations past their expiration */
4748 while ( (NULL != vs) &&
4749 (0 == GNUNET_TIME_absolute_get_remaining (vs->valid_until).rel_value_us) )
4750 {
4751 free_validation_state (vs);
4752 vs = GNUNET_CONTAINER_heap_peek (validation_heap);
4753 }
4754 if (NULL == vs)
4755 return; /* woopsie, no more addresses known, should only
4756 happen if we're really a lonely peer */
4757 n = GNUNET_CONTAINER_multipeermap_get (neighbours,
4758 &vs->pid);
4759 q = NULL;
4760 if (NULL != n)
4761 {
4762 for (struct Queue *pos = n->queue_head;
4763 NULL != pos;
4764 pos = pos->next_neighbour)
4765 {
4766 if (0 == strcmp (pos->address,
4767 vs->address))
4768 {
4769 q = pos;
4770 break;
4771 }
4772 }
4773 }
4774 if (NULL == q)
4775 {
4776 vs->awaiting_queue = GNUNET_YES;
4777 suggest_to_connect (&vs->pid,
4778 vs->address);
4779 }
4780 else
4781 validation_transmit_on_queue (q,
4782 vs);
4783 /* Finally, reschedule next attempt */
4784 vs->challenge_backoff = GNUNET_TIME_randomized_backoff (vs->challenge_backoff,
4785 MAX_VALIDATION_CHALLENGE_FREQ);
4786 update_next_challenge_time (vs,
4787 GNUNET_TIME_relative_to_absolute (vs->challenge_backoff));
4788}
4789
4790
4791/**
4792 * A new queue has been created, check if any address validation
4793 * requests have been waiting for it.
4794 *
4795 * @param cls a `struct Queue`
4796 * @param pid peer concerned (unused)
4797 * @param value a `struct ValidationState`
4798 * @return #GNUNET_NO if a match was found and we can stop looking
4799 */
4800static int
4801check_validation_request_pending (void *cls,
4802 const struct GNUNET_PeerIdentity *pid,
4803 void *value)
4804{
4805 struct Queue *q = cls;
4806 struct ValidationState *vs = value;
4807
4808 (void) pid;
4809 if ( (GNUNET_YES == vs->awaiting_queue) &&
4810 (0 == strcmp (vs->address,
4811 q->address)) )
4812 {
4813 vs->awaiting_queue = GNUNET_NO;
4814 validation_transmit_on_queue (q,
4815 vs);
4816 return GNUNET_NO;
4817 }
4818 return GNUNET_OK;
4819}
4820
4821
4822/**
4823 * New queue became available. Process the request.
4824 *
4825 * @param cls the client
4826 * @param aqm the send message that was sent
4827 */
4828static void
4829handle_add_queue_message (void *cls,
4830 const struct GNUNET_TRANSPORT_AddQueueMessage *aqm)
4831{
4832 struct TransportClient *tc = cls;
4833 struct Queue *queue;
4834 struct Neighbour *neighbour;
4835 const char *addr;
4836 uint16_t addr_len;
4837
4838 if (ntohl (aqm->mtu) <= sizeof (struct TransportFragmentBox))
4839 {
4840 /* MTU so small as to be useless for transmissions,
4841 required for #fragment_message()! */
4842 GNUNET_break_op (0);
4843 GNUNET_SERVICE_client_drop (tc->client);
4844 return;
4845 }
4846 neighbour = lookup_neighbour (&aqm->receiver);
4847 if (NULL == neighbour)
4848 {
4849 neighbour = GNUNET_new (struct Neighbour);
4850 neighbour->earliest_timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
4851 neighbour->pid = aqm->receiver;
4852 GNUNET_assert (GNUNET_OK ==
4853 GNUNET_CONTAINER_multipeermap_put (neighbours,
4854 &neighbour->pid,
4855 neighbour,
4856 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
4857 cores_send_connect_info (&neighbour->pid,
4858 GNUNET_BANDWIDTH_ZERO);
4859 }
4860 addr_len = ntohs (aqm->header.size) - sizeof (*aqm);
4861 addr = (const char *) &aqm[1];
4862
4863 queue = GNUNET_malloc (sizeof (struct Queue) + addr_len);
4864 queue->tc = tc;
4865 queue->address = (const char *) &queue[1];
4866 queue->rtt = GNUNET_TIME_UNIT_FOREVER_REL;
4867 queue->qid = aqm->qid;
4868 queue->mtu = ntohl (aqm->mtu);
4869 queue->nt = (enum GNUNET_NetworkType) ntohl (aqm->nt);
4870 queue->cs = (enum GNUNET_TRANSPORT_ConnectionStatus) ntohl (aqm->cs);
4871 queue->neighbour = neighbour;
4872 GNUNET_BANDWIDTH_tracker_init2 (&queue->tracker_in,
4873 &tracker_update_in_cb,
4874 queue,
4875 GNUNET_BANDWIDTH_ZERO,
4876 GNUNET_CONSTANTS_MAX_BANDWIDTH_CARRY_S,
4877 &tracker_excess_in_cb,
4878 queue);
4879 GNUNET_BANDWIDTH_tracker_init2 (&queue->tracker_out,
4880 &tracker_update_out_cb,
4881 queue,
4882 GNUNET_BANDWIDTH_ZERO,
4883 GNUNET_CONSTANTS_MAX_BANDWIDTH_CARRY_S,
4884 &tracker_excess_out_cb,
4885 queue);
4886 memcpy (&queue[1],
4887 addr,
4888 addr_len);
4889 /* notify monitors about new queue */
4890 {
4891 struct MonitorEvent me = {
4892 .rtt = queue->rtt,
4893 .cs = queue->cs
4894 };
4895
4896 notify_monitors (&neighbour->pid,
4897 queue->address,
4898 queue->nt,
4899 &me);
4900 }
4901 GNUNET_CONTAINER_MDLL_insert (neighbour,
4902 neighbour->queue_head,
4903 neighbour->queue_tail,
4904 queue);
4905 GNUNET_CONTAINER_MDLL_insert (client,
4906 tc->details.communicator.queue_head,
4907 tc->details.communicator.queue_tail,
4908 queue);
4909 /* check if valdiations are waiting for the queue */
4910 (void) GNUNET_CONTAINER_multipeermap_get_multiple (validation_map,
4911 &aqm->receiver,
4912 &check_validation_request_pending,
4913 queue);
4914 GNUNET_SERVICE_client_continue (tc->client);
4915}
4916
4917
4918/**
4713 * Communicator tells us that our request to create a queue "worked", that 4919 * Communicator tells us that our request to create a queue "worked", that
4714 * is setting up the queue is now in process. 4920 * is setting up the queue is now in process.
4715 * 4921 *
@@ -4914,6 +5120,49 @@ check_address_consider_verify (void *cls,
4914 5120
4915 5121
4916/** 5122/**
5123 * Closure for #check_known_address.
5124 */
5125struct CheckKnownAddressContext
5126{
5127 /**
5128 * Set to the address we are looking for.
5129 */
5130 const char *address;
5131
5132 /**
5133 * Set to a matching validation state, if one was found.
5134 */
5135 struct ValidationState *vs;
5136};
5137
5138
5139/**
5140 * Test if the validation state in @a value matches the
5141 * address from @a cls.
5142 *
5143 * @param cls a `struct CheckKnownAddressContext`
5144 * @param pid unused (must match though)
5145 * @param value a `struct ValidationState`
5146 * @return #GNUNET_OK if not matching, #GNUNET_NO if match found
5147 */
5148static int
5149check_known_address (void *cls,
5150 const struct GNUNET_PeerIdentity *pid,
5151 void *value)
5152{
5153 struct CheckKnownAddressContext *ckac = cls;
5154 struct ValidationState *vs = value;
5155
5156 (void) pid;
5157 if (0 != strcmp (vs->address,
5158 ckac->address))
5159 return GNUNET_OK;
5160 ckac->vs = vs;
5161 return GNUNET_NO;
5162}
5163
5164
5165/**
4917 * Given another peers address, consider checking it for validity 5166 * Given another peers address, consider checking it for validity
4918 * and then adding it to the Peerstore. 5167 * and then adding it to the Peerstore.
4919 * 5168 *
@@ -4928,10 +5177,13 @@ handle_address_consider_verify (void *cls,
4928 char *address; 5177 char *address;
4929 enum GNUNET_NetworkType nt; 5178 enum GNUNET_NetworkType nt;
4930 struct GNUNET_TIME_Absolute expiration; 5179 struct GNUNET_TIME_Absolute expiration;
5180 struct GNUNET_TIME_Absolute now;
5181 struct ValidationState *vs;
4931 5182
4932 (void) cls; 5183 (void) cls;
4933 // FIXME: pre-check: do we know this address already? 5184 // FIXME: checking that we know this address already should
4934 // FIXME: pre-check: rate-limit signature verification / validation! 5185 // be done BEFORE checking the signature => HELLO API change!
5186 // FIXME: pre-check: rate-limit signature verification / validation?!
4935 address = GNUNET_HELLO_extract_address (&hdr[1], 5187 address = GNUNET_HELLO_extract_address (&hdr[1],
4936 ntohs (hdr->header.size) - sizeof (*hdr), 5188 ntohs (hdr->header.size) - sizeof (*hdr),
4937 &hdr->peer, 5189 &hdr->peer,
@@ -4944,8 +5196,50 @@ handle_address_consider_verify (void *cls,
4944 } 5196 }
4945 if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us) 5197 if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us)
4946 return; /* expired */ 5198 return; /* expired */
4947 // FIXME: do begin actual verification here! 5199 {
4948 GNUNET_free (address); 5200 struct CheckKnownAddressContext ckac = {
5201 .address = address,
5202 .vs = NULL
5203 };
5204
5205 (void) GNUNET_CONTAINER_multipeermap_get_multiple (validation_map,
5206 &hdr->peer,
5207 &check_known_address,
5208 &ckac);
5209 if (NULL != (vs = ckac.vs))
5210 {
5211 /* if 'vs' is not currently valid, we need to speed up retrying the validation */
5212 if (vs->validated_until.abs_value_us < vs->next_challenge.abs_value_us)
5213 {
5214 /* reduce backoff as we got a fresh advertisement */
5215 vs->challenge_backoff = GNUNET_TIME_relative_min (FAST_VALIDATION_CHALLENGE_FREQ,
5216 GNUNET_TIME_relative_divide (vs->challenge_backoff,
5217 2));
5218 update_next_challenge_time (vs,
5219 GNUNET_TIME_relative_to_absolute (vs->challenge_backoff));
5220 }
5221 GNUNET_free (address);
5222 return;
5223 }
5224 }
5225 now = GNUNET_TIME_absolute_get();
5226 vs = GNUNET_new (struct ValidationState);
5227 vs->pid = hdr->peer;
5228 vs->valid_until = expiration;
5229 vs->first_challenge_use = now;
5230 vs->validation_rtt = GNUNET_TIME_UNIT_FOREVER_REL;
5231 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
5232 &vs->challenge,
5233 sizeof (vs->challenge));
5234 vs->address = address;
5235 vs->nt = nt;
5236 GNUNET_assert (GNUNET_YES ==
5237 GNUNET_CONTAINER_multipeermap_put (validation_map,
5238 &vs->pid,
5239 vs,
5240 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
5241 update_next_challenge_time (vs,
5242 now);
4949} 5243}
4950 5244
4951 5245
@@ -5033,7 +5327,7 @@ free_dv_routes_cb (void *cls,
5033 * 5327 *
5034 * @param cls NULL 5328 * @param cls NULL
5035 * @param pid unused 5329 * @param pid unused
5036 * @param value a `struct Neighbour` 5330 * @param value a `struct EphemeralCacheEntry`
5037 * @return #GNUNET_OK (always) 5331 * @return #GNUNET_OK (always)
5038 */ 5332 */
5039static int 5333static int
@@ -5051,6 +5345,28 @@ free_ephemeral_cb (void *cls,
5051 5345
5052 5346
5053/** 5347/**
5348 * Free validation state.
5349 *
5350 * @param cls NULL
5351 * @param pid unused
5352 * @param value a `struct ValidationState`
5353 * @return #GNUNET_OK (always)
5354 */
5355static int
5356free_validation_state_cb (void *cls,
5357 const struct GNUNET_PeerIdentity *pid,
5358 void *value)
5359{
5360 struct ValidationState *vs = value;
5361
5362 (void) cls;
5363 (void) pid;
5364 free_validation_state (vs);
5365 return GNUNET_OK;
5366}
5367
5368
5369/**
5054 * Function called when the service shuts down. Unloads our plugins 5370 * Function called when the service shuts down. Unloads our plugins
5055 * and cancels pending validations. 5371 * and cancels pending validations.
5056 * 5372 *
@@ -5088,14 +5404,21 @@ do_shutdown (void *cls)
5088 } 5404 }
5089 GNUNET_CONTAINER_multipeermap_destroy (neighbours); 5405 GNUNET_CONTAINER_multipeermap_destroy (neighbours);
5090 neighbours = NULL; 5406 neighbours = NULL;
5407 GNUNET_CONTAINER_multipeermap_iterate (validation_map,
5408 &free_validation_state_cb,
5409 NULL);
5410 GNUNET_CONTAINER_multipeermap_destroy (validation_map);
5411 validation_map = NULL;
5412 GNUNET_CONTAINER_heap_destroy (validation_heap);
5413 validation_heap = NULL;
5091 GNUNET_CONTAINER_multipeermap_iterate (dv_routes, 5414 GNUNET_CONTAINER_multipeermap_iterate (dv_routes,
5092 &free_dv_routes_cb, 5415 &free_dv_routes_cb,
5093 NULL); 5416 NULL);
5094 GNUNET_CONTAINER_multipeermap_destroy (dv_routes); 5417 GNUNET_CONTAINER_multipeermap_destroy (dv_routes);
5095 dv_routes = NULL; 5418 dv_routes = NULL;
5096 GNUNET_CONTAINER_multipeermap_iterate (ephemeral_map, 5419 GNUNET_CONTAINER_multipeermap_iterate (ephemeral_map,
5097 &free_ephemeral_cb, 5420 &free_ephemeral_cb,
5098 NULL); 5421 NULL);
5099 GNUNET_CONTAINER_multipeermap_destroy (ephemeral_map); 5422 GNUNET_CONTAINER_multipeermap_destroy (ephemeral_map);
5100 ephemeral_map = NULL; 5423 ephemeral_map = NULL;
5101 GNUNET_CONTAINER_heap_destroy (ephemeral_heap); 5424 GNUNET_CONTAINER_heap_destroy (ephemeral_heap);
@@ -5125,6 +5448,9 @@ run (void *cls,
5125 ephemeral_map = GNUNET_CONTAINER_multipeermap_create (32, 5448 ephemeral_map = GNUNET_CONTAINER_multipeermap_create (32,
5126 GNUNET_YES); 5449 GNUNET_YES);
5127 ephemeral_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); 5450 ephemeral_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
5451 validation_map = GNUNET_CONTAINER_multipeermap_create (1024,
5452 GNUNET_YES);
5453 validation_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
5128 GST_my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (GST_cfg); 5454 GST_my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (GST_cfg);
5129 if (NULL == GST_my_private_key) 5455 if (NULL == GST_my_private_key)
5130 { 5456 {