summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorplutooo <tfy12vbr@student.lu.se>2013-08-05 15:04:38 -0700
committerplutooo <tfy12vbr@student.lu.se>2013-08-06 09:21:39 -0700
commite71413d8f1fab4928be0e024821d58147f6f1b0e (patch)
treed00900d8cb8da93bd9e36b8f533faa65ba6d575d /core
parent071ac463082646189ade6e31bb3f6051516f81b2 (diff)
core: Move send ping packets functions to ping.c
Diffstat (limited to 'core')
-rw-r--r--core/DHT.c84
-rw-r--r--core/packets.h37
-rw-r--r--core/ping.c168
-rw-r--r--core/ping.h3
-rw-r--r--core/util.c38
-rw-r--r--core/util.h3
6 files changed, 197 insertions, 136 deletions
diff --git a/core/DHT.c b/core/DHT.c
index 01abfdd2..fa36d41f 100644
--- a/core/DHT.c
+++ b/core/DHT.c
@@ -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 */
478static 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 */
512static 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 */
541static int getnodes(IP_Port ip_port, uint8_t * public_key, uint8_t * client_id) 477static 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
8typedef struct {
9 uint8_t id[CLIENT_ID_SIZE];
10
11} __attribute__((packed)) clientid_t;
12
13typedef enum {
14 PACKET_PING_REQ = 0,
15 PACKET_PING_RES = 1
16
17} packetid_t;
18
19// Ping packet
20typedef 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
30typedef 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
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}
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 @@
10void init_ping(); 10void init_ping();
11uint64_t add_ping(IP_Port ipp); 11uint64_t add_ping(IP_Port ipp);
12bool is_pinging(IP_Port ipp, uint64_t ping_id); 12bool is_pinging(IP_Port ipp, uint64_t ping_id);
13 13int send_ping_request(IP_Port ipp, clientid_t* client_id);
14int 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
14uint64_t now() { 15uint64_t now()
15 return time(NULL); 16{
17 return time(NULL);
16} 18}
17 19
18uint64_t random_64b() { 20uint64_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
29bool ipp_eq(IP_Port a, IP_Port b) { 32bool 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
37bool id_eq(clientid_t* dest, clientid_t* src)
38{
39 return memcmp(dest, src, sizeof(clientid_t)) == 0;
40}
41
42void 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 @@
8uint64_t now(); 8uint64_t now();
9uint64_t random_64b(); 9uint64_t random_64b();
10bool ipp_eq(IP_Port a, IP_Port b); 10bool ipp_eq(IP_Port a, IP_Port b);
11bool id_eq(clientid_t* dest, clientid_t* src);
12void id_cpy(clientid_t* dest, clientid_t* src);
13