diff options
author | irungentoo <irungentoo@gmail.com> | 2014-05-12 14:07:03 -0400 |
---|---|---|
committer | irungentoo <irungentoo@gmail.com> | 2014-05-12 14:07:03 -0400 |
commit | 10da970e0dfcb21fda4da96635b690065375daff (patch) | |
tree | f2459735e1d51906e063b3288b60f41cd287b47f /toxcore/ping.c | |
parent | 87cec792062a755675e53b5603049cdb067aa70f (diff) |
Added ping_array, a special efficient array for use in operations
that require sending ping type packets.
Made ping packets use it.
Diffstat (limited to 'toxcore/ping.c')
-rw-r--r-- | toxcore/ping.c | 135 |
1 files changed, 33 insertions, 102 deletions
diff --git a/toxcore/ping.c b/toxcore/ping.c index 35aab86f..52817cd6 100644 --- a/toxcore/ping.c +++ b/toxcore/ping.c | |||
@@ -34,6 +34,7 @@ | |||
34 | 34 | ||
35 | #include "network.h" | 35 | #include "network.h" |
36 | #include "util.h" | 36 | #include "util.h" |
37 | #include "ping_array.h" | ||
37 | 38 | ||
38 | #define PING_NUM_MAX 512 | 39 | #define PING_NUM_MAX 512 |
39 | 40 | ||
@@ -43,109 +44,18 @@ | |||
43 | /* Ping newly announced nodes to ping per TIME_TO_PING seconds*/ | 44 | /* Ping newly announced nodes to ping per TIME_TO_PING seconds*/ |
44 | #define TIME_TO_PING 3 | 45 | #define TIME_TO_PING 3 |
45 | 46 | ||
46 | typedef struct { | ||
47 | IP_Port ip_port; | ||
48 | uint64_t id; | ||
49 | uint64_t timestamp; | ||
50 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; | ||
51 | } pinged_t; | ||
52 | 47 | ||
53 | struct PING { | 48 | struct PING { |
54 | DHT *dht; | 49 | DHT *dht; |
55 | 50 | ||
56 | pinged_t pings[PING_NUM_MAX]; | 51 | Ping_Array ping_array; |
57 | size_t num_pings; | ||
58 | size_t pos_pings; | ||
59 | |||
60 | Node_format to_ping[MAX_TO_PING]; | 52 | Node_format to_ping[MAX_TO_PING]; |
61 | uint64_t last_to_ping; | 53 | uint64_t last_to_ping; |
62 | }; | 54 | }; |
63 | 55 | ||
64 | static int is_ping_timeout(uint64_t time) | ||
65 | { | ||
66 | return is_timeout(time, PING_TIMEOUT); | ||
67 | } | ||
68 | |||
69 | static void remove_timeouts(PING *ping) // O(n) | ||
70 | { | ||
71 | size_t i, id; | ||
72 | size_t new_pos = ping->pos_pings; | ||
73 | size_t new_num = ping->num_pings; | ||
74 | |||
75 | // Loop through buffer, oldest first. | ||
76 | for (i = 0; i < ping->num_pings; i++) { | ||
77 | id = (ping->pos_pings + i) % PING_NUM_MAX; | ||
78 | |||
79 | if (is_ping_timeout(ping->pings[id].timestamp)) { | ||
80 | new_pos++; | ||
81 | new_num--; | ||
82 | } | ||
83 | // Break here because list is sorted. | ||
84 | else { | ||
85 | break; | ||
86 | } | ||
87 | } | ||
88 | |||
89 | ping->num_pings = new_num; | ||
90 | ping->pos_pings = new_pos % PING_NUM_MAX; | ||
91 | } | ||
92 | |||
93 | static uint64_t add_ping(PING *ping, IP_Port ipp, uint8_t *shared_encryption_key) // O(n) | ||
94 | { | ||
95 | size_t p; | ||
96 | |||
97 | remove_timeouts(ping); | ||
98 | |||
99 | /* Remove oldest ping if full buffer. */ | ||
100 | if (ping->num_pings == PING_NUM_MAX) { | ||
101 | ping->num_pings--; | ||
102 | ping->pos_pings = (ping->pos_pings + 1) % PING_NUM_MAX; | ||
103 | } | ||
104 | |||
105 | /* Insert new ping at end of list. */ | ||
106 | p = (ping->pos_pings + ping->num_pings) % PING_NUM_MAX; | ||
107 | |||
108 | ping->pings[p].ip_port = ipp; | ||
109 | ping->pings[p].timestamp = unix_time(); | ||
110 | ping->pings[p].id = random_64b(); | ||
111 | memcpy(ping->pings[p].shared_key, shared_encryption_key, crypto_box_BEFORENMBYTES); | ||
112 | |||
113 | ping->num_pings++; | ||
114 | return ping->pings[p].id; | ||
115 | } | ||
116 | |||
117 | /* checks if ip/port or ping_id are already in the list to ping | ||
118 | * if both are set, both must match, otherwise the set must match | ||
119 | * | ||
120 | * returns 0 if neither is set or no match was found | ||
121 | * returns the (index + 1) of the match if one was found | ||
122 | */ | ||
123 | static int is_pinging(PING *ping, IP_Port ipp, uint64_t ping_id) | ||
124 | { | ||
125 | // O(n) TODO: Replace this with something else. | ||
126 | |||
127 | /* at least one MUST be set */ | ||
128 | uint8_t ip_valid = ip_isset(&ipp.ip); | ||
129 | |||
130 | if (!ip_valid && !ping_id) | ||
131 | return 0; | ||
132 | |||
133 | size_t i; | ||
134 | |||
135 | remove_timeouts(ping); | ||
136 | |||
137 | for (i = 0; i < ping->num_pings; i++) { | ||
138 | size_t id = (ping->pos_pings + i) % PING_NUM_MAX; | ||
139 | |||
140 | if (!ping_id || (ping->pings[id].id == ping_id)) | ||
141 | if (!ip_valid || ipport_equal(&ping->pings[id].ip_port, &ipp)) | ||
142 | return id + 1; | ||
143 | } | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | 56 | ||
148 | #define DHT_PING_SIZE (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(uint64_t) + crypto_box_MACBYTES) | 57 | #define DHT_PING_SIZE (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(uint64_t) + crypto_box_MACBYTES) |
58 | #define PING_DATA_SIZE (CLIENT_ID_SIZE + sizeof(IP_Port)) | ||
149 | 59 | ||
150 | int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id) | 60 | int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id) |
151 | { | 61 | { |
@@ -153,7 +63,7 @@ int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id) | |||
153 | int rc; | 63 | int rc; |
154 | uint64_t ping_id; | 64 | uint64_t ping_id; |
155 | 65 | ||
156 | if (is_pinging(ping, ipp, 0) || id_equal(client_id, ping->dht->self_public_key)) | 66 | if (id_equal(client_id, ping->dht->self_public_key)) |
157 | return 1; | 67 | return 1; |
158 | 68 | ||
159 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; | 69 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; |
@@ -161,7 +71,13 @@ int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id) | |||
161 | // generate key to encrypt ping_id with recipient privkey | 71 | // generate key to encrypt ping_id with recipient privkey |
162 | DHT_get_shared_key_sent(ping->dht, shared_key, client_id); | 72 | DHT_get_shared_key_sent(ping->dht, shared_key, client_id); |
163 | // Generate random ping_id. | 73 | // Generate random ping_id. |
164 | ping_id = add_ping(ping, ipp, shared_key); | 74 | uint8_t data[PING_DATA_SIZE]; |
75 | id_copy(data, client_id); | ||
76 | memcpy(data + CLIENT_ID_SIZE, &ipp, sizeof(IP_Port)); | ||
77 | ping_id = ping_array_add(&ping->ping_array, data, sizeof(data)); | ||
78 | |||
79 | if (ping_id == 0) | ||
80 | return 1; | ||
165 | 81 | ||
166 | pk[0] = NET_PACKET_PING_REQUEST; | 82 | pk[0] = NET_PACKET_PING_REQUEST; |
167 | id_copy(pk + 1, ping->dht->self_public_key); // Our pubkey | 83 | id_copy(pk + 1, ping->dht->self_public_key); // Our pubkey |
@@ -252,14 +168,13 @@ static int handle_ping_response(void *_dht, IP_Port source, uint8_t *packet, uin | |||
252 | if (id_equal(packet + 1, ping->dht->self_public_key)) | 168 | if (id_equal(packet + 1, ping->dht->self_public_key)) |
253 | return 1; | 169 | return 1; |
254 | 170 | ||
255 | int ping_index = is_pinging(ping, source, 0); | 171 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; |
256 | 172 | ||
257 | if (!ping_index) | 173 | // generate key to encrypt ping_id with recipient privkey |
258 | return 1; | 174 | DHT_get_shared_key_sent(ping->dht, shared_key, packet + 1); |
259 | 175 | ||
260 | --ping_index; | ||
261 | // Decrypt ping_id | 176 | // Decrypt ping_id |
262 | rc = decrypt_data_symmetric(ping->pings[ping_index].shared_key, | 177 | rc = decrypt_data_symmetric(shared_key, |
263 | packet + 1 + CLIENT_ID_SIZE, | 178 | packet + 1 + CLIENT_ID_SIZE, |
264 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, | 179 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, |
265 | sizeof(ping_id) + crypto_box_MACBYTES, | 180 | sizeof(ping_id) + crypto_box_MACBYTES, |
@@ -268,11 +183,21 @@ static int handle_ping_response(void *_dht, IP_Port source, uint8_t *packet, uin | |||
268 | if (rc != sizeof(ping_id)) | 183 | if (rc != sizeof(ping_id)) |
269 | return 1; | 184 | return 1; |
270 | 185 | ||
271 | if (ping->pings[ping_index].id != ping_id) | 186 | uint8_t data[PING_DATA_SIZE]; |
187 | |||
188 | if (ping_array_check(data, sizeof(data), &ping->ping_array, ping_id) != sizeof(data)) | ||
272 | return 1; | 189 | return 1; |
273 | 190 | ||
274 | addto_lists(dht, source, packet + 1); | 191 | if (!id_equal(packet + 1, data)) |
192 | return 1; | ||
193 | |||
194 | IP_Port ipp; | ||
195 | memcpy(&ipp, data + CLIENT_ID_SIZE, sizeof(IP_Port)); | ||
275 | 196 | ||
197 | if (!ipport_equal(&ipp, &source)) | ||
198 | return 1; | ||
199 | |||
200 | addto_lists(dht, source, packet + 1); | ||
276 | return 0; | 201 | return 0; |
277 | } | 202 | } |
278 | 203 | ||
@@ -348,6 +273,11 @@ PING *new_ping(DHT *dht) | |||
348 | if (ping == NULL) | 273 | if (ping == NULL) |
349 | return NULL; | 274 | return NULL; |
350 | 275 | ||
276 | if (ping_array_init(&ping->ping_array, PING_NUM_MAX, PING_TIMEOUT) != 0) { | ||
277 | free(ping); | ||
278 | return NULL; | ||
279 | } | ||
280 | |||
351 | ping->dht = dht; | 281 | ping->dht = dht; |
352 | networking_registerhandler(ping->dht->net, NET_PACKET_PING_REQUEST, &handle_ping_request, dht); | 282 | networking_registerhandler(ping->dht->net, NET_PACKET_PING_REQUEST, &handle_ping_request, dht); |
353 | networking_registerhandler(ping->dht->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, dht); | 283 | networking_registerhandler(ping->dht->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, dht); |
@@ -359,6 +289,7 @@ void kill_ping(PING *ping) | |||
359 | { | 289 | { |
360 | networking_registerhandler(ping->dht->net, NET_PACKET_PING_REQUEST, NULL, NULL); | 290 | networking_registerhandler(ping->dht->net, NET_PACKET_PING_REQUEST, NULL, NULL); |
361 | networking_registerhandler(ping->dht->net, NET_PACKET_PING_RESPONSE, NULL, NULL); | 291 | networking_registerhandler(ping->dht->net, NET_PACKET_PING_RESPONSE, NULL, NULL); |
292 | ping_array_free_all(&ping->ping_array); | ||
362 | 293 | ||
363 | free(ping); | 294 | free(ping); |
364 | } | 295 | } |