diff options
author | plutooo <tfy12vbr@student.lu.se> | 2013-08-05 15:04:38 -0700 |
---|---|---|
committer | plutooo <tfy12vbr@student.lu.se> | 2013-08-06 09:21:39 -0700 |
commit | e71413d8f1fab4928be0e024821d58147f6f1b0e (patch) | |
tree | d00900d8cb8da93bd9e36b8f533faa65ba6d575d | |
parent | 071ac463082646189ade6e31bb3f6051516f81b2 (diff) |
core: Move send ping packets functions to ping.c
-rw-r--r-- | core/DHT.c | 84 | ||||
-rw-r--r-- | core/packets.h | 37 | ||||
-rw-r--r-- | core/ping.c | 168 | ||||
-rw-r--r-- | core/ping.h | 3 | ||||
-rw-r--r-- | core/util.c | 38 | ||||
-rw-r--r-- | core/util.h | 3 |
6 files changed, 197 insertions, 136 deletions
@@ -24,6 +24,7 @@ | |||
24 | /*----------------------------------------------------------------------------------*/ | 24 | /*----------------------------------------------------------------------------------*/ |
25 | 25 | ||
26 | #include "DHT.h" | 26 | #include "DHT.h" |
27 | #include "packets.h" | ||
27 | #include "ping.h" | 28 | #include "ping.h" |
28 | 29 | ||
29 | /* maximum number of clients stored per friend. */ | 30 | /* maximum number of clients stored per friend. */ |
@@ -472,71 +473,6 @@ static uint64_t add_gettingnodes(IP_Port ip_port) | |||
472 | return 0; | 473 | return 0; |
473 | } | 474 | } |
474 | 475 | ||
475 | /* send a ping request, only works if none has been sent to that ip/port | ||
476 | * in the last 5 seconds. | ||
477 | */ | ||
478 | static int pingreq(IP_Port ip_port, uint8_t * public_key) | ||
479 | { | ||
480 | /* check if packet is gonna be sent to ourself */ | ||
481 | if(id_equal(public_key, self_public_key) || is_pinging(ip_port, 0)) | ||
482 | return 1; | ||
483 | |||
484 | uint64_t ping_id = add_ping(ip_port); | ||
485 | if(ping_id == 0) | ||
486 | return 1; | ||
487 | |||
488 | uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING]; | ||
489 | uint8_t encrypt[sizeof(ping_id) + ENCRYPTION_PADDING]; | ||
490 | uint8_t nonce[crypto_box_NONCEBYTES]; | ||
491 | random_nonce(nonce); | ||
492 | |||
493 | int len = encrypt_data( public_key, | ||
494 | self_secret_key, | ||
495 | nonce, | ||
496 | (uint8_t *)&ping_id, | ||
497 | sizeof(ping_id), | ||
498 | encrypt ); | ||
499 | |||
500 | if(len != sizeof(ping_id) + ENCRYPTION_PADDING) | ||
501 | return -1; | ||
502 | |||
503 | data[0] = 0; | ||
504 | memcpy(data + 1, self_public_key, CLIENT_ID_SIZE); | ||
505 | memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); | ||
506 | memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); | ||
507 | |||
508 | return sendpacket(ip_port, data, sizeof(data)); | ||
509 | } | ||
510 | |||
511 | /* send a ping response */ | ||
512 | static int pingres(IP_Port ip_port, uint8_t * public_key, uint64_t ping_id) | ||
513 | { | ||
514 | /* check if packet is gonna be sent to ourself */ | ||
515 | if(id_equal(public_key, self_public_key)) | ||
516 | return 1; | ||
517 | |||
518 | uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING]; | ||
519 | uint8_t encrypt[sizeof(ping_id) + ENCRYPTION_PADDING]; | ||
520 | uint8_t nonce[crypto_box_NONCEBYTES]; | ||
521 | random_nonce(nonce); | ||
522 | |||
523 | int len = encrypt_data( public_key, | ||
524 | self_secret_key, nonce, | ||
525 | (uint8_t *)&ping_id, | ||
526 | sizeof(ping_id), | ||
527 | encrypt ); | ||
528 | |||
529 | if(len != sizeof(ping_id) + ENCRYPTION_PADDING) | ||
530 | return -1; | ||
531 | |||
532 | data[0] = 1; | ||
533 | memcpy(data + 1, self_public_key, CLIENT_ID_SIZE); | ||
534 | memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); | ||
535 | memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); | ||
536 | |||
537 | return sendpacket(ip_port, data, sizeof(data)); | ||
538 | } | ||
539 | |||
540 | /* send a getnodes request */ | 476 | /* send a getnodes request */ |
541 | static int getnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id) | 477 | static int getnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id) |
542 | { | 478 | { |
@@ -641,8 +577,8 @@ static int handle_pingreq(uint8_t * packet, uint32_t length, IP_Port source) | |||
641 | if(len != sizeof(ping_id)) | 577 | if(len != sizeof(ping_id)) |
642 | return 1; | 578 | return 1; |
643 | 579 | ||
644 | pingres(source, packet + 1, ping_id); | 580 | send_ping_response(source, (clientid_t*) (packet + 1), ping_id); |
645 | pingreq(source, packet + 1); /* TODO: make this smarter? */ | 581 | send_ping_request(source, (clientid_t*) (packet + 1)); /* TODO: make this smarter? */ |
646 | 582 | ||
647 | return 0; | 583 | return 0; |
648 | } | 584 | } |
@@ -701,7 +637,7 @@ static int handle_getnodes(uint8_t * packet, uint32_t length, IP_Port source) | |||
701 | memcpy(&ping_id, plain, sizeof(ping_id)); | 637 | memcpy(&ping_id, plain, sizeof(ping_id)); |
702 | sendnodes(source, packet + 1, plain + sizeof(ping_id), ping_id); | 638 | sendnodes(source, packet + 1, plain + sizeof(ping_id), ping_id); |
703 | 639 | ||
704 | pingreq(source, packet + 1); /* TODO: make this smarter? */ | 640 | send_ping_request(source, (clientid_t*) (packet + 1)); /* TODO: make this smarter? */ |
705 | 641 | ||
706 | return 0; | 642 | return 0; |
707 | } | 643 | } |
@@ -741,7 +677,7 @@ static int handle_sendnodes(uint8_t * packet, uint32_t length, IP_Port source) | |||
741 | 677 | ||
742 | uint32_t i; | 678 | uint32_t i; |
743 | for(i = 0; i < num_nodes; ++i) { | 679 | for(i = 0; i < num_nodes; ++i) { |
744 | pingreq(nodes_list[i].ip_port, nodes_list[i].client_id); | 680 | send_ping_request(nodes_list[i].ip_port, (clientid_t*) &nodes_list[i].client_id); |
745 | returnedip_ports(nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1); | 681 | returnedip_ports(nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1); |
746 | } | 682 | } |
747 | 683 | ||
@@ -831,8 +767,8 @@ static void doDHTFriends(void) | |||
831 | /* if node is not dead. */ | 767 | /* if node is not dead. */ |
832 | if (!is_timeout(temp_time, friends_list[i].client_list[j].timestamp, Kill_NODE_TIMEOUT)) { | 768 | if (!is_timeout(temp_time, friends_list[i].client_list[j].timestamp, Kill_NODE_TIMEOUT)) { |
833 | if ((friends_list[i].client_list[j].last_pinged + PING_INTERVAL) <= temp_time) { | 769 | if ((friends_list[i].client_list[j].last_pinged + PING_INTERVAL) <= temp_time) { |
834 | pingreq( friends_list[i].client_list[j].ip_port, | 770 | send_ping_request( friends_list[i].client_list[j].ip_port, |
835 | friends_list[i].client_list[j].client_id ); | 771 | (clientid_t*) &friends_list[i].client_list[j].client_id ); |
836 | friends_list[i].client_list[j].last_pinged = temp_time; | 772 | friends_list[i].client_list[j].last_pinged = temp_time; |
837 | } | 773 | } |
838 | /* if node is good. */ | 774 | /* if node is good. */ |
@@ -869,8 +805,8 @@ static void doClose(void) | |||
869 | /* if node is not dead. */ | 805 | /* if node is not dead. */ |
870 | if (!is_timeout(temp_time, close_clientlist[i].timestamp, Kill_NODE_TIMEOUT)) { | 806 | if (!is_timeout(temp_time, close_clientlist[i].timestamp, Kill_NODE_TIMEOUT)) { |
871 | if ((close_clientlist[i].last_pinged + PING_INTERVAL) <= temp_time) { | 807 | if ((close_clientlist[i].last_pinged + PING_INTERVAL) <= temp_time) { |
872 | pingreq( close_clientlist[i].ip_port, | 808 | send_ping_request( close_clientlist[i].ip_port, |
873 | close_clientlist[i].client_id ); | 809 | (clientid_t*) &close_clientlist[i].client_id ); |
874 | close_clientlist[i].last_pinged = temp_time; | 810 | close_clientlist[i].last_pinged = temp_time; |
875 | } | 811 | } |
876 | /* if node is good. */ | 812 | /* if node is good. */ |
@@ -1151,7 +1087,7 @@ static void punch_holes(IP ip, uint16_t * port_list, uint16_t numports, uint16_t | |||
1151 | /*TODO: improve port guessing algorithm*/ | 1087 | /*TODO: improve port guessing algorithm*/ |
1152 | uint16_t port = port_list[(i/2) % numports] + (i/(2*numports))*((i % 2) ? -1 : 1); | 1088 | uint16_t port = port_list[(i/2) % numports] + (i/(2*numports))*((i % 2) ? -1 : 1); |
1153 | IP_Port pinging = {ip, htons(port)}; | 1089 | IP_Port pinging = {ip, htons(port)}; |
1154 | pingreq(pinging, friends_list[friend_num].client_id); | 1090 | send_ping_request(pinging, (clientid_t*) &friends_list[friend_num].client_id); |
1155 | } | 1091 | } |
1156 | friends_list[friend_num].punching_index = i; | 1092 | friends_list[friend_num].punching_index = i; |
1157 | } | 1093 | } |
diff --git a/core/packets.h b/core/packets.h new file mode 100644 index 00000000..222b1425 --- /dev/null +++ b/core/packets.h | |||
@@ -0,0 +1,37 @@ | |||
1 | /* | ||
2 | * packet.h -- Packet structure | ||
3 | * | ||
4 | * This file is donated to the Tox Project. | ||
5 | * Copyright 2013 plutooo | ||
6 | */ | ||
7 | |||
8 | typedef struct { | ||
9 | uint8_t id[CLIENT_ID_SIZE]; | ||
10 | |||
11 | } __attribute__((packed)) clientid_t; | ||
12 | |||
13 | typedef enum { | ||
14 | PACKET_PING_REQ = 0, | ||
15 | PACKET_PING_RES = 1 | ||
16 | |||
17 | } packetid_t; | ||
18 | |||
19 | // Ping packet | ||
20 | typedef struct { | ||
21 | uint8_t magic; | ||
22 | clientid_t client_id; | ||
23 | uint8_t nonce[crypto_box_NONCEBYTES]; | ||
24 | uint64_t ping_id; | ||
25 | uint8_t padding[ENCRYPTION_PADDING]; | ||
26 | |||
27 | } __attribute__((packed)) pingreq_t; | ||
28 | |||
29 | // Pong packet | ||
30 | typedef struct { | ||
31 | uint8_t magic; | ||
32 | clientid_t client_id; | ||
33 | uint8_t nonce[crypto_box_NONCEBYTES]; | ||
34 | uint64_t ping_id; | ||
35 | uint8_t padding[ENCRYPTION_PADDING]; | ||
36 | |||
37 | } __attribute__((packed)) pingres_t; | ||
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 | } |
diff --git a/core/ping.h b/core/ping.h index 1d23df97..f2770a00 100644 --- a/core/ping.h +++ b/core/ping.h | |||
@@ -10,4 +10,5 @@ | |||
10 | void init_ping(); | 10 | void init_ping(); |
11 | uint64_t add_ping(IP_Port ipp); | 11 | uint64_t add_ping(IP_Port ipp); |
12 | bool is_pinging(IP_Port ipp, uint64_t ping_id); | 12 | bool is_pinging(IP_Port ipp, uint64_t ping_id); |
13 | 13 | int send_ping_request(IP_Port ipp, clientid_t* client_id); | |
14 | int send_ping_response(IP_Port ipp, clientid_t* client_id, uint64_t ping_id); | ||
diff --git a/core/util.c b/core/util.c index 6b40dad7..d201bcb4 100644 --- a/core/util.c +++ b/core/util.c | |||
@@ -9,23 +9,37 @@ | |||
9 | #include <stdint.h> | 9 | #include <stdint.h> |
10 | #include <stdbool.h> | 10 | #include <stdbool.h> |
11 | 11 | ||
12 | #include "network.h" | 12 | #include "DHT.h" |
13 | #include "packets.h" | ||
13 | 14 | ||
14 | uint64_t now() { | 15 | uint64_t now() |
15 | return time(NULL); | 16 | { |
17 | return time(NULL); | ||
16 | } | 18 | } |
17 | 19 | ||
18 | uint64_t random_64b() { | 20 | uint64_t random_64b() |
19 | uint64_t r; | 21 | { |
22 | uint64_t r; | ||
20 | 23 | ||
21 | // This is probably not random enough? | 24 | // This is probably not random enough? |
22 | r = random_int(); | 25 | r = random_int(); |
23 | r <<= 32; | 26 | r <<= 32; |
24 | r |= random_int(); | 27 | r |= random_int(); |
25 | 28 | ||
26 | return r; | 29 | return r; |
27 | } | 30 | } |
28 | 31 | ||
29 | bool ipp_eq(IP_Port a, IP_Port b) { | 32 | bool ipp_eq(IP_Port a, IP_Port b) |
30 | return (a.ip.i == b.ip.i) && (a.port == b.port); | 33 | { |
34 | return (a.ip.i == b.ip.i) && (a.port == b.port); | ||
35 | } | ||
36 | |||
37 | bool id_eq(clientid_t* dest, clientid_t* src) | ||
38 | { | ||
39 | return memcmp(dest, src, sizeof(clientid_t)) == 0; | ||
40 | } | ||
41 | |||
42 | void id_cpy(clientid_t* dest, clientid_t* src) | ||
43 | { | ||
44 | memcpy(dest, src, sizeof(clientid_t)); | ||
31 | } | 45 | } |
diff --git a/core/util.h b/core/util.h index aab2ead9..a93be08a 100644 --- a/core/util.h +++ b/core/util.h | |||
@@ -8,3 +8,6 @@ | |||
8 | uint64_t now(); | 8 | uint64_t now(); |
9 | uint64_t random_64b(); | 9 | uint64_t random_64b(); |
10 | bool ipp_eq(IP_Port a, IP_Port b); | 10 | bool ipp_eq(IP_Port a, IP_Port b); |
11 | bool id_eq(clientid_t* dest, clientid_t* src); | ||
12 | void id_cpy(clientid_t* dest, clientid_t* src); | ||
13 | |||