diff options
author | Christian Grothoff <christian@grothoff.org> | 2019-05-19 13:56:22 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2019-05-19 13:56:22 +0200 |
commit | 6e2ca97fb0d3d85c1ef127bc0b9bd3e1e72aa9e8 (patch) | |
tree | ab6fccbfa05730f952c519cb3f397afd7af199aa /src/transport/gnunet-service-tng.c | |
parent | be18b8ecb5232ef5bc718cb8d71c4bcc9f03d2f7 (diff) | |
download | gnunet-6e2ca97fb0d3d85c1ef127bc0b9bd3e1e72aa9e8.tar.gz gnunet-6e2ca97fb0d3d85c1ef127bc0b9bd3e1e72aa9e8.zip |
FC work
Diffstat (limited to 'src/transport/gnunet-service-tng.c')
-rw-r--r-- | src/transport/gnunet-service-tng.c | 809 |
1 files changed, 547 insertions, 262 deletions
diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c index e00c7d573..f009a491b 100644 --- a/src/transport/gnunet-service-tng.c +++ b/src/transport/gnunet-service-tng.c | |||
@@ -25,11 +25,27 @@ | |||
25 | * TODO: | 25 | * TODO: |
26 | * Implement next: | 26 | * Implement next: |
27 | * - FIXME-FC: realize transport-to-transport flow control (needed in case | 27 | * - FIXME-FC: realize transport-to-transport flow control (needed in case |
28 | * communicators do not offer flow control). Note that we may not | 28 | * communicators do not offer flow control). |
29 | * want to simply delay the ACKs as that may cause unnecessary | 29 | * We do transmit FC window sizes now. Left: |
30 | * re-transmissions. => Introduce proper flow and congestion window(s)! | 30 | * for SENDING) |
31 | * - Increment "outbound_fc_window_size_used_kb" on transmission | ||
32 | * - Throttle sending if "outbound_fc_window_size_used_kb" reaches limit | ||
33 | * - Send *new* challenge when we get close to the limit (including | ||
34 | * at the beginning when the limit is zero!) | ||
35 | * - Retransmit challenge if it goes unanswered! | ||
36 | * | ||
37 | * for RECEIVING) | ||
38 | * - increment incoming_fc_window_size_ram_kb when receiving | ||
39 | * incoming packets! | ||
40 | * - OR drop if incoming_fc_window_size_ram goes | ||
41 | * (significantly?) beyond available_fc_window_size_kb | ||
42 | * - decrement incoming_fc_window_size_ram_kb when CORE is done | ||
43 | * with incoming packets! | ||
44 | * - increment incoming_fc_window_size_used_kb when CORE is done | ||
45 | * with incoming packets! | ||
46 | * | ||
31 | * - review retransmission logic, right now there is no smartness there! | 47 | * - review retransmission logic, right now there is no smartness there! |
32 | * => congestion control, flow control, etc [PERFORMANCE-BASICS] | 48 | * => congestion control, etc [PERFORMANCE-BASICS] |
33 | * | 49 | * |
34 | * Optimizations: | 50 | * Optimizations: |
35 | * - When forwarding DV learn messages, if a peer is reached that | 51 | * - When forwarding DV learn messages, if a peer is reached that |
@@ -59,6 +75,14 @@ | |||
59 | * AcknowledgementUUIDP altogether, as they won't be acked! [BANDWIDTH] | 75 | * AcknowledgementUUIDP altogether, as they won't be acked! [BANDWIDTH] |
60 | * (-> have 2nd type of acknowledgment message; low priority, as we | 76 | * (-> have 2nd type of acknowledgment message; low priority, as we |
61 | * do not have an MTU-limited *reliable* communicator) | 77 | * do not have an MTU-limited *reliable* communicator) |
78 | * - Adapt available_fc_window_size_kb, using larger values for high-bandwidth | ||
79 | * and high-latency links *if* we have the RAM [GOODPUT / utilization / stalls] | ||
80 | * - Set last_window_consum_limit_kb promise properly based on | ||
81 | * latency and bandwidth of the respective connection [GOODPUT / utilization / stalls] | ||
82 | * - re-sending challenge response without a challenge when we have | ||
83 | * significantly increased the FC window (upon CORE being done with messages) | ||
84 | * so as to avoid the sender having to give us a fresh challenge [BANDWIDTH] | ||
85 | * Also can re-use signature in this case [CPU]. | ||
62 | * | 86 | * |
63 | * Design realizations / discussion: | 87 | * Design realizations / discussion: |
64 | * - communicators do flow control by calling MQ "notify sent" | 88 | * - communicators do flow control by calling MQ "notify sent" |
@@ -114,6 +138,22 @@ | |||
114 | #define GOODPUT_AGING_SLOTS 4 | 138 | #define GOODPUT_AGING_SLOTS 4 |
115 | 139 | ||
116 | /** | 140 | /** |
141 | * How big is the flow control window size by default; | ||
142 | * limits per-neighbour RAM utilization (in kilobytes). | ||
143 | */ | ||
144 | #define DEFAULT_WINDOW_SIZE_KB 128 | ||
145 | |||
146 | /** | ||
147 | * For how many incoming connections do we try to create a | ||
148 | * virtual link for (at the same time!). This does NOT | ||
149 | * limit the number of incoming connections, just the number | ||
150 | * for which we are actively trying to find working addresses | ||
151 | * in the absence (!) of our own applications wanting the | ||
152 | * link to go up. | ||
153 | */ | ||
154 | #define MAX_INCOMING_REQUEST 16 | ||
155 | |||
156 | /** | ||
117 | * Maximum number of peers we select for forwarding DVInit | 157 | * Maximum number of peers we select for forwarding DVInit |
118 | * messages at the same time (excluding initiator). | 158 | * messages at the same time (excluding initiator). |
119 | */ | 159 | */ |
@@ -818,64 +858,8 @@ struct TransportValidationChallengeMessage | |||
818 | struct ChallengeNonceP challenge; | 858 | struct ChallengeNonceP challenge; |
819 | 859 | ||
820 | /** | 860 | /** |
821 | * Timestamp of the sender, to be copied into the reply | 861 | * Timestamp of the sender, to be copied into the reply to allow |
822 | * to allow sender to calculate RTT. | 862 | * sender to calculate RTT. Must be monotonically increasing! |
823 | */ | ||
824 | struct GNUNET_TIME_AbsoluteNBO sender_time; | ||
825 | }; | ||
826 | |||
827 | |||
828 | /** | ||
829 | * Message send to another peer to answer to a validation challenge | ||
830 | * and at the same time issue a challenge in the other direction. | ||
831 | */ | ||
832 | struct TransportValidationChallengeResponseMessage | ||
833 | { | ||
834 | |||
835 | /** | ||
836 | * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE_RESPONSE | ||
837 | */ | ||
838 | struct GNUNET_MessageHeader header; | ||
839 | |||
840 | /** | ||
841 | * Flow control window size in kilobytes (1024 b), in NBO. | ||
842 | * The receiver can now send this many kilobytes as per | ||
843 | * the @e received_challenge "account". | ||
844 | */ | ||
845 | uint32_t fc_window_size_kb GNUNET_PACKED; | ||
846 | |||
847 | /** | ||
848 | * Challenge returned to the origin by the receiving peer. | ||
849 | */ | ||
850 | struct ChallengeNonceP received_challenge; | ||
851 | |||
852 | /** | ||
853 | * The peer's signature matching the | ||
854 | * #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE purpose. | ||
855 | */ | ||
856 | struct GNUNET_CRYPTO_EddsaSignature signature; | ||
857 | |||
858 | /** | ||
859 | * Fresh challenge created by the sender to be returned | ||
860 | * by the receiving peer. | ||
861 | */ | ||
862 | struct ChallengeNonceP sender_challenge; | ||
863 | |||
864 | /** | ||
865 | * How long does the sender believe the address on | ||
866 | * which the challenge was received to remain valid? | ||
867 | */ | ||
868 | struct GNUNET_TIME_RelativeNBO validity_duration; | ||
869 | |||
870 | /** | ||
871 | * Timestamp of the sender, to be copied into the reply | ||
872 | * to allow sender to calculate RTT. | ||
873 | */ | ||
874 | struct GNUNET_TIME_AbsoluteNBO origin_time; | ||
875 | |||
876 | /** | ||
877 | * Timestamp of the sender, to be copied into the reply | ||
878 | * to allow sender to calculate RTT. | ||
879 | */ | 863 | */ |
880 | struct GNUNET_TIME_AbsoluteNBO sender_time; | 864 | struct GNUNET_TIME_AbsoluteNBO sender_time; |
881 | }; | 865 | }; |
@@ -1224,7 +1208,84 @@ struct VirtualLink | |||
1224 | uint64_t message_uuid_ctr; | 1208 | uint64_t message_uuid_ctr; |
1225 | 1209 | ||
1226 | /** | 1210 | /** |
1227 | * How many more messages can we send to core before we exhaust | 1211 | * Sender timestamp of @e n_challenge, used to generate out-of-order |
1212 | * challenges (as sender's timestamps must be monotonically | ||
1213 | * increasing). Note that we do not persist this monotonic time | ||
1214 | * as we do not really have to worry about ancient flow control | ||
1215 | * window sizes after restarts. | ||
1216 | */ | ||
1217 | struct GNUNET_TIME_Absolute n_challenge_time; | ||
1218 | |||
1219 | /** | ||
1220 | * Last challenge we received from @a n, for which we created the | ||
1221 | * flow control window given in @e fc_window_size_kb. | ||
1222 | */ | ||
1223 | struct ChallengeNonceP n_challenge; | ||
1224 | |||
1225 | /** | ||
1226 | * Last challenge we used with @a n for flow control. If we receive | ||
1227 | * window size increases for a different challenge, they are | ||
1228 | * out-of-order and must be discarded! | ||
1229 | */ | ||
1230 | struct ChallengeNonceP my_challenge; | ||
1231 | |||
1232 | /** | ||
1233 | * Memory allocated for this virtual link. Expresses how much RAM | ||
1234 | * we are willing to allocate to this virtual link. OPTIMIZE-ME: | ||
1235 | * Can be adapted to dedicate more RAM to links that need it, while | ||
1236 | * sticking to some overall RAM limit. For now, set to | ||
1237 | * #DEFAULT_WINDOW_SIZE_KB. | ||
1238 | */ | ||
1239 | uint32_t available_fc_window_size_kb; | ||
1240 | |||
1241 | /** | ||
1242 | * Memory actually used to buffer packets on this virtual link. | ||
1243 | * Expresses how much RAM we are currently using for virtual link. | ||
1244 | * Note that once CORE is done with a packet, we decrement the value | ||
1245 | * here. | ||
1246 | */ | ||
1247 | uint32_t incoming_fc_window_size_ram_kb; | ||
1248 | |||
1249 | /** | ||
1250 | * Last flow control window size we provided to the other peer, in | ||
1251 | * kilobytes (1024 b). We are allowing the other peer to send this | ||
1252 | * many kilobytes as per its last @e n_challenge "account". | ||
1253 | */ | ||
1254 | uint32_t incoming_fc_window_size_kb; | ||
1255 | |||
1256 | /** | ||
1257 | * How many bytes could we still get from the previous flow control | ||
1258 | * window, in kilobytes (1024 b). We need to consider this value | ||
1259 | * when calculating what we allow for the current window due to | ||
1260 | * the possibility of out-of-order challenges. | ||
1261 | */ | ||
1262 | uint32_t last_fc_window_size_remaining_kb; | ||
1263 | |||
1264 | /** | ||
1265 | * How much of the window did the other peer successfully use (and | ||
1266 | * we already passed it on to CORE)? Must be below @e | ||
1267 | * incoming_fc_window_size_kb. We should effectively signal the | ||
1268 | * other peer that the window is this much bigger at the next | ||
1269 | * opportunity / challenge. | ||
1270 | */ | ||
1271 | uint32_t incoming_fc_window_size_used_kb; | ||
1272 | |||
1273 | /** | ||
1274 | * Our current flow control window size in kilobytes (1024 b). We | ||
1275 | * are allowed to transmit this many kilobytes to @a n as per | ||
1276 | * our @e my_challenge "account". | ||
1277 | */ | ||
1278 | uint32_t outbound_fc_window_size_kb; | ||
1279 | |||
1280 | /** | ||
1281 | * How much of our current flow control window size have we | ||
1282 | * used (in kilobytes (1024 b)). Must be below | ||
1283 | * @e outbound_fc_window_size_kb. | ||
1284 | */ | ||
1285 | uint32_t outbound_fc_window_size_used_kb; | ||
1286 | |||
1287 | /** | ||
1288 | * How many more messages can we send to CORE before we exhaust | ||
1228 | * the receive window of CORE for this peer? If this hits zero, | 1289 | * the receive window of CORE for this peer? If this hits zero, |
1229 | * we must tell communicators to stop providing us more messages | 1290 | * we must tell communicators to stop providing us more messages |
1230 | * for this peer. In fact, the window can go negative as we | 1291 | * for this peer. In fact, the window can go negative as we |
@@ -1787,6 +1848,35 @@ struct Neighbour | |||
1787 | 1848 | ||
1788 | 1849 | ||
1789 | /** | 1850 | /** |
1851 | * Another peer attempted to talk to us, we should try to establish | ||
1852 | * a connection in the other direction. | ||
1853 | */ | ||
1854 | struct IncomingRequest | ||
1855 | { | ||
1856 | |||
1857 | /** | ||
1858 | * Kept in a DLL. | ||
1859 | */ | ||
1860 | struct IncomingRequest *next; | ||
1861 | |||
1862 | /** | ||
1863 | * Kept in a DLL. | ||
1864 | */ | ||
1865 | struct IncomingRequest *prev; | ||
1866 | |||
1867 | /** | ||
1868 | * Handle for watching the peerstore for HELLOs for this peer. | ||
1869 | */ | ||
1870 | struct GNUNET_PEERSTORE_WatchContext *wc; | ||
1871 | |||
1872 | /** | ||
1873 | * Which peer is this about? | ||
1874 | */ | ||
1875 | struct GNUNET_PeerIdentity pid; | ||
1876 | }; | ||
1877 | |||
1878 | |||
1879 | /** | ||
1790 | * A peer that an application (client) would like us to talk to directly. | 1880 | * A peer that an application (client) would like us to talk to directly. |
1791 | */ | 1881 | */ |
1792 | struct PeerRequest | 1882 | struct PeerRequest |
@@ -2357,6 +2447,13 @@ struct ValidationState | |||
2357 | struct GNUNET_PEERSTORE_StoreContext *sc; | 2447 | struct GNUNET_PEERSTORE_StoreContext *sc; |
2358 | 2448 | ||
2359 | /** | 2449 | /** |
2450 | * Self-imposed limit on the previous flow control window. (May be zero, | ||
2451 | * if we never used data from the previous window or are establishing the | ||
2452 | * connection for the first time). | ||
2453 | */ | ||
2454 | uint32_t last_window_consum_limit_kb; | ||
2455 | |||
2456 | /** | ||
2360 | * We are technically ready to send the challenge, but we are waiting for | 2457 | * We are technically ready to send the challenge, but we are waiting for |
2361 | * the respective queue to become available for transmission. | 2458 | * the respective queue to become available for transmission. |
2362 | */ | 2459 | */ |
@@ -2545,6 +2642,23 @@ static struct PendingAcknowledgement *pa_head; | |||
2545 | static struct PendingAcknowledgement *pa_tail; | 2642 | static struct PendingAcknowledgement *pa_tail; |
2546 | 2643 | ||
2547 | /** | 2644 | /** |
2645 | * List of incomming connections where we are trying | ||
2646 | * to get a connection back established. Length | ||
2647 | * kept in #ir_total. | ||
2648 | */ | ||
2649 | static struct IncomingRequest *ir_head; | ||
2650 | |||
2651 | /** | ||
2652 | * Tail of DLL starting at #ir_head. | ||
2653 | */ | ||
2654 | static struct IncomingRequest *ir_tail; | ||
2655 | |||
2656 | /** | ||
2657 | * Length of the DLL starting at #ir_head. | ||
2658 | */ | ||
2659 | static unsigned int ir_total; | ||
2660 | |||
2661 | /** | ||
2548 | * Generator of `logging_uuid` in `struct PendingMessage`. | 2662 | * Generator of `logging_uuid` in `struct PendingMessage`. |
2549 | */ | 2663 | */ |
2550 | static unsigned long long logging_uuid_gen; | 2664 | static unsigned long long logging_uuid_gen; |
@@ -2587,6 +2701,22 @@ get_age () | |||
2587 | 2701 | ||
2588 | 2702 | ||
2589 | /** | 2703 | /** |
2704 | * Release @a ir data structure. | ||
2705 | * | ||
2706 | * @param ir data structure to release | ||
2707 | */ | ||
2708 | static void | ||
2709 | free_incoming_request (struct IncomingRequest *ir) | ||
2710 | { | ||
2711 | GNUNET_CONTAINER_DLL_remove (ir_head, ir_tail, ir); | ||
2712 | GNUNET_assert (ir_total > 0); | ||
2713 | ir_total--; | ||
2714 | GNUNET_PEERSTORE_watch_cancel (ir->wc); | ||
2715 | GNUNET_free (ir); | ||
2716 | } | ||
2717 | |||
2718 | |||
2719 | /** | ||
2590 | * Release @a pa data structure. | 2720 | * Release @a pa data structure. |
2591 | * | 2721 | * |
2592 | * @param pa data structure to release | 2722 | * @param pa data structure to release |
@@ -5688,6 +5818,7 @@ activate_core_visible_dv_path (struct DistanceVectorHop *hop) | |||
5688 | vl->dv = dv; | 5818 | vl->dv = dv; |
5689 | dv->vl = vl; | 5819 | dv->vl = vl; |
5690 | vl->core_recv_window = RECV_WINDOW_SIZE; | 5820 | vl->core_recv_window = RECV_WINDOW_SIZE; |
5821 | vl->available_fc_window_size_kb = DEFAULT_WINDOW_SIZE_KB; | ||
5691 | vl->visibility_task = | 5822 | vl->visibility_task = |
5692 | GNUNET_SCHEDULER_add_at (hop->path_valid_until, &check_link_down, vl); | 5823 | GNUNET_SCHEDULER_add_at (hop->path_valid_until, &check_link_down, vl); |
5693 | GNUNET_break (GNUNET_YES == | 5824 | GNUNET_break (GNUNET_YES == |
@@ -7052,6 +7183,270 @@ check_incoming_msg (void *cls, | |||
7052 | 7183 | ||
7053 | 7184 | ||
7054 | /** | 7185 | /** |
7186 | * We received a @a challenge from another peer, check if we can | ||
7187 | * increase the flow control window to that peer. | ||
7188 | * | ||
7189 | * @param vl virtual link | ||
7190 | * @param challenge the challenge we received | ||
7191 | * @param sender_time when did the peer send the message? | ||
7192 | * @param last_window_consum_limit_kb maximum number of kb the sender | ||
7193 | * promises to use of the previous window (if any) | ||
7194 | */ | ||
7195 | static void | ||
7196 | update_fc_window (struct VirtualLink *vl, | ||
7197 | const struct ChallengeNonceP *challenge, | ||
7198 | struct GNUNET_TIME_Absolute sender_time, | ||
7199 | uint32_t last_window_consum_limit_kb) | ||
7200 | { | ||
7201 | if (0 == GNUNET_memcmp (challenge, &vl->n_challenge)) | ||
7202 | { | ||
7203 | uint32_t avail; | ||
7204 | |||
7205 | /* Challenge identical to last one, update | ||
7206 | @a last_window_consum_limit_kb (to minimum) */ | ||
7207 | vl->last_fc_window_size_remaining_kb = | ||
7208 | GNUNET_MIN (last_window_consum_limit_kb, | ||
7209 | vl->last_fc_window_size_remaining_kb); | ||
7210 | /* window could have shrunk! */ | ||
7211 | if (vl->available_fc_window_size_kb > vl->last_fc_window_size_remaining_kb) | ||
7212 | avail = | ||
7213 | vl->available_fc_window_size_kb - vl->last_fc_window_size_remaining_kb; | ||
7214 | else | ||
7215 | avail = 0; | ||
7216 | /* guard against integer overflow */ | ||
7217 | if (vl->incoming_fc_window_size_used_kb + avail >= | ||
7218 | vl->incoming_fc_window_size_used_kb) | ||
7219 | vl->incoming_fc_window_size_kb = | ||
7220 | vl->incoming_fc_window_size_used_kb + avail; | ||
7221 | else | ||
7222 | vl->incoming_fc_window_size_kb = UINT32_MAX; | ||
7223 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
7224 | "Updated window to %u/%u kb (%u used) for virtual link to %s!\n", | ||
7225 | vl->incoming_fc_window_size_kb, | ||
7226 | vl->available_fc_window_size_kb, | ||
7227 | vl->incoming_fc_window_size_used_kb, | ||
7228 | GNUNET_i2s (&vl->target)); | ||
7229 | return; | ||
7230 | } | ||
7231 | if (vl->n_challenge_time.abs_value_us >= sender_time.abs_value_us) | ||
7232 | { | ||
7233 | GNUNET_STATISTICS_update (GST_stats, | ||
7234 | "# Challenges ignored: sender time not increasing", | ||
7235 | 1, | ||
7236 | GNUNET_NO); | ||
7237 | return; | ||
7238 | } | ||
7239 | /* new challenge! */ | ||
7240 | if (vl->incoming_fc_window_size_used_kb > last_window_consum_limit_kb) | ||
7241 | { | ||
7242 | /* lying peer: it already used more than it promised it would ever use! */ | ||
7243 | GNUNET_break_op (0); | ||
7244 | last_window_consum_limit_kb = vl->incoming_fc_window_size_used_kb; | ||
7245 | } | ||
7246 | /* What remains is at most the difference between what we already processed | ||
7247 | and what the sender promises to limit itself to. */ | ||
7248 | vl->last_fc_window_size_remaining_kb = | ||
7249 | last_window_consum_limit_kb - vl->incoming_fc_window_size_used_kb; | ||
7250 | vl->n_challenge = *challenge; | ||
7251 | vl->n_challenge_time = sender_time; | ||
7252 | vl->incoming_fc_window_size_used_kb = 0; | ||
7253 | /* window could have shrunk! */ | ||
7254 | if (vl->available_fc_window_size_kb > vl->last_fc_window_size_remaining_kb) | ||
7255 | vl->incoming_fc_window_size_kb = | ||
7256 | vl->available_fc_window_size_kb - vl->last_fc_window_size_remaining_kb; | ||
7257 | else | ||
7258 | vl->incoming_fc_window_size_kb = 0; | ||
7259 | GNUNET_log ( | ||
7260 | GNUNET_ERROR_TYPE_DEBUG, | ||
7261 | "New window at %u/%u kb (%u left on previous) for virtual link to %s!\n", | ||
7262 | vl->incoming_fc_window_size_kb, | ||
7263 | vl->available_fc_window_size_kb, | ||
7264 | vl->last_fc_window_size_remaining_kb, | ||
7265 | GNUNET_i2s (&vl->target)); | ||
7266 | } | ||
7267 | |||
7268 | |||
7269 | /** | ||
7270 | * Closure for #check_known_address. | ||
7271 | */ | ||
7272 | struct CheckKnownAddressContext | ||
7273 | { | ||
7274 | /** | ||
7275 | * Set to the address we are looking for. | ||
7276 | */ | ||
7277 | const char *address; | ||
7278 | |||
7279 | /** | ||
7280 | * Set to a matching validation state, if one was found. | ||
7281 | */ | ||
7282 | struct ValidationState *vs; | ||
7283 | }; | ||
7284 | |||
7285 | |||
7286 | /** | ||
7287 | * Test if the validation state in @a value matches the | ||
7288 | * address from @a cls. | ||
7289 | * | ||
7290 | * @param cls a `struct CheckKnownAddressContext` | ||
7291 | * @param pid unused (must match though) | ||
7292 | * @param value a `struct ValidationState` | ||
7293 | * @return #GNUNET_OK if not matching, #GNUNET_NO if match found | ||
7294 | */ | ||
7295 | static int | ||
7296 | check_known_address (void *cls, | ||
7297 | const struct GNUNET_PeerIdentity *pid, | ||
7298 | void *value) | ||
7299 | { | ||
7300 | struct CheckKnownAddressContext *ckac = cls; | ||
7301 | struct ValidationState *vs = value; | ||
7302 | |||
7303 | (void) pid; | ||
7304 | if (0 != strcmp (vs->address, ckac->address)) | ||
7305 | return GNUNET_OK; | ||
7306 | ckac->vs = vs; | ||
7307 | return GNUNET_NO; | ||
7308 | } | ||
7309 | |||
7310 | |||
7311 | /** | ||
7312 | * Task run periodically to validate some address based on #validation_heap. | ||
7313 | * | ||
7314 | * @param cls NULL | ||
7315 | */ | ||
7316 | static void | ||
7317 | validation_start_cb (void *cls); | ||
7318 | |||
7319 | |||
7320 | /** | ||
7321 | * Set the time for next_challenge of @a vs to @a new_time. | ||
7322 | * Updates the heap and if necessary reschedules the job. | ||
7323 | * | ||
7324 | * @param vs validation state to update | ||
7325 | * @param new_time new time for revalidation | ||
7326 | */ | ||
7327 | static void | ||
7328 | update_next_challenge_time (struct ValidationState *vs, | ||
7329 | struct GNUNET_TIME_Absolute new_time) | ||
7330 | { | ||
7331 | struct GNUNET_TIME_Relative delta; | ||
7332 | |||
7333 | if (new_time.abs_value_us == vs->next_challenge.abs_value_us) | ||
7334 | return; /* be lazy */ | ||
7335 | vs->next_challenge = new_time; | ||
7336 | if (NULL == vs->hn) | ||
7337 | vs->hn = | ||
7338 | GNUNET_CONTAINER_heap_insert (validation_heap, vs, new_time.abs_value_us); | ||
7339 | else | ||
7340 | GNUNET_CONTAINER_heap_update_cost (vs->hn, new_time.abs_value_us); | ||
7341 | if ((vs != GNUNET_CONTAINER_heap_peek (validation_heap)) && | ||
7342 | (NULL != validation_task)) | ||
7343 | return; | ||
7344 | if (NULL != validation_task) | ||
7345 | GNUNET_SCHEDULER_cancel (validation_task); | ||
7346 | /* randomize a bit */ | ||
7347 | delta.rel_value_us = | ||
7348 | GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
7349 | MIN_DELAY_ADDRESS_VALIDATION.rel_value_us); | ||
7350 | new_time = GNUNET_TIME_absolute_add (new_time, delta); | ||
7351 | validation_task = | ||
7352 | GNUNET_SCHEDULER_add_at (new_time, &validation_start_cb, NULL); | ||
7353 | } | ||
7354 | |||
7355 | |||
7356 | /** | ||
7357 | * Start address validation. | ||
7358 | * | ||
7359 | * @param pid peer the @a address is for | ||
7360 | * @param address an address to reach @a pid (presumably) | ||
7361 | */ | ||
7362 | static void | ||
7363 | start_address_validation (const struct GNUNET_PeerIdentity *pid, | ||
7364 | const char *address) | ||
7365 | { | ||
7366 | struct GNUNET_TIME_Absolute now; | ||
7367 | struct ValidationState *vs; | ||
7368 | struct CheckKnownAddressContext ckac = {.address = address, .vs = NULL}; | ||
7369 | |||
7370 | (void) GNUNET_CONTAINER_multipeermap_get_multiple (validation_map, | ||
7371 | pid, | ||
7372 | &check_known_address, | ||
7373 | &ckac); | ||
7374 | if (NULL != (vs = ckac.vs)) | ||
7375 | { | ||
7376 | /* if 'vs' is not currently valid, we need to speed up retrying the | ||
7377 | * validation */ | ||
7378 | if (vs->validated_until.abs_value_us < vs->next_challenge.abs_value_us) | ||
7379 | { | ||
7380 | /* reduce backoff as we got a fresh advertisement */ | ||
7381 | vs->challenge_backoff = | ||
7382 | GNUNET_TIME_relative_min (FAST_VALIDATION_CHALLENGE_FREQ, | ||
7383 | GNUNET_TIME_relative_divide (vs->challenge_backoff, | ||
7384 | 2)); | ||
7385 | update_next_challenge_time (vs, | ||
7386 | GNUNET_TIME_relative_to_absolute ( | ||
7387 | vs->challenge_backoff)); | ||
7388 | } | ||
7389 | return; | ||
7390 | } | ||
7391 | now = GNUNET_TIME_absolute_get (); | ||
7392 | vs = GNUNET_new (struct ValidationState); | ||
7393 | vs->pid = *pid; | ||
7394 | vs->valid_until = | ||
7395 | GNUNET_TIME_relative_to_absolute (ADDRESS_VALIDATION_LIFETIME); | ||
7396 | vs->first_challenge_use = now; | ||
7397 | vs->validation_rtt = GNUNET_TIME_UNIT_FOREVER_REL; | ||
7398 | GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, | ||
7399 | &vs->challenge, | ||
7400 | sizeof (vs->challenge)); | ||
7401 | vs->address = GNUNET_strdup (address); | ||
7402 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
7403 | "Starting address validation `%s' of peer %s using challenge %s\n", | ||
7404 | address, | ||
7405 | GNUNET_i2s (pid), | ||
7406 | GNUNET_sh2s (&vs->challenge.value)); | ||
7407 | GNUNET_assert (GNUNET_YES == | ||
7408 | GNUNET_CONTAINER_multipeermap_put ( | ||
7409 | validation_map, | ||
7410 | &vs->pid, | ||
7411 | vs, | ||
7412 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
7413 | update_next_challenge_time (vs, now); | ||
7414 | } | ||
7415 | |||
7416 | |||
7417 | /** | ||
7418 | * Function called by PEERSTORE for each matching record. | ||
7419 | * | ||
7420 | * @param cls closure, a `struct IncomingRequest` | ||
7421 | * @param record peerstore record information | ||
7422 | * @param emsg error message, or NULL if no errors | ||
7423 | */ | ||
7424 | static void | ||
7425 | handle_hello_for_incoming (void *cls, | ||
7426 | const struct GNUNET_PEERSTORE_Record *record, | ||
7427 | const char *emsg) | ||
7428 | { | ||
7429 | struct IncomingRequest *ir = cls; | ||
7430 | const char *val; | ||
7431 | |||
7432 | if (NULL != emsg) | ||
7433 | { | ||
7434 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
7435 | "Got failure from PEERSTORE: %s\n", | ||
7436 | emsg); | ||
7437 | return; | ||
7438 | } | ||
7439 | val = record->value; | ||
7440 | if ((0 == record->value_size) || ('\0' != val[record->value_size - 1])) | ||
7441 | { | ||
7442 | GNUNET_break (0); | ||
7443 | return; | ||
7444 | } | ||
7445 | start_address_validation (&ir->pid, (const char *) record->value); | ||
7446 | } | ||
7447 | |||
7448 | |||
7449 | /** | ||
7055 | * Communicator gave us a transport address validation challenge. Process the | 7450 | * Communicator gave us a transport address validation challenge. Process the |
7056 | * request. | 7451 | * request. |
7057 | * | 7452 | * |
@@ -7065,62 +7460,86 @@ handle_validation_challenge ( | |||
7065 | const struct TransportValidationChallengeMessage *tvc) | 7460 | const struct TransportValidationChallengeMessage *tvc) |
7066 | { | 7461 | { |
7067 | struct CommunicatorMessageContext *cmc = cls; | 7462 | struct CommunicatorMessageContext *cmc = cls; |
7068 | struct TransportValidationResponseMessage *tvr; | 7463 | struct TransportValidationResponseMessage tvr; |
7464 | struct VirtualLink *vl; | ||
7465 | struct GNUNET_TIME_RelativeNBO validity_duration; | ||
7466 | struct IncomingRequest *ir; | ||
7467 | struct Neighbour *n; | ||
7069 | 7468 | ||
7469 | /* We use a validity_duration of 0 for DV-routed messages, | ||
7470 | as we can neither control the validity and need to allow | ||
7471 | the receiver to tell DV paths from direct connections */ | ||
7070 | if (cmc->total_hops > 0) | 7472 | if (cmc->total_hops > 0) |
7071 | { | 7473 | validity_duration = GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_ZERO); |
7072 | /* DV routing is not allowed for validation challenges! */ | 7474 | else |
7073 | GNUNET_break_op (0); | 7475 | validity_duration = cmc->im.expected_address_validity; |
7074 | finish_cmc_handling (cmc); | ||
7075 | return; | ||
7076 | } | ||
7077 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 7476 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
7078 | "Received address validation challenge %s\n", | 7477 | "Received address validation challenge %s\n", |
7079 | GNUNET_sh2s (&tvc->challenge.value)); | 7478 | GNUNET_sh2s (&tvc->challenge.value)); |
7080 | tvr = GNUNET_new (struct TransportValidationResponseMessage); | 7479 | /* If we have a virtual link, we use this mechanism to signal the |
7081 | tvr->header.type = | 7480 | size of the flow control window, and to allow the sender |
7481 | to ask for increases. If for us the virtual link is still down, | ||
7482 | we will always give a window size of zero. */ | ||
7483 | vl = lookup_virtual_link (&cmc->im.sender); | ||
7484 | if (NULL != vl) | ||
7485 | update_fc_window (vl, | ||
7486 | &tvc->challenge, | ||
7487 | GNUNET_TIME_absolute_ntoh (tvc->sender_time), | ||
7488 | ntohl (tvc->last_window_consum_limit_kb)); | ||
7489 | tvr.header.type = | ||
7082 | htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE); | 7490 | htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE); |
7083 | tvr->header.size = htons (sizeof (*tvr)); | 7491 | tvr.header.size = htons (sizeof (tvr)); |
7084 | tvr->challenge = tvc->challenge; | 7492 | tvr.fc_window_size_kb = |
7085 | tvr->origin_time = tvc->sender_time; | 7493 | htonl ((NULL == vl) ? 0 : vl->incoming_fc_window_size_kb); |
7086 | tvr->validity_duration = cmc->im.expected_address_validity; | 7494 | tvr.challenge = tvc->challenge; |
7495 | tvr.origin_time = tvc->sender_time; | ||
7496 | tvr.validity_duration = validity_duration; | ||
7087 | { | 7497 | { |
7088 | /* create signature */ | 7498 | /* create signature */ |
7089 | struct TransportValidationPS tvp = | 7499 | struct TransportValidationPS tvp = |
7090 | {.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE), | 7500 | {.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_CHALLENGE), |
7091 | .purpose.size = htonl (sizeof (tvp)), | 7501 | .purpose.size = htonl (sizeof (tvp)), |
7092 | .validity_duration = tvr->validity_duration, | 7502 | .validity_duration = validity_duration, |
7093 | .challenge = tvc->challenge}; | 7503 | .challenge = tvc->challenge}; |
7094 | 7504 | ||
7095 | GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (GST_my_private_key, | 7505 | GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (GST_my_private_key, |
7096 | &tvp.purpose, | 7506 | &tvp.purpose, |
7097 | &tvr->signature)); | 7507 | &tvr.signature)); |
7098 | } | 7508 | } |
7099 | route_message (&cmc->im.sender, | 7509 | route_message (&cmc->im.sender, |
7100 | &tvr->header, | 7510 | &tvr.header, |
7101 | RMO_ANYTHING_GOES | RMO_REDUNDANT); | 7511 | RMO_ANYTHING_GOES | RMO_REDUNDANT); |
7102 | finish_cmc_handling (cmc); | 7512 | finish_cmc_handling (cmc); |
7103 | } | 7513 | if (NULL != vl) |
7104 | 7514 | return; | |
7105 | |||
7106 | /** | ||
7107 | * Communicator gave us a transport address validation challenge. Process the | ||
7108 | * request. | ||
7109 | * | ||
7110 | * @param cls a `struct CommunicatorMessageContext` (must call | ||
7111 | * #finish_cmc_handling() when done) | ||
7112 | * @param tvrc the message that was received | ||
7113 | */ | ||
7114 | static void | ||
7115 | handle_validation_challenge_response ( | ||
7116 | void *cls, | ||
7117 | const struct TransportValidationChallengeResponseMessage *tvrc) | ||
7118 | { | ||
7119 | struct CommunicatorMessageContext *cmc = cls; | ||
7120 | struct TransportValidationResponseMessage *tvr; | ||
7121 | 7515 | ||
7516 | /* For us, the link is still down, but we need bi-directional | ||
7517 | connections (for flow-control and for this to be useful for | ||
7518 | CORE), so we must try to bring the link up! */ | ||
7122 | 7519 | ||
7123 | finish_cmc_handling (cmc); | 7520 | /* (1) Check existing queues, if any, we may be lucky! */ |
7521 | n = lookup_neighbour (&cmc->im.sender); | ||
7522 | if (NULL != n) | ||
7523 | for (struct Queue *q = n->queue_head; NULL != q; q = q->next_neighbour) | ||
7524 | start_address_validation (&cmc->im.sender, q->address); | ||
7525 | /* (2) Also try to see if we have addresses in PEERSTORE for this peer | ||
7526 | we could use */ | ||
7527 | for (ir = ir_head; NULL != ir; ir = ir->next) | ||
7528 | if (0 == GNUNET_memcmp (&ir->pid, &cmc->im.sender)) | ||
7529 | return; /* we are already trying */ | ||
7530 | ir = GNUNET_new (struct IncomingRequest); | ||
7531 | ir->pid = cmc->im.sender; | ||
7532 | GNUNET_CONTAINER_DLL_insert (ir_head, ir_tail, ir); | ||
7533 | ir->wc = GNUNET_PEERSTORE_watch (peerstore, | ||
7534 | "transport", | ||
7535 | &ir->pid, | ||
7536 | GNUNET_PEERSTORE_TRANSPORT_URLADDRESS_KEY, | ||
7537 | &handle_hello_for_incoming, | ||
7538 | ir); | ||
7539 | ir_total++; | ||
7540 | /* Bound attempts we do in parallel here, might otherwise get excessive */ | ||
7541 | while (ir_total > MAX_INCOMING_REQUEST) | ||
7542 | free_incoming_request (ir_head); | ||
7124 | } | 7543 | } |
7125 | 7544 | ||
7126 | 7545 | ||
@@ -7189,51 +7608,6 @@ peerstore_store_validation_cb (void *cls, int success) | |||
7189 | 7608 | ||
7190 | 7609 | ||
7191 | /** | 7610 | /** |
7192 | * Task run periodically to validate some address based on #validation_heap. | ||
7193 | * | ||
7194 | * @param cls NULL | ||
7195 | */ | ||
7196 | static void | ||
7197 | validation_start_cb (void *cls); | ||
7198 | |||
7199 | |||
7200 | /** | ||
7201 | * Set the time for next_challenge of @a vs to @a new_time. | ||
7202 | * Updates the heap and if necessary reschedules the job. | ||
7203 | * | ||
7204 | * @param vs validation state to update | ||
7205 | * @param new_time new time for revalidation | ||
7206 | */ | ||
7207 | static void | ||
7208 | update_next_challenge_time (struct ValidationState *vs, | ||
7209 | struct GNUNET_TIME_Absolute new_time) | ||
7210 | { | ||
7211 | struct GNUNET_TIME_Relative delta; | ||
7212 | |||
7213 | if (new_time.abs_value_us == vs->next_challenge.abs_value_us) | ||
7214 | return; /* be lazy */ | ||
7215 | vs->next_challenge = new_time; | ||
7216 | if (NULL == vs->hn) | ||
7217 | vs->hn = | ||
7218 | GNUNET_CONTAINER_heap_insert (validation_heap, vs, new_time.abs_value_us); | ||
7219 | else | ||
7220 | GNUNET_CONTAINER_heap_update_cost (vs->hn, new_time.abs_value_us); | ||
7221 | if ((vs != GNUNET_CONTAINER_heap_peek (validation_heap)) && | ||
7222 | (NULL != validation_task)) | ||
7223 | return; | ||
7224 | if (NULL != validation_task) | ||
7225 | GNUNET_SCHEDULER_cancel (validation_task); | ||
7226 | /* randomize a bit */ | ||
7227 | delta.rel_value_us = | ||
7228 | GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
7229 | MIN_DELAY_ADDRESS_VALIDATION.rel_value_us); | ||
7230 | new_time = GNUNET_TIME_absolute_add (new_time, delta); | ||
7231 | validation_task = | ||
7232 | GNUNET_SCHEDULER_add_at (new_time, &validation_start_cb, NULL); | ||
7233 | } | ||
7234 | |||
7235 | |||
7236 | /** | ||
7237 | * Find the queue matching @a pid and @a address. | 7611 | * Find the queue matching @a pid and @a address. |
7238 | * | 7612 | * |
7239 | * @param pid peer the queue must go to | 7613 | * @param pid peer the queue must go to |
@@ -7387,10 +7761,23 @@ handle_validation_response ( | |||
7387 | if (NULL != vl) | 7761 | if (NULL != vl) |
7388 | { | 7762 | { |
7389 | /* Link was already up, remember n is also now available and we are done */ | 7763 | /* Link was already up, remember n is also now available and we are done */ |
7390 | vl->n = n; | 7764 | if (NULL == vl->n) |
7391 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 7765 | { |
7392 | "Virtual link to %s could now also direct neighbour!\n", | 7766 | vl->n = n; |
7393 | GNUNET_i2s (&vs->pid)); | 7767 | n->vl = vl; |
7768 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
7769 | "Virtual link to %s could now also direct neighbour!\n", | ||
7770 | GNUNET_i2s (&vs->pid)); | ||
7771 | } | ||
7772 | else | ||
7773 | { | ||
7774 | GNUNET_assert (n == vl->n); | ||
7775 | } | ||
7776 | if (0 == GNUNET_memcmp (&vl->my_challenge, &tvr->challenge)) | ||
7777 | { | ||
7778 | /* Update window size if the challenge matches */ | ||
7779 | vl->outbound_fc_window_size_kb = ntohl (tvr->fc_window_size_kb); | ||
7780 | } | ||
7394 | return; | 7781 | return; |
7395 | } | 7782 | } |
7396 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 7783 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
@@ -7401,6 +7788,9 @@ handle_validation_response ( | |||
7401 | vl->n = n; | 7788 | vl->n = n; |
7402 | n->vl = vl; | 7789 | n->vl = vl; |
7403 | vl->core_recv_window = RECV_WINDOW_SIZE; | 7790 | vl->core_recv_window = RECV_WINDOW_SIZE; |
7791 | vl->available_fc_window_size_kb = DEFAULT_WINDOW_SIZE_KB; | ||
7792 | vl->outbound_fc_window_size_kb = ntohl (tvr->fc_window_size_kb); | ||
7793 | vl->my_challenge = tvr->challenge; | ||
7404 | vl->visibility_task = | 7794 | vl->visibility_task = |
7405 | GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl); | 7795 | GNUNET_SCHEDULER_add_at (q->validated_until, &check_link_down, vl); |
7406 | GNUNET_break (GNUNET_YES == | 7796 | GNUNET_break (GNUNET_YES == |
@@ -7479,11 +7869,6 @@ demultiplex_with_cmc (struct CommunicatorMessageContext *cmc, | |||
7479 | struct TransportValidationChallengeMessage, | 7869 | struct TransportValidationChallengeMessage, |
7480 | &cmc), | 7870 | &cmc), |
7481 | GNUNET_MQ_hd_fixed_size ( | 7871 | GNUNET_MQ_hd_fixed_size ( |
7482 | validation_challenge_response, | ||
7483 | GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE_RESPONSE, | ||
7484 | struct TransportValidationChallengeResponseMessage, | ||
7485 | &cmc), | ||
7486 | GNUNET_MQ_hd_fixed_size ( | ||
7487 | validation_response, | 7872 | validation_response, |
7488 | GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE, | 7873 | GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_RESPONSE, |
7489 | struct TransportValidationResponseMessage, | 7874 | struct TransportValidationResponseMessage, |
@@ -8398,11 +8783,11 @@ validation_transmit_on_queue (struct Queue *q, struct ValidationState *vs) | |||
8398 | { | 8783 | { |
8399 | struct TransportValidationChallengeMessage tvc; | 8784 | struct TransportValidationChallengeMessage tvc; |
8400 | 8785 | ||
8401 | vs->last_challenge_use = GNUNET_TIME_absolute_get (); | 8786 | vs->last_challenge_use = GNUNET_TIME_absolute_get_monotonic (GST_cfg); |
8402 | tvc.header.type = | 8787 | tvc.header.type = |
8403 | htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE); | 8788 | htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_VALIDATION_CHALLENGE); |
8404 | tvc.header.size = htons (sizeof (tvc)); | 8789 | tvc.header.size = htons (sizeof (tvc)); |
8405 | tvc.last_window_consum_limit_kb = htonl (0); // FIXME! | 8790 | tvc.last_window_consum_limit_kb = htonl (vs->last_window_consum_limit_kb); |
8406 | tvc.challenge = vs->challenge; | 8791 | tvc.challenge = vs->challenge; |
8407 | tvc.sender_time = GNUNET_TIME_absolute_hton (vs->last_challenge_use); | 8792 | tvc.sender_time = GNUNET_TIME_absolute_hton (vs->last_challenge_use); |
8408 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 8793 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
@@ -8893,119 +9278,16 @@ handle_suggest_cancel (void *cls, const struct ExpressPreferenceMessage *msg) | |||
8893 | 9278 | ||
8894 | 9279 | ||
8895 | /** | 9280 | /** |
8896 | * Closure for #check_known_address. | ||
8897 | */ | ||
8898 | struct CheckKnownAddressContext | ||
8899 | { | ||
8900 | /** | ||
8901 | * Set to the address we are looking for. | ||
8902 | */ | ||
8903 | const char *address; | ||
8904 | |||
8905 | /** | ||
8906 | * Set to a matching validation state, if one was found. | ||
8907 | */ | ||
8908 | struct ValidationState *vs; | ||
8909 | }; | ||
8910 | |||
8911 | |||
8912 | /** | ||
8913 | * Test if the validation state in @a value matches the | ||
8914 | * address from @a cls. | ||
8915 | * | ||
8916 | * @param cls a `struct CheckKnownAddressContext` | ||
8917 | * @param pid unused (must match though) | ||
8918 | * @param value a `struct ValidationState` | ||
8919 | * @return #GNUNET_OK if not matching, #GNUNET_NO if match found | ||
8920 | */ | ||
8921 | static int | ||
8922 | check_known_address (void *cls, | ||
8923 | const struct GNUNET_PeerIdentity *pid, | ||
8924 | void *value) | ||
8925 | { | ||
8926 | struct CheckKnownAddressContext *ckac = cls; | ||
8927 | struct ValidationState *vs = value; | ||
8928 | |||
8929 | (void) pid; | ||
8930 | if (0 != strcmp (vs->address, ckac->address)) | ||
8931 | return GNUNET_OK; | ||
8932 | ckac->vs = vs; | ||
8933 | return GNUNET_NO; | ||
8934 | } | ||
8935 | |||
8936 | |||
8937 | /** | ||
8938 | * Start address validation. | ||
8939 | * | ||
8940 | * @param pid peer the @a address is for | ||
8941 | * @param address an address to reach @a pid (presumably) | ||
8942 | */ | ||
8943 | static void | ||
8944 | start_address_validation (const struct GNUNET_PeerIdentity *pid, | ||
8945 | const char *address) | ||
8946 | { | ||
8947 | struct GNUNET_TIME_Absolute now; | ||
8948 | struct ValidationState *vs; | ||
8949 | struct CheckKnownAddressContext ckac = {.address = address, .vs = NULL}; | ||
8950 | |||
8951 | (void) GNUNET_CONTAINER_multipeermap_get_multiple (validation_map, | ||
8952 | pid, | ||
8953 | &check_known_address, | ||
8954 | &ckac); | ||
8955 | if (NULL != (vs = ckac.vs)) | ||
8956 | { | ||
8957 | /* if 'vs' is not currently valid, we need to speed up retrying the | ||
8958 | * validation */ | ||
8959 | if (vs->validated_until.abs_value_us < vs->next_challenge.abs_value_us) | ||
8960 | { | ||
8961 | /* reduce backoff as we got a fresh advertisement */ | ||
8962 | vs->challenge_backoff = | ||
8963 | GNUNET_TIME_relative_min (FAST_VALIDATION_CHALLENGE_FREQ, | ||
8964 | GNUNET_TIME_relative_divide (vs->challenge_backoff, | ||
8965 | 2)); | ||
8966 | update_next_challenge_time (vs, | ||
8967 | GNUNET_TIME_relative_to_absolute ( | ||
8968 | vs->challenge_backoff)); | ||
8969 | } | ||
8970 | return; | ||
8971 | } | ||
8972 | now = GNUNET_TIME_absolute_get (); | ||
8973 | vs = GNUNET_new (struct ValidationState); | ||
8974 | vs->pid = *pid; | ||
8975 | vs->valid_until = | ||
8976 | GNUNET_TIME_relative_to_absolute (ADDRESS_VALIDATION_LIFETIME); | ||
8977 | vs->first_challenge_use = now; | ||
8978 | vs->validation_rtt = GNUNET_TIME_UNIT_FOREVER_REL; | ||
8979 | GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, | ||
8980 | &vs->challenge, | ||
8981 | sizeof (vs->challenge)); | ||
8982 | vs->address = GNUNET_strdup (address); | ||
8983 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
8984 | "Starting address validation `%s' of peer %s using challenge %s\n", | ||
8985 | address, | ||
8986 | GNUNET_i2s (pid), | ||
8987 | GNUNET_sh2s (&vs->challenge.value)); | ||
8988 | GNUNET_assert (GNUNET_YES == | ||
8989 | GNUNET_CONTAINER_multipeermap_put ( | ||
8990 | validation_map, | ||
8991 | &vs->pid, | ||
8992 | vs, | ||
8993 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
8994 | update_next_challenge_time (vs, now); | ||
8995 | } | ||
8996 | |||
8997 | |||
8998 | /** | ||
8999 | * Function called by PEERSTORE for each matching record. | 9281 | * Function called by PEERSTORE for each matching record. |
9000 | * | 9282 | * |
9001 | * @param cls closure | 9283 | * @param cls closure, a `struct PeerRequest` |
9002 | * @param record peerstore record information | 9284 | * @param record peerstore record information |
9003 | * @param emsg error message, or NULL if no errors | 9285 | * @param emsg error message, or NULL if no errors |
9004 | */ | 9286 | */ |
9005 | static void | 9287 | static void |
9006 | handle_hello (void *cls, | 9288 | handle_hello_for_client (void *cls, |
9007 | const struct GNUNET_PEERSTORE_Record *record, | 9289 | const struct GNUNET_PEERSTORE_Record *record, |
9008 | const char *emsg) | 9290 | const char *emsg) |
9009 | { | 9291 | { |
9010 | struct PeerRequest *pr = cls; | 9292 | struct PeerRequest *pr = cls; |
9011 | const char *val; | 9293 | const char *val; |
@@ -9077,7 +9359,7 @@ handle_suggest (void *cls, const struct ExpressPreferenceMessage *msg) | |||
9077 | "transport", | 9359 | "transport", |
9078 | &pr->pid, | 9360 | &pr->pid, |
9079 | GNUNET_PEERSTORE_TRANSPORT_URLADDRESS_KEY, | 9361 | GNUNET_PEERSTORE_TRANSPORT_URLADDRESS_KEY, |
9080 | &handle_hello, | 9362 | &handle_hello_for_client, |
9081 | pr); | 9363 | pr); |
9082 | GNUNET_SERVICE_client_continue (tc->client); | 9364 | GNUNET_SERVICE_client_continue (tc->client); |
9083 | } | 9365 | } |
@@ -9286,6 +9568,9 @@ do_shutdown (void *cls) | |||
9286 | NULL); | 9568 | NULL); |
9287 | GNUNET_CONTAINER_multipeermap_destroy (validation_map); | 9569 | GNUNET_CONTAINER_multipeermap_destroy (validation_map); |
9288 | validation_map = NULL; | 9570 | validation_map = NULL; |
9571 | while (NULL != ir_head) | ||
9572 | free_incoming_request (ir_head); | ||
9573 | GNUNET_assert (0 == ir_total); | ||
9289 | while (NULL != (lle = lle_head)) | 9574 | while (NULL != (lle = lle_head)) |
9290 | { | 9575 | { |
9291 | GNUNET_CONTAINER_DLL_remove (lle_head, lle_tail, lle); | 9576 | GNUNET_CONTAINER_DLL_remove (lle_head, lle_tail, lle); |