summaryrefslogtreecommitdiff
path: root/core/ping.c
diff options
context:
space:
mode:
Diffstat (limited to 'core/ping.c')
-rw-r--r--core/ping.c168
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
23static pinged_t pings[PING_NUM_MAX]; 26static pinged_t pings[PING_NUM_MAX];
24static size_t num_pings; 27static size_t num_pings;
25static size_t pos_pings; 28static size_t pos_pings;
29static clientid_t* self_id = (clientid_t*) &self_public_key;
26 30
31extern uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; // DHT.c
27 32
28void init_ping() {
29 num_pings = 0;
30 pos_pings = 0;
31}
32 33
33static bool is_timeout(uint64_t time) { 34void init_ping()
34 return (time + PING_TIMEOUT) < now(); 35{
36 num_pings = 0;
37 pos_pings = 0;
35} 38}
36 39
37static void remove_timeouts() { // O(n) 40static 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)) { 45static 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
59uint64_t add_ping(IP_Port ipp) { // O(n) 69uint64_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
81bool is_pinging(IP_Port ipp, uint64_t ping_id) { // O(n) 92bool 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
113int 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
142int 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}