diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/gnunet_time_lib.h | 12 | ||||
-rw-r--r-- | src/transport/gnunet-service-tng.c | 542 |
2 files changed, 440 insertions, 114 deletions
diff --git a/src/include/gnunet_time_lib.h b/src/include/gnunet_time_lib.h index 93e6cd00f..482ae52d8 100644 --- a/src/include/gnunet_time_lib.h +++ b/src/include/gnunet_time_lib.h | |||
@@ -11,7 +11,7 @@ | |||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Affero General Public License for more details. | 13 | Affero General Public License for more details. |
14 | 14 | ||
15 | You should have received a copy of the GNU Affero General Public License | 15 | You should have received a copy of the GNU Affero General Public License |
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | 16 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | 17 | ||
@@ -368,7 +368,7 @@ GNUNET_TIME_absolute_get_remaining (struct GNUNET_TIME_Absolute future); | |||
368 | */ | 368 | */ |
369 | struct GNUNET_TIME_Relative | 369 | struct GNUNET_TIME_Relative |
370 | GNUNET_TIME_calculate_eta (struct GNUNET_TIME_Absolute start, | 370 | GNUNET_TIME_calculate_eta (struct GNUNET_TIME_Absolute start, |
371 | uint64_t finished, | 371 | uint64_t finished, |
372 | uint64_t total); | 372 | uint64_t total); |
373 | 373 | ||
374 | 374 | ||
@@ -579,15 +579,15 @@ struct GNUNET_CONFIGURATION_Handle; | |||
579 | * increasing. Guards against systems without an RTC or | 579 | * increasing. Guards against systems without an RTC or |
580 | * clocks running backwards and other nasty surprises. Does | 580 | * clocks running backwards and other nasty surprises. Does |
581 | * not guarantee that the returned time is near the current | 581 | * not guarantee that the returned time is near the current |
582 | * time returned by #GNUNET_TIME_absolute_get(). Two | 582 | * time returned by #GNUNET_TIME_absolute_get(). Two |
583 | * subsequent calls (within a short time period) may return the | 583 | * subsequent calls (within a short time period) may return the |
584 | * same value. Persists the last returned time on disk to | 584 | * same value. Persists the last returned time on disk to |
585 | * ensure that time never goes backwards. As a result, the | 585 | * ensure that time never goes backwards. As a result, the |
586 | * resulting value can be used to check if a message is the | 586 | * resulting value can be used to check if a message is the |
587 | * "most recent" value and replays of older messages (from | 587 | * "most recent" value and replays of older messages (from |
588 | * the same origin) would be discarded. | 588 | * the same origin) would be discarded. |
589 | * | 589 | * |
590 | * @param cfg configuration, used to determine where to | 590 | * @param cfg configuration, used to determine where to |
591 | * store the time; user can also insist RTC is working | 591 | * store the time; user can also insist RTC is working |
592 | * nicely and disable the feature | 592 | * nicely and disable the feature |
593 | * @return monotonically increasing time | 593 | * @return monotonically increasing time |
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 | */ |
1728 | static struct GNUNET_SCHEDULER_Task *ephemeral_task; | 1742 | static struct GNUNET_SCHEDULER_Task *ephemeral_task; |
1729 | 1743 | ||
1744 | /** | ||
1745 | * Task to run address validation. | ||
1746 | */ | ||
1747 | static 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 | */ | ||
1771 | static void | ||
1772 | free_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 | */ |
2012 | static int | 2054 | static int |
2013 | free_reassembly_cb (void *cls, | 2055 | free_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 | */ |
2912 | static void | 2954 | static void |
2913 | route_message (const struct GNUNET_PeerIdentity *target, | 2955 | route_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 | */ |
3327 | static void | 3369 | static void |
3328 | handle_fragment_box (void *cls, | 3370 | handle_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 | */ |
3501 | static void | 3543 | static void |
3502 | handle_fragment_ack (void *cls, | 3544 | handle_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 | */ |
3740 | static void | 3782 | static void |
3741 | handle_dv_box (void *cls, | 3783 | handle_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 | */ | ||
4356 | static void | ||
4357 | handle_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 | */ |
4609 | static void | 4560 | static void |
4610 | handle_monitor_start (void *cls, | 4561 | handle_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 | */ | ||
4668 | static void | ||
4669 | validation_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 | */ | ||
4679 | static void | ||
4680 | update_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 | */ | ||
4718 | static void | ||
4719 | validation_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 | */ | ||
4737 | static void | ||
4738 | validation_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 | */ | ||
4800 | static int | ||
4801 | check_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 | */ | ||
4828 | static void | ||
4829 | handle_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 | */ | ||
5125 | struct 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 | */ | ||
5148 | static int | ||
5149 | check_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 | */ |
5039 | static int | 5333 | static 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 | */ | ||
5355 | static int | ||
5356 | free_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 | { |