diff options
Diffstat (limited to 'core/ping.c')
-rw-r--r-- | core/ping.c | 168 |
1 files changed, 119 insertions, 49 deletions
diff --git a/core/ping.c b/core/ping.c index 8a7d534f..37f1b7ae 100644 --- a/core/ping.c +++ b/core/ping.c | |||
@@ -8,6 +8,9 @@ | |||
8 | #include <stdbool.h> | 8 | #include <stdbool.h> |
9 | #include <stdint.h> | 9 | #include <stdint.h> |
10 | 10 | ||
11 | #include "DHT.h" | ||
12 | #include "net_crypto.h" | ||
13 | #include "packets.h" | ||
11 | #include "network.h" | 14 | #include "network.h" |
12 | #include "util.h" | 15 | #include "util.h" |
13 | 16 | ||
@@ -20,76 +23,143 @@ typedef struct { | |||
20 | uint64_t timestamp; | 23 | uint64_t timestamp; |
21 | } pinged_t; | 24 | } pinged_t; |
22 | 25 | ||
23 | static pinged_t pings[PING_NUM_MAX]; | 26 | static pinged_t pings[PING_NUM_MAX]; |
24 | static size_t num_pings; | 27 | static size_t num_pings; |
25 | static size_t pos_pings; | 28 | static size_t pos_pings; |
29 | static clientid_t* self_id = (clientid_t*) &self_public_key; | ||
26 | 30 | ||
31 | extern uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; // DHT.c | ||
27 | 32 | ||
28 | void init_ping() { | ||
29 | num_pings = 0; | ||
30 | pos_pings = 0; | ||
31 | } | ||
32 | 33 | ||
33 | static bool is_timeout(uint64_t time) { | 34 | void init_ping() |
34 | return (time + PING_TIMEOUT) < now(); | 35 | { |
36 | num_pings = 0; | ||
37 | pos_pings = 0; | ||
35 | } | 38 | } |
36 | 39 | ||
37 | static void remove_timeouts() { // O(n) | 40 | static bool is_timeout(uint64_t time) |
38 | size_t i, id; | 41 | { |
39 | size_t new_pos = pos_pings; | 42 | return (time + PING_TIMEOUT) < now(); |
40 | size_t new_num = num_pings; | 43 | } |
41 | |||
42 | // Loop through buffer, oldest first | ||
43 | for(i=0; i<num_pings; i++) { | ||
44 | id = (pos_pings + i) % PING_NUM_MAX; | ||
45 | 44 | ||
46 | if(is_timeout(pings[id].timestamp)) { | 45 | static void remove_timeouts() // O(n) |
47 | new_pos++; | 46 | { |
48 | new_num--; | 47 | size_t i, id; |
48 | size_t new_pos = pos_pings; | ||
49 | size_t new_num = num_pings; | ||
50 | |||
51 | // Loop through buffer, oldest first | ||
52 | for (i=0; i<num_pings; i++) { | ||
53 | id = (pos_pings + i) % PING_NUM_MAX; | ||
54 | |||
55 | if(is_timeout(pings[id].timestamp)) { | ||
56 | new_pos++; | ||
57 | new_num--; | ||
58 | } | ||
59 | // Break here because list is sorted. | ||
60 | else { | ||
61 | break; | ||
62 | } | ||
49 | } | 63 | } |
50 | // Break here because list is sorted. | ||
51 | else | ||
52 | break; | ||
53 | } | ||
54 | 64 | ||
55 | num_pings = new_num; | 65 | num_pings = new_num; |
56 | pos_pings = new_pos % PING_NUM_MAX; | 66 | pos_pings = new_pos % PING_NUM_MAX; |
57 | } | 67 | } |
58 | 68 | ||
59 | uint64_t add_ping(IP_Port ipp) { // O(n) | 69 | uint64_t add_ping(IP_Port ipp) // O(n) |
60 | size_t p; | 70 | { |
61 | 71 | size_t p; | |
62 | remove_timeouts(); | ||
63 | 72 | ||
64 | // Remove oldest ping if full buffer | 73 | remove_timeouts(); |
65 | if(num_pings == PING_NUM_MAX) { | ||
66 | num_pings--; | ||
67 | pos_pings = (pos_pings + 1) % PING_NUM_MAX; | ||
68 | } | ||
69 | 74 | ||
70 | // Insert new ping at end of list | 75 | // Remove oldest ping if full buffer |
71 | p = (pos_pings + num_pings) % PING_NUM_MAX; | 76 | if (num_pings == PING_NUM_MAX) { |
77 | num_pings--; | ||
78 | pos_pings = (pos_pings + 1) % PING_NUM_MAX; | ||
79 | } | ||
80 | |||
81 | // Insert new ping at end of list | ||
82 | p = (pos_pings + num_pings) % PING_NUM_MAX; | ||
72 | 83 | ||
73 | pings[p].ipp = ipp; | 84 | pings[p].ipp = ipp; |
74 | pings[p].timestamp = now(); | 85 | pings[p].timestamp = now(); |
75 | pings[p].id = random_64b(); | 86 | pings[p].id = random_64b(); |
76 | 87 | ||
77 | num_pings++; | 88 | num_pings++; |
78 | return pings[p].id; | 89 | return pings[p].id; |
79 | } | 90 | } |
80 | 91 | ||
81 | bool is_pinging(IP_Port ipp, uint64_t ping_id) { // O(n) | 92 | bool is_pinging(IP_Port ipp, uint64_t ping_id) // O(n) |
82 | size_t i, id; | 93 | { |
94 | size_t i, id; | ||
95 | |||
96 | if (ipp.ip.i == 0 && ping_id == 0) | ||
97 | return false; | ||
83 | 98 | ||
84 | remove_timeouts(); | 99 | remove_timeouts(); |
85 | 100 | ||
86 | for(i=0; i<num_pings; i++) { | 101 | for (i=0; i<num_pings; i++) { |
87 | id = (pos_pings + i) % PING_NUM_MAX; | 102 | id = (pos_pings + i) % PING_NUM_MAX; |
88 | 103 | ||
89 | if(ipp_eq(pings[id].ipp, ipp) && pings[id].id == ping_id) { | 104 | // ping_id = 0 means match any id |
90 | return true; | 105 | if(ipp_eq(pings[id].ipp, ipp) && (ping_id == 0 || pings[id].id == ping_id)) { |
106 | return true; | ||
107 | } | ||
91 | } | 108 | } |
92 | } | ||
93 | 109 | ||
94 | return false; | 110 | return false; |
111 | } | ||
112 | |||
113 | int send_ping_request(IP_Port ipp, clientid_t* client_id) | ||
114 | { | ||
115 | pingreq_t pk; | ||
116 | int rc; | ||
117 | uint64_t ping_id; | ||
118 | |||
119 | if (is_pinging(ipp, 0) || id_eq(client_id, self_id)) | ||
120 | return 1; | ||
121 | |||
122 | // Generate random ping_id | ||
123 | ping_id = add_ping(ipp); | ||
124 | |||
125 | pk.magic = PACKET_PING_REQ; | ||
126 | id_cpy(&pk.client_id, self_id); // Our pubkey | ||
127 | random_nonce((uint8_t*) &pk.nonce); // Generate random nonce | ||
128 | |||
129 | // Encrypt ping_id using recipient privkey | ||
130 | rc = encrypt_data((uint8_t*) client_id, | ||
131 | self_secret_key, | ||
132 | (uint8_t*) &pk.nonce, | ||
133 | (uint8_t*) &ping_id, sizeof(ping_id), | ||
134 | (uint8_t*) &pk.ping_id); | ||
135 | |||
136 | if (rc != sizeof(ping_id) + ENCRYPTION_PADDING) | ||
137 | return 1; | ||
138 | |||
139 | return sendpacket(ipp, (uint8_t*) &pk, sizeof(pk)); | ||
140 | } | ||
141 | |||
142 | int send_ping_response(IP_Port ipp, clientid_t* client_id, uint64_t ping_id) | ||
143 | { | ||
144 | pingres_t pk; | ||
145 | int rc; | ||
146 | |||
147 | if (id_eq(client_id, self_id)) | ||
148 | return 1; | ||
149 | |||
150 | pk.magic = PACKET_PING_RES; | ||
151 | id_cpy(&pk.client_id, self_id); // Our pubkey | ||
152 | random_nonce((uint8_t*) &pk.nonce); // Generate random nonce | ||
153 | |||
154 | // Encrypt ping_id using recipient privkey | ||
155 | rc = encrypt_data((uint8_t*) client_id, | ||
156 | self_secret_key, | ||
157 | (uint8_t*) &pk.nonce, | ||
158 | (uint8_t*) &ping_id, sizeof(ping_id), | ||
159 | (uint8_t*) &pk.ping_id); | ||
160 | |||
161 | if (rc != sizeof(ping_id) + ENCRYPTION_PADDING) | ||
162 | return 1; | ||
163 | |||
164 | return sendpacket(ipp, (uint8_t*) &pk, sizeof(pk)); | ||
95 | } | 165 | } |