ffi-tox 0.1.1 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (153) hide show
  1. checksums.yaml +4 -4
  2. data/ProjectTox-Core/AUTHORS +0 -0
  3. data/ProjectTox-Core/ChangeLog +0 -0
  4. data/ProjectTox-Core/INSTALL +370 -0
  5. data/ProjectTox-Core/INSTALL.md +455 -56
  6. data/ProjectTox-Core/Makefile.am +35 -0
  7. data/ProjectTox-Core/NEWS +0 -0
  8. data/ProjectTox-Core/README +43 -0
  9. data/ProjectTox-Core/README.md +34 -44
  10. data/ProjectTox-Core/auto_tests/Makefile.inc +110 -0
  11. data/ProjectTox-Core/auto_tests/TCP_test.c +519 -0
  12. data/ProjectTox-Core/auto_tests/assoc_test.c +160 -0
  13. data/ProjectTox-Core/auto_tests/crypto_test.c +302 -0
  14. data/ProjectTox-Core/auto_tests/dht_test.c +362 -0
  15. data/ProjectTox-Core/auto_tests/encryptsave_test.c +104 -0
  16. data/ProjectTox-Core/auto_tests/friends_test.c +238 -0
  17. data/ProjectTox-Core/auto_tests/helpers.h +15 -0
  18. data/ProjectTox-Core/auto_tests/messenger_test.c +365 -0
  19. data/ProjectTox-Core/auto_tests/network_test.c +171 -0
  20. data/ProjectTox-Core/auto_tests/onion_test.c +363 -0
  21. data/ProjectTox-Core/auto_tests/skeleton_test.c +49 -0
  22. data/ProjectTox-Core/auto_tests/tox_test.c +454 -0
  23. data/ProjectTox-Core/auto_tests/toxav_basic_test.c +597 -0
  24. data/ProjectTox-Core/auto_tests/toxav_many_test.c +402 -0
  25. data/ProjectTox-Core/autogen.sh +6 -0
  26. data/ProjectTox-Core/build/Makefile.am +14 -0
  27. data/ProjectTox-Core/configure.ac +694 -0
  28. data/ProjectTox-Core/dist-build/android-arm.sh +3 -0
  29. data/ProjectTox-Core/dist-build/android-armv7.sh +3 -0
  30. data/ProjectTox-Core/dist-build/android-build.sh +59 -0
  31. data/ProjectTox-Core/dist-build/android-mips.sh +3 -0
  32. data/ProjectTox-Core/dist-build/android-x86.sh +3 -0
  33. data/ProjectTox-Core/docs/Group-Chats.md +71 -0
  34. data/ProjectTox-Core/docs/Hardening.txt +60 -0
  35. data/ProjectTox-Core/docs/Hardening_docs.txt +30 -0
  36. data/ProjectTox-Core/docs/Prevent_Tracking.txt +160 -0
  37. data/ProjectTox-Core/docs/TCP_Network.txt +154 -0
  38. data/ProjectTox-Core/docs/TODO +62 -0
  39. data/ProjectTox-Core/docs/Tox_middle_level_network_protocol.txt +120 -0
  40. data/ProjectTox-Core/docs/av_api.md +194 -0
  41. data/ProjectTox-Core/libtoxav.pc.in +11 -0
  42. data/ProjectTox-Core/libtoxcore.pc.in +11 -0
  43. data/ProjectTox-Core/m4/ax_have_epoll.m4 +104 -0
  44. data/ProjectTox-Core/m4/ax_pthread.m4 +317 -0
  45. data/ProjectTox-Core/m4/pkg.m4 +199 -0
  46. data/ProjectTox-Core/other/DHT_bootstrap.c +121 -58
  47. data/ProjectTox-Core/other/DHTnodes +3 -0
  48. data/ProjectTox-Core/other/Makefile.inc +20 -0
  49. data/ProjectTox-Core/other/bootstrap_node_packets.c +65 -0
  50. data/ProjectTox-Core/other/tox.png +0 -0
  51. data/ProjectTox-Core/testing/DHT_test.c +170 -98
  52. data/ProjectTox-Core/testing/Makefile.inc +112 -0
  53. data/ProjectTox-Core/testing/Messenger_test.c +133 -69
  54. data/ProjectTox-Core/testing/dns3_test.c +115 -0
  55. data/ProjectTox-Core/testing/misc_tools.c +59 -13
  56. data/ProjectTox-Core/testing/nTox.c +1127 -264
  57. data/ProjectTox-Core/testing/nTox.h +10 -19
  58. data/ProjectTox-Core/testing/tox_shell.c +159 -0
  59. data/ProjectTox-Core/testing/tox_sync.c +299 -0
  60. data/ProjectTox-Core/tools/README +11 -0
  61. data/ProjectTox-Core/tools/astylerc +11 -0
  62. data/ProjectTox-Core/tools/pre-commit +17 -0
  63. data/ProjectTox-Core/toxav/Makefile.inc +36 -0
  64. data/ProjectTox-Core/toxav/codec.c +357 -0
  65. data/ProjectTox-Core/toxav/codec.h +116 -0
  66. data/ProjectTox-Core/toxav/msi.c +1949 -0
  67. data/ProjectTox-Core/toxav/msi.h +267 -0
  68. data/ProjectTox-Core/toxav/rtp.c +600 -0
  69. data/ProjectTox-Core/toxav/rtp.h +196 -0
  70. data/ProjectTox-Core/toxav/toxav.c +1148 -0
  71. data/ProjectTox-Core/toxav/toxav.h +389 -0
  72. data/ProjectTox-Core/toxcore/DHT.c +2521 -0
  73. data/ProjectTox-Core/toxcore/DHT.h +412 -0
  74. data/ProjectTox-Core/toxcore/LAN_discovery.c +322 -0
  75. data/ProjectTox-Core/{core → toxcore}/LAN_discovery.h +17 -12
  76. data/ProjectTox-Core/toxcore/Makefile.inc +67 -0
  77. data/ProjectTox-Core/toxcore/Messenger.c +3006 -0
  78. data/ProjectTox-Core/toxcore/Messenger.h +818 -0
  79. data/ProjectTox-Core/toxcore/TCP_client.c +858 -0
  80. data/ProjectTox-Core/toxcore/TCP_client.h +156 -0
  81. data/ProjectTox-Core/toxcore/TCP_server.c +1332 -0
  82. data/ProjectTox-Core/toxcore/TCP_server.h +181 -0
  83. data/ProjectTox-Core/toxcore/assoc.c +1033 -0
  84. data/ProjectTox-Core/toxcore/assoc.h +104 -0
  85. data/ProjectTox-Core/toxcore/crypto_core.c +278 -0
  86. data/ProjectTox-Core/toxcore/crypto_core.h +151 -0
  87. data/ProjectTox-Core/toxcore/friend_requests.c +175 -0
  88. data/ProjectTox-Core/toxcore/friend_requests.h +83 -0
  89. data/ProjectTox-Core/toxcore/group_chats.c +837 -0
  90. data/ProjectTox-Core/toxcore/group_chats.h +199 -0
  91. data/ProjectTox-Core/toxcore/list.c +256 -0
  92. data/ProjectTox-Core/toxcore/list.h +85 -0
  93. data/ProjectTox-Core/toxcore/logger.c +153 -0
  94. data/ProjectTox-Core/toxcore/logger.h +84 -0
  95. data/ProjectTox-Core/toxcore/misc_tools.h +70 -0
  96. data/ProjectTox-Core/toxcore/net_crypto.c +2753 -0
  97. data/ProjectTox-Core/toxcore/net_crypto.h +410 -0
  98. data/ProjectTox-Core/toxcore/network.c +979 -0
  99. data/ProjectTox-Core/toxcore/network.h +367 -0
  100. data/ProjectTox-Core/toxcore/onion.c +540 -0
  101. data/ProjectTox-Core/toxcore/onion.h +150 -0
  102. data/ProjectTox-Core/toxcore/onion_announce.c +433 -0
  103. data/ProjectTox-Core/toxcore/onion_announce.h +139 -0
  104. data/ProjectTox-Core/toxcore/onion_client.c +1347 -0
  105. data/ProjectTox-Core/toxcore/onion_client.h +253 -0
  106. data/ProjectTox-Core/toxcore/ping.c +346 -0
  107. data/ProjectTox-Core/toxcore/ping.h +47 -0
  108. data/ProjectTox-Core/toxcore/ping_array.c +162 -0
  109. data/ProjectTox-Core/toxcore/ping_array.h +75 -0
  110. data/ProjectTox-Core/toxcore/tox.c +940 -0
  111. data/ProjectTox-Core/toxcore/tox.h +734 -0
  112. data/ProjectTox-Core/toxcore/util.c +193 -0
  113. data/ProjectTox-Core/toxcore/util.h +63 -0
  114. data/ProjectTox-Core/toxdns/Makefile.inc +29 -0
  115. data/ProjectTox-Core/toxdns/toxdns.c +238 -0
  116. data/ProjectTox-Core/toxdns/toxdns.h +88 -0
  117. data/ProjectTox-Core/toxencryptsave/Makefile.inc +45 -0
  118. data/ProjectTox-Core/toxencryptsave/toxencryptsave.c +179 -0
  119. data/ProjectTox-Core/toxencryptsave/toxencryptsave.h +74 -0
  120. data/interfaces/libtox.i +2 -6
  121. data/lib/ffi-tox/libtox.rb +406 -28
  122. metadata +124 -46
  123. data/ProjectTox-Core/CMakeLists.txt +0 -50
  124. data/ProjectTox-Core/cmake/FindLIBCONFIG.cmake +0 -15
  125. data/ProjectTox-Core/cmake/FindNaCl.cmake +0 -17
  126. data/ProjectTox-Core/cmake/FindSODIUM.cmake +0 -15
  127. data/ProjectTox-Core/core/CMakeLists.txt +0 -19
  128. data/ProjectTox-Core/core/DHT.c +0 -1104
  129. data/ProjectTox-Core/core/DHT.h +0 -111
  130. data/ProjectTox-Core/core/LAN_discovery.c +0 -79
  131. data/ProjectTox-Core/core/Lossless_UDP.c +0 -755
  132. data/ProjectTox-Core/core/Lossless_UDP.h +0 -106
  133. data/ProjectTox-Core/core/Messenger.c +0 -596
  134. data/ProjectTox-Core/core/Messenger.h +0 -165
  135. data/ProjectTox-Core/core/friend_requests.c +0 -131
  136. data/ProjectTox-Core/core/friend_requests.h +0 -51
  137. data/ProjectTox-Core/core/net_crypto.c +0 -575
  138. data/ProjectTox-Core/core/net_crypto.h +0 -134
  139. data/ProjectTox-Core/core/network.c +0 -205
  140. data/ProjectTox-Core/core/network.h +0 -134
  141. data/ProjectTox-Core/docs/commands.md +0 -25
  142. data/ProjectTox-Core/docs/start_guide.de.md +0 -40
  143. data/ProjectTox-Core/docs/start_guide.md +0 -38
  144. data/ProjectTox-Core/other/CMakeLists.txt +0 -9
  145. data/ProjectTox-Core/testing/CMakeLists.txt +0 -18
  146. data/ProjectTox-Core/testing/DHT_cryptosendfiletest.c +0 -228
  147. data/ProjectTox-Core/testing/DHT_sendfiletest.c +0 -176
  148. data/ProjectTox-Core/testing/Lossless_UDP_testclient.c +0 -214
  149. data/ProjectTox-Core/testing/Lossless_UDP_testserver.c +0 -201
  150. data/ProjectTox-Core/testing/misc_tools.h +0 -29
  151. data/ProjectTox-Core/testing/nTox_win32.c +0 -387
  152. data/ProjectTox-Core/testing/nTox_win32.h +0 -40
  153. data/ProjectTox-Core/testing/rect.py +0 -45
@@ -0,0 +1,139 @@
1
+ /*
2
+ * onion_announce.h -- Implementation of the announce part of docs/Prevent_Tracking.txt
3
+ *
4
+ * Copyright (C) 2013 Tox project All Rights Reserved.
5
+ *
6
+ * This file is part of Tox.
7
+ *
8
+ * Tox is free software: you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation, either version 3 of the License, or
11
+ * (at your option) any later version.
12
+ *
13
+ * Tox is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+
23
+ #ifndef ONION_ANNOUNCE_H
24
+ #define ONION_ANNOUNCE_H
25
+
26
+ #include "onion.h"
27
+
28
+ #define ONION_ANNOUNCE_MAX_ENTRIES 64
29
+ #define ONION_ANNOUNCE_TIMEOUT 300
30
+ #define ONION_PING_ID_SIZE crypto_hash_sha256_BYTES
31
+
32
+ #define ONION_ANNOUNCE_SENDBACK_DATA_LENGTH (sizeof(uint64_t))
33
+
34
+ #define ONION_ANNOUNCE_REQUEST_SIZE (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_MACBYTES)
35
+
36
+ #define ONION_ANNOUNCE_RESPONSE_MIN_SIZE (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES + 1 + ONION_PING_ID_SIZE + crypto_box_MACBYTES)
37
+ #define ONION_ANNOUNCE_RESPONSE_MAX_SIZE (ONION_ANNOUNCE_RESPONSE_MIN_SIZE + sizeof(Node_format)*MAX_SENT_NODES)
38
+
39
+ #define ONION_DATA_RESPONSE_MIN_SIZE (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES)
40
+
41
+ #if ONION_PING_ID_SIZE != crypto_box_PUBLICKEYBYTES
42
+ #error announce response packets assume that ONION_PING_ID_SIZE is equal to crypto_box_PUBLICKEYBYTES
43
+ #endif
44
+
45
+ #define ONION_DATA_REQUEST_MIN_SIZE (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES)
46
+ #define MAX_DATA_REQUEST_SIZE (ONION_MAX_DATA_SIZE - ONION_DATA_REQUEST_MIN_SIZE)
47
+
48
+ typedef struct {
49
+ uint8_t public_key[crypto_box_PUBLICKEYBYTES];
50
+ IP_Port ret_ip_port;
51
+ uint8_t ret[ONION_RETURN_3];
52
+ uint8_t data_public_key[crypto_box_PUBLICKEYBYTES];
53
+ uint64_t time;
54
+ } Onion_Announce_Entry;
55
+
56
+ typedef struct {
57
+ DHT *dht;
58
+ Networking_Core *net;
59
+ Onion_Announce_Entry entries[ONION_ANNOUNCE_MAX_ENTRIES];
60
+ /* This is crypto_box_KEYBYTES long just so we can use new_symmetric_key() to fill it */
61
+ uint8_t secret_bytes[crypto_box_KEYBYTES];
62
+
63
+ Shared_Keys shared_keys_recv;
64
+ } Onion_Announce;
65
+
66
+ /* Create an onion announce request packet in packet of max_packet_length (recommended size ONION_ANNOUNCE_REQUEST_SIZE).
67
+ *
68
+ * dest_client_id is the public key of the node the packet will be sent to.
69
+ * public_key and secret_key is the kepair which will be used to encrypt the request.
70
+ * ping_id is the ping id that will be sent in the request.
71
+ * client_id is the client id of the node we are searching for.
72
+ * data_public_key is the public key we want others to encrypt their data packets with.
73
+ * sendback_data is the data of ONION_ANNOUNCE_SENDBACK_DATA_LENGTH length that we expect to
74
+ * receive back in the response.
75
+ *
76
+ * return -1 on failure.
77
+ * return packet length on success.
78
+ */
79
+ int create_announce_request(uint8_t *packet, uint16_t max_packet_length, const uint8_t *dest_client_id,
80
+ const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *ping_id, const uint8_t *client_id,
81
+ const uint8_t *data_public_key, uint64_t sendback_data);
82
+
83
+ /* Create an onion data request packet in packet of max_packet_length (recommended size ONION_MAX_PACKET_SIZE).
84
+ *
85
+ * public_key is the real public key of the node which we want to send the data of length length to.
86
+ * encrypt_public_key is the public key used to encrypt the data packet.
87
+ *
88
+ * nonce is the nonce to encrypt this packet with
89
+ *
90
+ * return -1 on failure.
91
+ * return 0 on success.
92
+ */
93
+ int create_data_request(uint8_t *packet, uint16_t max_packet_length, const uint8_t *public_key,
94
+ const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length);
95
+
96
+ /* Create and send an onion announce request packet.
97
+ *
98
+ * path is the path the request will take before it is sent to dest.
99
+ *
100
+ * public_key and secret_key is the kepair which will be used to encrypt the request.
101
+ * ping_id is the ping id that will be sent in the request.
102
+ * client_id is the client id of the node we are searching for.
103
+ * data_public_key is the public key we want others to encrypt their data packets with.
104
+ * sendback_data is the data of ONION_ANNOUNCE_SENDBACK_DATA_LENGTH length that we expect to
105
+ * receive back in the response.
106
+ *
107
+ * return -1 on failure.
108
+ * return 0 on success.
109
+ */
110
+ int send_announce_request(Networking_Core *net, const Onion_Path *path, Node_format dest, const uint8_t *public_key,
111
+ const uint8_t *secret_key, const uint8_t *ping_id, const uint8_t *client_id, const uint8_t *data_public_key,
112
+ uint64_t sendback_data);
113
+
114
+ /* Create and send an onion data request packet.
115
+ *
116
+ * path is the path the request will take before it is sent to dest.
117
+ * (if dest knows the person with the public_key they should
118
+ * send the packet to that person in the form of a response)
119
+ *
120
+ * public_key is the real public key of the node which we want to send the data of length length to.
121
+ * encrypt_public_key is the public key used to encrypt the data packet.
122
+ *
123
+ * nonce is the nonce to encrypt this packet with
124
+ *
125
+ * The maximum length of data is MAX_DATA_REQUEST_SIZE.
126
+ *
127
+ * return -1 on failure.
128
+ * return 0 on success.
129
+ */
130
+ int send_data_request(Networking_Core *net, const Onion_Path *path, IP_Port dest, const uint8_t *public_key,
131
+ const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length);
132
+
133
+
134
+ Onion_Announce *new_onion_announce(DHT *dht);
135
+
136
+ void kill_onion_announce(Onion_Announce *onion_a);
137
+
138
+
139
+ #endif
@@ -0,0 +1,1347 @@
1
+ /*
2
+ * onion_client.c -- Implementation of the client part of docs/Prevent_Tracking.txt
3
+ * (The part that uses the onion stuff to connect to the friend)
4
+ *
5
+ * Copyright (C) 2013 Tox project All Rights Reserved.
6
+ *
7
+ * This file is part of Tox.
8
+ *
9
+ * Tox is free software: you can redistribute it and/or modify
10
+ * it under the terms of the GNU General Public License as published by
11
+ * the Free Software Foundation, either version 3 of the License, or
12
+ * (at your option) any later version.
13
+ *
14
+ * Tox is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ * GNU General Public License for more details.
18
+ *
19
+ * You should have received a copy of the GNU General Public License
20
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
21
+ *
22
+ */
23
+ #ifdef HAVE_CONFIG_H
24
+ #include "config.h"
25
+ #endif
26
+
27
+ #include "onion_client.h"
28
+ #include "util.h"
29
+ #include "LAN_discovery.h"
30
+
31
+ /* defines for the array size and
32
+ timeout for onion announce packets. */
33
+ #define ANNOUNCE_ARRAY_SIZE 256
34
+ #define ANNOUNCE_TIMEOUT 10
35
+
36
+ /* Add a node to the path_nodes array.
37
+ *
38
+ * return -1 on failure
39
+ * return 0 on success
40
+ */
41
+ int onion_add_path_node(Onion_Client *onion_c, IP_Port ip_port, const uint8_t *client_id)
42
+ {
43
+ if (ip_port.ip.family != AF_INET && ip_port.ip.family != AF_INET6)
44
+ return -1;
45
+
46
+ unsigned int i;
47
+
48
+ for (i = 0; i < MAX_PATH_NODES; ++i) {
49
+ if (memcmp(client_id, onion_c->path_nodes[i].client_id, crypto_box_PUBLICKEYBYTES) == 0)
50
+ return -1;
51
+ }
52
+
53
+ onion_c->path_nodes[onion_c->path_nodes_index % MAX_PATH_NODES].ip_port = ip_port;
54
+ memcpy(onion_c->path_nodes[onion_c->path_nodes_index % MAX_PATH_NODES].client_id, client_id, crypto_box_PUBLICKEYBYTES);
55
+
56
+ uint16_t last = onion_c->path_nodes_index;
57
+ ++onion_c->path_nodes_index;
58
+
59
+ if (onion_c->path_nodes_index < last)
60
+ onion_c->path_nodes_index = MAX_PATH_NODES + 1;
61
+
62
+ return 0;
63
+ }
64
+
65
+ /* Put up to max_num nodes in nodes.
66
+ *
67
+ * return the number of nodes.
68
+ */
69
+ uint16_t onion_backup_nodes(const Onion_Client *onion_c, Node_format *nodes, uint16_t max_num)
70
+ {
71
+ unsigned int i;
72
+
73
+ if (!max_num)
74
+ return 0;
75
+
76
+ unsigned int num_nodes = (onion_c->path_nodes_index < MAX_PATH_NODES) ? onion_c->path_nodes_index : MAX_PATH_NODES;
77
+
78
+ if (num_nodes == 0)
79
+ return 0;
80
+
81
+ if (num_nodes < max_num)
82
+ max_num = num_nodes;
83
+
84
+ for (i = 0; i < max_num; ++i) {
85
+ nodes[i] = onion_c->path_nodes[(onion_c->path_nodes_index - (1 + i)) % num_nodes];
86
+ }
87
+
88
+ return max_num;
89
+ }
90
+
91
+ /* Put up to max_num random nodes in nodes.
92
+ *
93
+ * return the number of nodes.
94
+ */
95
+ static uint16_t random_nodes_path_onion(const Onion_Client *onion_c, Node_format *nodes, uint16_t max_num)
96
+ {
97
+ unsigned int i;
98
+
99
+ if (!max_num)
100
+ return 0;
101
+
102
+ unsigned int num_nodes = (onion_c->path_nodes_index < MAX_PATH_NODES) ? onion_c->path_nodes_index : MAX_PATH_NODES;
103
+
104
+ //if (DHT_non_lan_connected(onion_c->dht)) {
105
+ if (DHT_isconnected(onion_c->dht)) {
106
+ if (num_nodes < 3)
107
+ return random_nodes_path(onion_c->dht, nodes, max_num);
108
+
109
+ for (i = 0; i < max_num; ++i) {
110
+ nodes[i] = onion_c->path_nodes[rand() % num_nodes];
111
+ }
112
+ } else {
113
+ if (num_nodes == 0)
114
+ return 0;
115
+
116
+ nodes[0].ip_port.ip.family = TCP_FAMILY;
117
+
118
+ for (i = 1; i < max_num; ++i) {
119
+ nodes[i] = onion_c->path_nodes[rand() % num_nodes];
120
+ }
121
+ }
122
+
123
+ return max_num;
124
+ }
125
+
126
+ /*
127
+ * return -1 if nodes are suitable for creating a new path.
128
+ * return path number of already existing similar path if one already exists.
129
+ */
130
+ static int is_path_used(const Onion_Client_Paths *onion_paths, const Node_format *nodes)
131
+ {
132
+ uint32_t i;
133
+
134
+ for (i = 0; i < NUMBER_ONION_PATHS; ++i) {
135
+ if (is_timeout(onion_paths->last_path_success[i], ONION_PATH_TIMEOUT)) {
136
+ continue;
137
+ }
138
+
139
+ if (is_timeout(onion_paths->path_creation_time[i], ONION_PATH_MAX_LIFETIME)) {
140
+ continue;
141
+ }
142
+
143
+ if (ipport_equal(&onion_paths->paths[i].ip_port1, &nodes[2].ip_port)) {
144
+ return i;
145
+ }
146
+ }
147
+
148
+ return -1;
149
+ }
150
+
151
+ /* Create a new path or use an old suitable one (if pathnum is valid)
152
+ * or a rondom one from onion_paths.
153
+ *
154
+ * return -1 on failure
155
+ * return 0 on success
156
+ *
157
+ * TODO: Make this function better, it currently probably is vulnerable to some attacks that
158
+ * could de anonimize us.
159
+ */
160
+ static int random_path(const Onion_Client *onion_c, Onion_Client_Paths *onion_paths, uint32_t pathnum, Onion_Path *path)
161
+ {
162
+ if (pathnum >= NUMBER_ONION_PATHS)
163
+ pathnum = rand() % NUMBER_ONION_PATHS;
164
+
165
+ if (is_timeout(onion_paths->last_path_success[pathnum], ONION_PATH_TIMEOUT)
166
+ || is_timeout(onion_paths->path_creation_time[pathnum], ONION_PATH_MAX_LIFETIME)) {
167
+ Node_format nodes[3];
168
+
169
+ if (random_nodes_path_onion(onion_c, nodes, 3) != 3)
170
+ return -1;
171
+
172
+ int n = is_path_used(onion_paths, nodes);
173
+
174
+ if (n == -1) {
175
+ if (create_onion_path(onion_c->dht, &onion_paths->paths[pathnum], nodes) == -1)
176
+ return -1;
177
+
178
+ onion_paths->last_path_success[pathnum] = unix_time() + ONION_PATH_FIRST_TIMEOUT - ONION_PATH_TIMEOUT;
179
+ onion_paths->path_creation_time[pathnum] = unix_time();
180
+ uint32_t path_num = rand();
181
+ path_num /= NUMBER_ONION_PATHS;
182
+ path_num *= NUMBER_ONION_PATHS;
183
+ path_num += pathnum;
184
+
185
+ onion_paths->paths[pathnum].path_num = path_num;
186
+ } else {
187
+ pathnum = n;
188
+ }
189
+ }
190
+
191
+ memcpy(path, &onion_paths->paths[pathnum], sizeof(Onion_Path));
192
+ return 0;
193
+ }
194
+
195
+ /* Set path timeouts, return the path number.
196
+ *
197
+ */
198
+ static uint32_t set_path_timeouts(Onion_Client *onion_c, uint32_t num, uint32_t path_num)
199
+ {
200
+ if (num > onion_c->num_friends)
201
+ return -1;
202
+
203
+ Onion_Client_Paths *onion_paths;
204
+
205
+ if (num == 0) {
206
+ onion_paths = &onion_c->onion_paths;
207
+ } else {
208
+ onion_paths = &onion_c->friends_list[num - 1].onion_paths;
209
+ }
210
+
211
+ if (onion_paths->paths[path_num % NUMBER_ONION_PATHS].path_num == path_num) {
212
+ onion_paths->last_path_success[path_num % NUMBER_ONION_PATHS] = unix_time();
213
+ return path_num % NUMBER_ONION_PATHS;
214
+ }
215
+
216
+ return ~0;
217
+ }
218
+
219
+ /* Function to send onion packet via TCP and UDP.
220
+ *
221
+ * return -1 on failure.
222
+ * return 0 on success.
223
+ */
224
+ static int send_onion_packet_tcp_udp(const Onion_Client *onion_c, const Onion_Path *path, IP_Port dest,
225
+ const uint8_t *data, uint32_t length)
226
+ {
227
+ if (path->ip_port1.ip.family == AF_INET || path->ip_port1.ip.family == AF_INET6) {
228
+ uint8_t packet[ONION_MAX_PACKET_SIZE];
229
+ int len = create_onion_packet(packet, sizeof(packet), path, dest, data, length);
230
+
231
+ if (len == -1)
232
+ return -1;
233
+
234
+ if (sendpacket(onion_c->net, path->ip_port1, packet, len) != len)
235
+ return -1;
236
+
237
+ return 0;
238
+ } else if (path->ip_port1.ip.family == TCP_FAMILY) {
239
+ uint8_t packet[ONION_MAX_PACKET_SIZE];
240
+ int len = create_onion_packet_tcp(packet, sizeof(packet), path, dest, data, length);
241
+
242
+ if (len == -1)
243
+ return -1;
244
+
245
+ return send_tcp_onion_request(onion_c->c, packet, len);
246
+ } else {
247
+ return -1;
248
+ }
249
+ }
250
+
251
+ /* Creates a sendback for use in an announce request.
252
+ *
253
+ * num is 0 if we used our secret public key for the announce
254
+ * num is 1 + friendnum if we use a temporary one.
255
+ *
256
+ * Public key is the key we will be sending it to.
257
+ * ip_port is the ip_port of the node we will be sending
258
+ * it to.
259
+ *
260
+ * sendback must be at least ONION_ANNOUNCE_SENDBACK_DATA_LENGTH big
261
+ *
262
+ * return -1 on failure
263
+ * return 0 on success
264
+ *
265
+ */
266
+ static int new_sendback(Onion_Client *onion_c, uint32_t num, const uint8_t *public_key, IP_Port ip_port,
267
+ uint32_t path_num, uint64_t *sendback)
268
+ {
269
+ uint8_t data[sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port) + sizeof(uint32_t)];
270
+ memcpy(data, &num, sizeof(uint32_t));
271
+ memcpy(data + sizeof(uint32_t), public_key, crypto_box_PUBLICKEYBYTES);
272
+ memcpy(data + sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES, &ip_port, sizeof(IP_Port));
273
+ memcpy(data + sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port), &path_num, sizeof(uint32_t));
274
+ *sendback = ping_array_add(&onion_c->announce_ping_array, data, sizeof(data));
275
+
276
+ if (*sendback == 0)
277
+ return -1;
278
+
279
+ return 0;
280
+ }
281
+
282
+ /* Checks if the sendback is valid and returns the public key contained in it in ret_pubkey and the
283
+ * ip contained in it in ret_ip_port
284
+ *
285
+ * sendback is the sendback ONION_ANNOUNCE_SENDBACK_DATA_LENGTH big
286
+ * ret_pubkey must be at least crypto_box_PUBLICKEYBYTES big
287
+ * ret_ip_port must be at least 1 big
288
+ *
289
+ * return ~0 on failure
290
+ * return num (see new_sendback(...)) on success
291
+ */
292
+ static uint32_t check_sendback(Onion_Client *onion_c, const uint8_t *sendback, uint8_t *ret_pubkey,
293
+ IP_Port *ret_ip_port, uint32_t *path_num)
294
+ {
295
+ uint64_t sback;
296
+ memcpy(&sback, sendback, sizeof(uint64_t));
297
+ uint8_t data[sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port) + sizeof(uint32_t)];
298
+
299
+ if (ping_array_check(data, sizeof(data), &onion_c->announce_ping_array, sback) != sizeof(data))
300
+ return ~0;
301
+
302
+ memcpy(ret_pubkey, data + sizeof(uint32_t), crypto_box_PUBLICKEYBYTES);
303
+ memcpy(ret_ip_port, data + sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES, sizeof(IP_Port));
304
+ memcpy(path_num, data + sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port), sizeof(uint32_t));
305
+
306
+ uint32_t num;
307
+ memcpy(&num, data, sizeof(uint32_t));
308
+ return num;
309
+ }
310
+
311
+ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_Port dest, const uint8_t *dest_pubkey,
312
+ const uint8_t *ping_id, uint32_t pathnum)
313
+ {
314
+ if (num > onion_c->num_friends)
315
+ return -1;
316
+
317
+ uint64_t sendback;
318
+ Onion_Path path;
319
+
320
+ if (num == 0) {
321
+ if (random_path(onion_c, &onion_c->onion_paths, pathnum, &path) == -1)
322
+ return -1;
323
+ } else {
324
+ if (random_path(onion_c, &onion_c->friends_list[num - 1].onion_paths, pathnum, &path) == -1)
325
+ return -1;
326
+ }
327
+
328
+ if (new_sendback(onion_c, num, dest_pubkey, dest, path.path_num, &sendback) == -1)
329
+ return -1;
330
+
331
+ uint8_t zero_ping_id[ONION_PING_ID_SIZE] = {0};
332
+
333
+ if (ping_id == NULL)
334
+ ping_id = zero_ping_id;
335
+
336
+ Node_format dest_node;
337
+ dest_node.ip_port = dest;
338
+ memcpy(dest_node.client_id, dest_pubkey, crypto_box_PUBLICKEYBYTES);
339
+ uint8_t request[ONION_ANNOUNCE_REQUEST_SIZE];
340
+ int len;
341
+
342
+ if (num == 0) {
343
+ len = create_announce_request(request, sizeof(request), dest_pubkey, onion_c->c->self_public_key,
344
+ onion_c->c->self_secret_key, ping_id, onion_c->c->self_public_key, onion_c->temp_public_key, sendback);
345
+
346
+ } else {
347
+ len = create_announce_request(request, sizeof(request), dest_pubkey, onion_c->friends_list[num - 1].temp_public_key,
348
+ onion_c->friends_list[num - 1].temp_secret_key, ping_id, onion_c->friends_list[num - 1].real_client_id, zero_ping_id,
349
+ sendback);
350
+ }
351
+
352
+ if (len == -1) {
353
+ return -1;
354
+ }
355
+
356
+ return send_onion_packet_tcp_udp(onion_c, &path, dest, request, len);
357
+ }
358
+
359
+ static uint8_t cmp_public_key[crypto_box_PUBLICKEYBYTES];
360
+ static int cmp_entry(const void *a, const void *b)
361
+ {
362
+ Onion_Node entry1, entry2;
363
+ memcpy(&entry1, a, sizeof(Onion_Node));
364
+ memcpy(&entry2, b, sizeof(Onion_Node));
365
+ int t1 = is_timeout(entry1.timestamp, ONION_NODE_TIMEOUT);
366
+ int t2 = is_timeout(entry2.timestamp, ONION_NODE_TIMEOUT);
367
+
368
+ if (t1 && t2)
369
+ return 0;
370
+
371
+ if (t1)
372
+ return -1;
373
+
374
+ if (t2)
375
+ return 1;
376
+
377
+ int close = id_closest(cmp_public_key, entry1.client_id, entry2.client_id);
378
+
379
+ if (close == 1)
380
+ return 1;
381
+
382
+ if (close == 2)
383
+ return -1;
384
+
385
+ return 0;
386
+ }
387
+
388
+ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, const uint8_t *public_key, IP_Port ip_port,
389
+ uint8_t is_stored, const uint8_t *pingid_or_key, uint32_t path_num)
390
+ {
391
+ if (num > onion_c->num_friends)
392
+ return -1;
393
+
394
+ Onion_Node *list_nodes = NULL;
395
+ uint8_t *reference_id = NULL;
396
+
397
+ if (num == 0) {
398
+ list_nodes = onion_c->clients_announce_list;
399
+ reference_id = onion_c->c->self_public_key;
400
+
401
+ if (is_stored == 1 && memcmp(pingid_or_key, onion_c->temp_public_key, crypto_box_PUBLICKEYBYTES) != 0) {
402
+ is_stored = 0;
403
+ }
404
+
405
+ } else {
406
+ if (is_stored >= 2)
407
+ return -1;
408
+
409
+ list_nodes = onion_c->friends_list[num - 1].clients_list;
410
+ reference_id = onion_c->friends_list[num - 1].real_client_id;
411
+ }
412
+
413
+ memcpy(cmp_public_key, reference_id, crypto_box_PUBLICKEYBYTES);
414
+ qsort(list_nodes, MAX_ONION_CLIENTS, sizeof(Onion_Node), cmp_entry);
415
+
416
+ int index = -1, stored = 0;
417
+ uint32_t i;
418
+
419
+ if (is_timeout(list_nodes[0].timestamp, ONION_NODE_TIMEOUT)
420
+ || id_closest(reference_id, list_nodes[0].client_id, public_key) == 2) {
421
+ index = 0;
422
+ }
423
+
424
+ for (i = 0; i < MAX_ONION_CLIENTS; ++i) {
425
+ if (memcmp(list_nodes[i].client_id, public_key, crypto_box_PUBLICKEYBYTES) == 0) {
426
+ index = i;
427
+ stored = 1;
428
+ break;
429
+ }
430
+ }
431
+
432
+ if (index == -1)
433
+ return 0;
434
+
435
+ memcpy(list_nodes[index].client_id, public_key, CLIENT_ID_SIZE);
436
+ list_nodes[index].ip_port = ip_port;
437
+
438
+ //TODO: remove this and find a better source of nodes to use for paths.
439
+ onion_add_path_node(onion_c, ip_port, public_key);
440
+
441
+ if (is_stored == 1) {
442
+ memcpy(list_nodes[index].data_public_key, pingid_or_key, crypto_box_PUBLICKEYBYTES);
443
+ } else {
444
+ memcpy(list_nodes[index].ping_id, pingid_or_key, ONION_PING_ID_SIZE);
445
+ }
446
+
447
+ list_nodes[index].is_stored = is_stored;
448
+ list_nodes[index].timestamp = unix_time();
449
+
450
+ if (!stored)
451
+ list_nodes[index].last_pinged = 0;
452
+
453
+ list_nodes[index].path_used = set_path_timeouts(onion_c, num, path_num);
454
+ return 0;
455
+ }
456
+
457
+ static int good_to_ping(Last_Pinged *last_pinged, uint8_t *last_pinged_index, const uint8_t *client_id)
458
+ {
459
+ uint32_t i;
460
+
461
+ for (i = 0; i < MAX_STORED_PINGED_NODES; ++i) {
462
+ if (!is_timeout(last_pinged[i].timestamp, MIN_NODE_PING_TIME))
463
+ if (memcmp(last_pinged[i].client_id, client_id, crypto_box_PUBLICKEYBYTES) == 0)
464
+ return 0;
465
+ }
466
+
467
+ memcpy(last_pinged[*last_pinged_index % MAX_STORED_PINGED_NODES].client_id, client_id, crypto_box_PUBLICKEYBYTES);
468
+ last_pinged[*last_pinged_index % MAX_STORED_PINGED_NODES].timestamp = unix_time();
469
+ ++*last_pinged_index;
470
+ return 1;
471
+ }
472
+
473
+ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, const Node_format *nodes, uint16_t num_nodes,
474
+ IP_Port source)
475
+ {
476
+ if (num > onion_c->num_friends)
477
+ return -1;
478
+
479
+ if (num_nodes == 0)
480
+ return 0;
481
+
482
+ Onion_Node *list_nodes = NULL;
483
+ uint8_t *reference_id = NULL;
484
+
485
+ Last_Pinged *last_pinged = NULL;
486
+ uint8_t *last_pinged_index = NULL;
487
+
488
+ if (num == 0) {
489
+ list_nodes = onion_c->clients_announce_list;
490
+ reference_id = onion_c->c->self_public_key;
491
+ last_pinged = onion_c->last_pinged;
492
+ last_pinged_index = &onion_c->last_pinged_index;
493
+ } else {
494
+ list_nodes = onion_c->friends_list[num - 1].clients_list;
495
+ reference_id = onion_c->friends_list[num - 1].real_client_id;
496
+ last_pinged = onion_c->friends_list[num - 1].last_pinged;
497
+ last_pinged_index = &onion_c->friends_list[num - 1].last_pinged_index;
498
+ }
499
+
500
+ uint32_t i, j;
501
+ int lan_ips_accepted = (LAN_ip(source.ip) == 0);
502
+
503
+ for (i = 0; i < num_nodes; ++i) {
504
+
505
+ if (!lan_ips_accepted)
506
+ if (LAN_ip(nodes[i].ip_port.ip) == 0)
507
+ continue;
508
+
509
+ if (is_timeout(list_nodes[0].timestamp, ONION_NODE_TIMEOUT)
510
+ || id_closest(reference_id, list_nodes[0].client_id, nodes[i].client_id) == 2) {
511
+ /* check if node is already in list. */
512
+ for (j = 0; j < MAX_ONION_CLIENTS; ++j) {
513
+ if (memcmp(list_nodes[j].client_id, nodes[i].client_id, crypto_box_PUBLICKEYBYTES) == 0) {
514
+ break;
515
+ }
516
+ }
517
+
518
+ if (j == MAX_ONION_CLIENTS && good_to_ping(last_pinged, last_pinged_index, nodes[i].client_id)) {
519
+ client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].client_id, NULL, ~0);
520
+ }
521
+ }
522
+ }
523
+
524
+ return 0;
525
+ }
526
+
527
+ static int handle_announce_response(void *object, IP_Port source, const uint8_t *packet, uint32_t length)
528
+ {
529
+ Onion_Client *onion_c = object;
530
+
531
+ if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE)
532
+ return 1;
533
+
534
+ uint16_t len_nodes = length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE;
535
+
536
+ uint8_t public_key[crypto_box_PUBLICKEYBYTES];
537
+ IP_Port ip_port;
538
+ uint32_t path_num;
539
+ uint32_t num = check_sendback(onion_c, packet + 1, public_key, &ip_port, &path_num);
540
+
541
+ if (num > onion_c->num_friends)
542
+ return 1;
543
+
544
+ uint8_t plain[1 + ONION_PING_ID_SIZE + len_nodes];
545
+ int len = -1;
546
+
547
+ if (num == 0) {
548
+ len = decrypt_data(public_key, onion_c->c->self_secret_key, packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH,
549
+ packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES,
550
+ length - (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES), plain);
551
+ } else {
552
+ if (onion_c->friends_list[num - 1].status == 0)
553
+ return 1;
554
+
555
+ len = decrypt_data(public_key, onion_c->friends_list[num - 1].temp_secret_key,
556
+ packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH,
557
+ packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES,
558
+ length - (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES), plain);
559
+ }
560
+
561
+ if ((uint32_t)len != sizeof(plain))
562
+ return 1;
563
+
564
+ if (client_add_to_list(onion_c, num, public_key, ip_port, plain[0], plain + 1, path_num) == -1)
565
+ return 1;
566
+
567
+ if (len_nodes != 0) {
568
+ Node_format nodes[MAX_SENT_NODES];
569
+ int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, 0, plain + 1 + ONION_PING_ID_SIZE, len_nodes, 0);
570
+
571
+ if (num_nodes <= 0)
572
+ return 1;
573
+
574
+ if (client_ping_nodes(onion_c, num, nodes, num_nodes, source) == -1)
575
+ return 1;
576
+ }
577
+
578
+ return 0;
579
+ }
580
+
581
+ #define DATA_IN_RESPONSE_MIN_SIZE ONION_DATA_IN_RESPONSE_MIN_SIZE
582
+
583
+ static int handle_data_response(void *object, IP_Port source, const uint8_t *packet, uint32_t length)
584
+ {
585
+ Onion_Client *onion_c = object;
586
+
587
+ if (length <= (ONION_DATA_RESPONSE_MIN_SIZE + DATA_IN_RESPONSE_MIN_SIZE))
588
+ return 1;
589
+
590
+ if (length > MAX_DATA_REQUEST_SIZE)
591
+ return 1;
592
+
593
+ uint8_t temp_plain[length - ONION_DATA_RESPONSE_MIN_SIZE];
594
+ int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion_c->temp_secret_key, packet + 1,
595
+ packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES,
596
+ length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES), temp_plain);
597
+
598
+ if ((uint32_t)len != sizeof(temp_plain))
599
+ return 1;
600
+
601
+ uint8_t plain[sizeof(temp_plain) - DATA_IN_RESPONSE_MIN_SIZE];
602
+ len = decrypt_data(temp_plain, onion_c->c->self_secret_key, packet + 1, temp_plain + crypto_box_PUBLICKEYBYTES,
603
+ sizeof(temp_plain) - crypto_box_PUBLICKEYBYTES, plain);
604
+
605
+ if ((uint32_t)len != sizeof(plain))
606
+ return 1;
607
+
608
+ if (!onion_c->Onion_Data_Handlers[plain[0]].function)
609
+ return 1;
610
+
611
+ return onion_c->Onion_Data_Handlers[plain[0]].function(onion_c->Onion_Data_Handlers[plain[0]].object, temp_plain, plain,
612
+ sizeof(plain));
613
+ }
614
+
615
+ #define FAKEID_DATA_ID 156
616
+ #define FAKEID_DATA_MIN_LENGTH (1 + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES)
617
+ #define FAKEID_DATA_MAX_LENGTH (FAKEID_DATA_MIN_LENGTH + sizeof(Node_format)*MAX_SENT_NODES)
618
+ static int handle_fakeid_announce(void *object, const uint8_t *source_pubkey, const uint8_t *data, uint32_t length)
619
+ {
620
+ Onion_Client *onion_c = object;
621
+
622
+ if (length < FAKEID_DATA_MIN_LENGTH)
623
+ return 1;
624
+
625
+ if (length > FAKEID_DATA_MAX_LENGTH)
626
+ return 1;
627
+
628
+ int friend_num = onion_friend_num(onion_c, source_pubkey);
629
+
630
+ if (friend_num == -1)
631
+ return 1;
632
+
633
+ uint64_t no_replay;
634
+ memcpy(&no_replay, data + 1, sizeof(uint64_t));
635
+ net_to_host((uint8_t *) &no_replay, sizeof(no_replay));
636
+
637
+ if (no_replay <= onion_c->friends_list[friend_num].last_noreplay)
638
+ return 1;
639
+
640
+ onion_c->friends_list[friend_num].last_noreplay = no_replay;
641
+ onion_set_friend_DHT_pubkey(onion_c, friend_num, data + 1 + sizeof(uint64_t), current_time_monotonic());
642
+ onion_c->friends_list[friend_num].last_seen = unix_time();
643
+
644
+ uint16_t len_nodes = length - FAKEID_DATA_MIN_LENGTH;
645
+
646
+ if (len_nodes != 0) {
647
+ Node_format nodes[MAX_SENT_NODES];
648
+ int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, 0, data + 1 + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES,
649
+ len_nodes, 1);
650
+
651
+ if (num_nodes <= 0)
652
+ return 1;
653
+
654
+ int i;
655
+
656
+ for (i = 0; i < num_nodes; ++i) {
657
+ uint8_t family = nodes[i].ip_port.ip.family;
658
+
659
+ if (family == AF_INET || family == AF_INET6) {
660
+ DHT_getnodes(onion_c->dht, &nodes[i].ip_port, nodes[i].client_id, onion_c->friends_list[friend_num].fake_client_id);
661
+ } else if (family == TCP_INET || family == TCP_INET6) {
662
+ if (onion_c->friends_list[friend_num].tcp_relay_node_callback) {
663
+ void *obj = onion_c->friends_list[friend_num].tcp_relay_node_callback_object;
664
+ uint32_t number = onion_c->friends_list[friend_num].tcp_relay_node_callback_number;
665
+ onion_c->friends_list[friend_num].tcp_relay_node_callback(obj, number, nodes[i].ip_port, nodes[i].client_id);
666
+ }
667
+ }
668
+ }
669
+ }
670
+
671
+ return 0;
672
+ }
673
+
674
+ static int handle_tcp_onion(void *object, const uint8_t *data, uint16_t length)
675
+ {
676
+ if (length == 0)
677
+ return 1;
678
+
679
+ IP_Port ip_port = {0};
680
+ ip_port.ip.family = TCP_FAMILY;
681
+
682
+ if (data[0] == NET_PACKET_ANNOUNCE_RESPONSE) {
683
+ return handle_announce_response(object, ip_port, data, length);
684
+ } else if (data[0] == NET_PACKET_ONION_DATA_RESPONSE) {
685
+ return handle_data_response(object, ip_port, data, length);
686
+ }
687
+
688
+ return 1;
689
+ }
690
+
691
+ /* Send data of length length to friendnum.
692
+ * This data will be received by the friend using the Onion_Data_Handlers callbacks.
693
+ *
694
+ * Even if this function succeeds, the friend might not receive any data.
695
+ *
696
+ * return the number of packets sent on success
697
+ * return -1 on failure.
698
+ */
699
+ int send_onion_data(const Onion_Client *onion_c, int friend_num, const uint8_t *data, uint32_t length)
700
+ {
701
+ if ((uint32_t)friend_num >= onion_c->num_friends)
702
+ return -1;
703
+
704
+ if (length + DATA_IN_RESPONSE_MIN_SIZE > MAX_DATA_REQUEST_SIZE)
705
+ return -1;
706
+
707
+ if (length == 0)
708
+ return -1;
709
+
710
+ uint8_t nonce[crypto_box_NONCEBYTES];
711
+ random_nonce(nonce);
712
+
713
+ uint8_t packet[DATA_IN_RESPONSE_MIN_SIZE + length];
714
+ memcpy(packet, onion_c->c->self_public_key, crypto_box_PUBLICKEYBYTES);
715
+ int len = encrypt_data(onion_c->friends_list[friend_num].real_client_id, onion_c->c->self_secret_key, nonce, data,
716
+ length, packet + crypto_box_PUBLICKEYBYTES);
717
+
718
+ if ((uint32_t)len + crypto_box_PUBLICKEYBYTES != sizeof(packet))
719
+ return -1;
720
+
721
+ uint32_t i, good_nodes[MAX_ONION_CLIENTS], num_good = 0, num_nodes = 0;
722
+ Onion_Path path[MAX_ONION_CLIENTS];
723
+ Onion_Node *list_nodes = onion_c->friends_list[friend_num].clients_list;
724
+
725
+ for (i = 0; i < MAX_ONION_CLIENTS; ++i) {
726
+ if (is_timeout(list_nodes[i].timestamp, ONION_NODE_TIMEOUT))
727
+ continue;
728
+
729
+ ++num_nodes;
730
+
731
+ if (list_nodes[i].is_stored) {
732
+ if (random_path(onion_c, &onion_c->friends_list[friend_num].onion_paths, ~0, &path[num_good]) == -1)
733
+ continue;
734
+
735
+ good_nodes[num_good] = i;
736
+ ++num_good;
737
+ }
738
+ }
739
+
740
+ if (num_good < (num_nodes / 4) + 1)
741
+ return -1;
742
+
743
+ uint32_t good = 0;
744
+
745
+ for (i = 0; i < num_good; ++i) {
746
+ uint8_t o_packet[ONION_MAX_PACKET_SIZE];
747
+ len = create_data_request(o_packet, sizeof(o_packet), onion_c->friends_list[friend_num].real_client_id,
748
+ list_nodes[good_nodes[i]].data_public_key, nonce, packet, sizeof(packet));
749
+
750
+ if (len == -1)
751
+ continue;
752
+
753
+ if (send_onion_packet_tcp_udp(onion_c, &path[i], list_nodes[good_nodes[i]].ip_port, o_packet, len) == 0)
754
+ ++good;
755
+ }
756
+
757
+ return good;
758
+ }
759
+
760
+ /* Try to send the fakeid via the DHT instead of onion
761
+ *
762
+ * Even if this function succeeds, the friend might not receive any data.
763
+ *
764
+ * return the number of packets sent on success
765
+ * return -1 on failure.
766
+ */
767
+ static int send_dht_fakeid(const Onion_Client *onion_c, int friend_num, const uint8_t *data, uint32_t length)
768
+ {
769
+ if ((uint32_t)friend_num >= onion_c->num_friends)
770
+ return -1;
771
+
772
+ if (!onion_c->friends_list[friend_num].is_fake_clientid)
773
+ return -1;
774
+
775
+ uint8_t nonce[crypto_box_NONCEBYTES];
776
+ new_nonce(nonce);
777
+
778
+ uint8_t temp[DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES + length];
779
+ memcpy(temp, onion_c->c->self_public_key, crypto_box_PUBLICKEYBYTES);
780
+ memcpy(temp + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES);
781
+ int len = encrypt_data(onion_c->friends_list[friend_num].real_client_id, onion_c->c->self_secret_key, nonce, data,
782
+ length, temp + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES);
783
+
784
+ if ((uint32_t)len + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES != sizeof(temp))
785
+ return -1;
786
+
787
+ uint8_t packet[MAX_CRYPTO_REQUEST_SIZE];
788
+ len = create_request(onion_c->dht->self_public_key, onion_c->dht->self_secret_key, packet,
789
+ onion_c->friends_list[friend_num].fake_client_id, temp, sizeof(temp), FAKEID_DATA_ID);
790
+
791
+ if (len == -1)
792
+ return -1;
793
+
794
+ return route_tofriend(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id, packet, len);
795
+ }
796
+
797
+ static int handle_dht_fakeid(void *object, IP_Port source, const uint8_t *source_pubkey, const uint8_t *packet,
798
+ uint32_t length)
799
+ {
800
+ Onion_Client *onion_c = object;
801
+
802
+ if (length < FAKEID_DATA_MIN_LENGTH + DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES)
803
+ return 1;
804
+
805
+ if (length > FAKEID_DATA_MAX_LENGTH + DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES)
806
+ return 1;
807
+
808
+ uint8_t plain[FAKEID_DATA_MAX_LENGTH];
809
+ int len = decrypt_data(packet, onion_c->c->self_secret_key, packet + crypto_box_PUBLICKEYBYTES,
810
+ packet + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES,
811
+ length - (crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES), plain);
812
+
813
+ if ((uint32_t)len != length - (DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES))
814
+ return 1;
815
+
816
+ if (memcmp(source_pubkey, plain + 1 + sizeof(uint64_t), crypto_box_PUBLICKEYBYTES) != 0)
817
+ return 1;
818
+
819
+ return handle_fakeid_announce(onion_c, packet, plain, len);
820
+ }
821
+ /* Send the packets to tell our friends what our DHT public key is.
822
+ *
823
+ * if onion_dht_both is 0, use only the onion to send the packet.
824
+ * if it is 1, use only the dht.
825
+ * if it is something else, use both.
826
+ *
827
+ * return the number of packets sent on success
828
+ * return -1 on failure.
829
+ */
830
+ static int send_fakeid_announce(const Onion_Client *onion_c, uint16_t friend_num, uint8_t onion_dht_both)
831
+ {
832
+ if (friend_num >= onion_c->num_friends)
833
+ return -1;
834
+
835
+ uint8_t data[FAKEID_DATA_MAX_LENGTH];
836
+ data[0] = FAKEID_DATA_ID;
837
+ uint64_t no_replay = unix_time();
838
+ host_to_net((uint8_t *)&no_replay, sizeof(no_replay));
839
+ memcpy(data + 1, &no_replay, sizeof(no_replay));
840
+ memcpy(data + 1 + sizeof(uint64_t), onion_c->dht->self_public_key, crypto_box_PUBLICKEYBYTES);
841
+ Node_format nodes[MAX_SENT_NODES];
842
+ uint16_t num_relays = copy_connected_tcp_relays(onion_c->c, nodes, (MAX_SENT_NODES / 2));
843
+ uint16_t num_nodes = closelist_nodes(onion_c->dht, &nodes[num_relays], MAX_SENT_NODES - num_relays);
844
+ num_nodes += num_relays;
845
+ int nodes_len = 0;
846
+
847
+ if (num_nodes != 0) {
848
+ nodes_len = pack_nodes(data + FAKEID_DATA_MIN_LENGTH, FAKEID_DATA_MAX_LENGTH - FAKEID_DATA_MIN_LENGTH, nodes,
849
+ num_nodes);
850
+
851
+ if (nodes_len <= 0)
852
+ return -1;
853
+ }
854
+
855
+ int num1 = -1, num2 = -1;
856
+
857
+ if (onion_dht_both != 1)
858
+ num1 = send_onion_data(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + nodes_len);
859
+
860
+ if (onion_dht_both != 0)
861
+ num2 = send_dht_fakeid(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + nodes_len);
862
+
863
+ if (num1 == -1)
864
+ return num2;
865
+
866
+ if (num2 == -1)
867
+ return num1;
868
+
869
+ return num1 + num2;
870
+ }
871
+
872
+ /* Get the friend_num of a friend.
873
+ *
874
+ * return -1 on failure.
875
+ * return friend number on success.
876
+ */
877
+ int onion_friend_num(const Onion_Client *onion_c, const uint8_t *client_id)
878
+ {
879
+ uint32_t i;
880
+
881
+ for (i = 0; i < onion_c->num_friends; ++i) {
882
+ if (onion_c->friends_list[i].status == 0)
883
+ continue;
884
+
885
+ if (memcmp(client_id, onion_c->friends_list[i].real_client_id, crypto_box_PUBLICKEYBYTES) == 0)
886
+ return i;
887
+ }
888
+
889
+ return -1;
890
+ }
891
+
892
+ /* Set the size of the friend list to num.
893
+ *
894
+ * return -1 if realloc fails.
895
+ * return 0 if it succeeds.
896
+ */
897
+ static int realloc_onion_friends(Onion_Client *onion_c, uint32_t num)
898
+ {
899
+ if (num == 0) {
900
+ free(onion_c->friends_list);
901
+ onion_c->friends_list = NULL;
902
+ return 0;
903
+ }
904
+
905
+ Onion_Friend *newonion_friends = realloc(onion_c->friends_list, num * sizeof(Onion_Friend));
906
+
907
+ if (newonion_friends == NULL)
908
+ return -1;
909
+
910
+ onion_c->friends_list = newonion_friends;
911
+ return 0;
912
+ }
913
+
914
+ /* Add a friend who we want to connect to.
915
+ *
916
+ * return -1 on failure.
917
+ * return the friend number on success or if the friend was already added.
918
+ */
919
+ int onion_addfriend(Onion_Client *onion_c, const uint8_t *client_id)
920
+ {
921
+ int num = onion_friend_num(onion_c, client_id);
922
+
923
+ if (num != -1)
924
+ return num;
925
+
926
+ uint32_t i, index = ~0;
927
+
928
+ for (i = 0; i < onion_c->num_friends; ++i) {
929
+ if (onion_c->friends_list[i].status == 0) {
930
+ index = i;
931
+ break;
932
+ }
933
+ }
934
+
935
+ if (index == (uint32_t)~0) {
936
+ if (realloc_onion_friends(onion_c, onion_c->num_friends + 1) == -1)
937
+ return -1;
938
+
939
+ index = onion_c->num_friends;
940
+ memset(&(onion_c->friends_list[onion_c->num_friends]), 0, sizeof(Onion_Friend));
941
+ ++onion_c->num_friends;
942
+ }
943
+
944
+ onion_c->friends_list[index].status = 1;
945
+ memcpy(onion_c->friends_list[index].real_client_id, client_id, crypto_box_PUBLICKEYBYTES);
946
+ crypto_box_keypair(onion_c->friends_list[index].temp_public_key, onion_c->friends_list[index].temp_secret_key);
947
+ return index;
948
+ }
949
+
950
+ /* Delete a friend.
951
+ *
952
+ * return -1 on failure.
953
+ * return the deleted friend number on success.
954
+ */
955
+ int onion_delfriend(Onion_Client *onion_c, int friend_num)
956
+ {
957
+ if ((uint32_t)friend_num >= onion_c->num_friends)
958
+ return -1;
959
+
960
+ if (onion_c->friends_list[friend_num].is_fake_clientid)
961
+ DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id);
962
+
963
+ memset(&(onion_c->friends_list[friend_num]), 0, sizeof(Onion_Friend));
964
+ uint32_t i;
965
+
966
+ for (i = onion_c->num_friends; i != 0; --i) {
967
+ if (onion_c->friends_list[i - 1].status != 0)
968
+ break;
969
+ }
970
+
971
+ if (onion_c->num_friends != i) {
972
+ onion_c->num_friends = i;
973
+ realloc_onion_friends(onion_c, onion_c->num_friends);
974
+ }
975
+
976
+ return friend_num;
977
+ }
978
+
979
+ /* Set the function for this friend that will be callbacked with object and number
980
+ * when that friends gives us one of the TCP relays he is connected to.
981
+ *
982
+ * object and number will be passed as argument to this function.
983
+ *
984
+ * return -1 on failure.
985
+ * return 0 on success.
986
+ */
987
+ int recv_tcp_relay_handler(Onion_Client *onion_c, int friend_num, int (*tcp_relay_node_callback)(void *object,
988
+ uint32_t number, IP_Port ip_port, const uint8_t *public_key), void *object, uint32_t number)
989
+ {
990
+ if ((uint32_t)friend_num >= onion_c->num_friends)
991
+ return -1;
992
+
993
+ onion_c->friends_list[friend_num].tcp_relay_node_callback = tcp_relay_node_callback;
994
+ onion_c->friends_list[friend_num].tcp_relay_node_callback_object = object;
995
+ onion_c->friends_list[friend_num].tcp_relay_node_callback_number = number;
996
+ return 0;
997
+ }
998
+
999
+ /* Set a friends DHT public key.
1000
+ * timestamp is the time (current_time_monotonic()) at which the key was last confirmed belonging to
1001
+ * the other peer.
1002
+ *
1003
+ * return -1 on failure.
1004
+ * return 0 on success.
1005
+ */
1006
+ int onion_set_friend_DHT_pubkey(Onion_Client *onion_c, int friend_num, const uint8_t *dht_key, uint64_t timestamp)
1007
+ {
1008
+ if ((uint32_t)friend_num >= onion_c->num_friends)
1009
+ return -1;
1010
+
1011
+ if (onion_c->friends_list[friend_num].status == 0)
1012
+ return -1;
1013
+
1014
+ if (onion_c->friends_list[friend_num].fake_client_id_timestamp >= timestamp)
1015
+ return -1;
1016
+
1017
+ if (onion_c->friends_list[friend_num].is_fake_clientid) {
1018
+ if (memcmp(dht_key, onion_c->friends_list[friend_num].fake_client_id, crypto_box_PUBLICKEYBYTES) == 0) {
1019
+ return -1;
1020
+ }
1021
+
1022
+ DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id);
1023
+ }
1024
+
1025
+ if (DHT_addfriend(onion_c->dht, dht_key) == 1) {
1026
+ return -1;
1027
+ }
1028
+
1029
+ onion_c->friends_list[friend_num].last_seen = unix_time();
1030
+ onion_c->friends_list[friend_num].is_fake_clientid = 1;
1031
+ onion_c->friends_list[friend_num].fake_client_id_timestamp = timestamp;
1032
+ memcpy(onion_c->friends_list[friend_num].fake_client_id, dht_key, crypto_box_PUBLICKEYBYTES);
1033
+
1034
+ return 0;
1035
+ }
1036
+
1037
+ /* Copy friends DHT public key into dht_key.
1038
+ *
1039
+ * return 0 on failure (no key copied).
1040
+ * return timestamp on success (key copied).
1041
+ */
1042
+ uint64_t onion_getfriend_DHT_pubkey(const Onion_Client *onion_c, int friend_num, uint8_t *dht_key)
1043
+ {
1044
+ if ((uint32_t)friend_num >= onion_c->num_friends)
1045
+ return 0;
1046
+
1047
+ if (onion_c->friends_list[friend_num].status == 0)
1048
+ return 0;
1049
+
1050
+ if (!onion_c->friends_list[friend_num].is_fake_clientid)
1051
+ return 0;
1052
+
1053
+ memcpy(dht_key, onion_c->friends_list[friend_num].fake_client_id, crypto_box_PUBLICKEYBYTES);
1054
+ return onion_c->friends_list[friend_num].fake_client_id_timestamp;
1055
+ }
1056
+
1057
+ /* Get the ip of friend friendnum and put it in ip_port
1058
+ *
1059
+ * return -1, -- if client_id does NOT refer to a friend
1060
+ * return 0, -- if client_id refers to a friend and we failed to find the friend (yet)
1061
+ * return 1, ip if client_id refers to a friend and we found him
1062
+ *
1063
+ */
1064
+ int onion_getfriendip(const Onion_Client *onion_c, int friend_num, IP_Port *ip_port)
1065
+ {
1066
+ uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES];
1067
+
1068
+ if (onion_getfriend_DHT_pubkey(onion_c, friend_num, dht_public_key) == 0)
1069
+ return -1;
1070
+
1071
+ return DHT_getfriendip(onion_c->dht, dht_public_key, ip_port);
1072
+ }
1073
+
1074
+
1075
+ /* Set if friend is online or not.
1076
+ * NOTE: This function is there and should be used so that we don't send useless packets to the friend if he is online.
1077
+ *
1078
+ * is_online 1 means friend is online.
1079
+ * is_online 0 means friend is offline
1080
+ *
1081
+ * return -1 on failure.
1082
+ * return 0 on success.
1083
+ */
1084
+ int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_online)
1085
+ {
1086
+ if ((uint32_t)friend_num >= onion_c->num_friends)
1087
+ return -1;
1088
+
1089
+ if (is_online == 0 && onion_c->friends_list[friend_num].is_online == 1)
1090
+ onion_c->friends_list[friend_num].last_seen = unix_time();
1091
+
1092
+ onion_c->friends_list[friend_num].is_online = is_online;
1093
+
1094
+ /* This should prevent some clock related issues */
1095
+ if (!is_online)
1096
+ onion_c->friends_list[friend_num].last_noreplay = 0;
1097
+
1098
+ return 0;
1099
+ }
1100
+
1101
+ static void populate_path_nodes(Onion_Client *onion_c)
1102
+ {
1103
+ Node_format nodes_list[MAX_SENT_NODES];
1104
+ uint8_t client_id[crypto_box_PUBLICKEYBYTES];
1105
+ uint32_t random_num = rand();
1106
+ memcpy(client_id, &random_num, sizeof(random_num));
1107
+
1108
+ uint32_t num_nodes = get_close_nodes(onion_c->dht, client_id, nodes_list, (rand() % 2) ? AF_INET : AF_INET6, 1, 0);
1109
+ unsigned int i;
1110
+
1111
+ for (i = 0; i < num_nodes; ++i) {
1112
+ onion_add_path_node(onion_c, nodes_list[i].ip_port, nodes_list[i].client_id);
1113
+ }
1114
+ }
1115
+
1116
+ #define ANNOUNCE_FRIEND (ONION_NODE_PING_INTERVAL * 3)
1117
+ #define ANNOUNCE_FRIEND_BEGINNING 5
1118
+ #define FRIEND_ONION_NODE_TIMEOUT (ONION_NODE_TIMEOUT * 3)
1119
+
1120
+ #define RUN_COUNT_FRIEND_ANNOUNCE_BEGINNING 15
1121
+
1122
+ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
1123
+ {
1124
+ if (friendnum >= onion_c->num_friends)
1125
+ return;
1126
+
1127
+ if (onion_c->friends_list[friendnum].status == 0)
1128
+ return;
1129
+
1130
+ uint32_t interval = ANNOUNCE_FRIEND;
1131
+
1132
+ if (onion_c->friends_list[friendnum].run_count < RUN_COUNT_FRIEND_ANNOUNCE_BEGINNING)
1133
+ interval = ANNOUNCE_FRIEND_BEGINNING;
1134
+
1135
+ uint32_t i, count = 0;
1136
+ Onion_Node *list_nodes = onion_c->friends_list[friendnum].clients_list;
1137
+
1138
+ if (!onion_c->friends_list[friendnum].is_online) {
1139
+
1140
+ ++onion_c->friends_list[friendnum].run_count;
1141
+
1142
+ for (i = 0; i < MAX_ONION_CLIENTS; ++i) {
1143
+ if (is_timeout(list_nodes[i].timestamp, FRIEND_ONION_NODE_TIMEOUT))
1144
+ continue;
1145
+
1146
+ ++count;
1147
+
1148
+
1149
+ if (list_nodes[i].last_pinged == 0) {
1150
+ list_nodes[i].last_pinged = unix_time();
1151
+ continue;
1152
+ }
1153
+
1154
+ if (is_timeout(list_nodes[i].last_pinged, interval)) {
1155
+ if (client_send_announce_request(onion_c, friendnum + 1, list_nodes[i].ip_port, list_nodes[i].client_id, 0, ~0) == 0) {
1156
+ list_nodes[i].last_pinged = unix_time();
1157
+ }
1158
+ }
1159
+ }
1160
+
1161
+ if (count != MAX_ONION_CLIENTS) {
1162
+ unsigned int num_nodes = (onion_c->path_nodes_index < MAX_PATH_NODES) ? onion_c->path_nodes_index : MAX_PATH_NODES;
1163
+
1164
+ unsigned int n = num_nodes;
1165
+
1166
+ if (num_nodes > (MAX_ONION_CLIENTS / 2))
1167
+ n = (MAX_ONION_CLIENTS / 2);
1168
+
1169
+ if (num_nodes != 0) {
1170
+ unsigned int j;
1171
+
1172
+ for (j = 0; j < n; ++j) {
1173
+ unsigned int num = rand() % num_nodes;
1174
+ client_send_announce_request(onion_c, friendnum + 1, onion_c->path_nodes[num].ip_port,
1175
+ onion_c->path_nodes[num].client_id, 0, ~0);
1176
+ }
1177
+ }
1178
+ }
1179
+
1180
+ /* send packets to friend telling them our fake DHT id. */
1181
+ if (is_timeout(onion_c->friends_list[friendnum].last_fakeid_onion_sent, ONION_FAKEID_INTERVAL))
1182
+ if (send_fakeid_announce(onion_c, friendnum, 0) >= 1)
1183
+ onion_c->friends_list[friendnum].last_fakeid_onion_sent = unix_time();
1184
+
1185
+ if (is_timeout(onion_c->friends_list[friendnum].last_fakeid_dht_sent, DHT_FAKEID_INTERVAL))
1186
+ if (send_fakeid_announce(onion_c, friendnum, 1) >= 1)
1187
+ onion_c->friends_list[friendnum].last_fakeid_dht_sent = unix_time();
1188
+
1189
+ }
1190
+ }
1191
+
1192
+ /* Timeout before which a peer is considered dead and removed from the DHT search. */
1193
+ #define DEAD_ONION_TIMEOUT (10 * 60)
1194
+
1195
+ static void cleanup_friend(Onion_Client *onion_c, uint16_t friendnum)
1196
+ {
1197
+ if (friendnum >= onion_c->num_friends)
1198
+ return;
1199
+
1200
+ if (onion_c->friends_list[friendnum].status == 0)
1201
+ return;
1202
+
1203
+ if (onion_c->friends_list[friendnum].is_fake_clientid && !onion_c->friends_list[friendnum].is_online
1204
+ && is_timeout(onion_c->friends_list[friendnum].last_seen, DEAD_ONION_TIMEOUT)) {
1205
+ onion_c->friends_list[friendnum].is_fake_clientid = 0;
1206
+ DHT_delfriend(onion_c->dht, onion_c->friends_list[friendnum].fake_client_id);
1207
+ }
1208
+ }
1209
+
1210
+ /* Function to call when onion data packet with contents beginning with byte is received. */
1211
+ void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_handler_callback cb, void *object)
1212
+ {
1213
+ onion_c->Onion_Data_Handlers[byte].function = cb;
1214
+ onion_c->Onion_Data_Handlers[byte].object = object;
1215
+ }
1216
+
1217
+ #define ANNOUNCE_INTERVAL_NOT_ANNOUNCED 5
1218
+ #define ANNOUNCE_INTERVAL_ANNOUNCED ONION_NODE_PING_INTERVAL
1219
+
1220
+ static void do_announce(Onion_Client *onion_c)
1221
+ {
1222
+ uint32_t i, count = 0;
1223
+ Onion_Node *list_nodes = onion_c->clients_announce_list;
1224
+
1225
+ for (i = 0; i < MAX_ONION_CLIENTS; ++i) {
1226
+ if (is_timeout(list_nodes[i].timestamp, ONION_NODE_TIMEOUT))
1227
+ continue;
1228
+
1229
+ ++count;
1230
+
1231
+ /* Don't announce ourselves the first time this is run to new peers */
1232
+ if (list_nodes[i].last_pinged == 0) {
1233
+ list_nodes[i].last_pinged = 1;
1234
+ continue;
1235
+ }
1236
+
1237
+ uint32_t interval = ANNOUNCE_INTERVAL_NOT_ANNOUNCED;
1238
+
1239
+ if (list_nodes[i].is_stored) {
1240
+ interval = ANNOUNCE_INTERVAL_ANNOUNCED;
1241
+ }
1242
+
1243
+ if (is_timeout(list_nodes[i].last_pinged, interval)) {
1244
+ if (client_send_announce_request(onion_c, 0, list_nodes[i].ip_port, list_nodes[i].client_id,
1245
+ list_nodes[i].ping_id, list_nodes[i].path_used) == 0) {
1246
+ list_nodes[i].last_pinged = unix_time();
1247
+ }
1248
+ }
1249
+ }
1250
+
1251
+ if (count != MAX_ONION_CLIENTS) {
1252
+ if (count < (uint32_t)rand() % MAX_ONION_CLIENTS) {
1253
+
1254
+ unsigned int num_nodes = (onion_c->path_nodes_index < MAX_PATH_NODES) ? onion_c->path_nodes_index : MAX_PATH_NODES;
1255
+
1256
+ if (num_nodes != 0) {
1257
+ unsigned int num = rand() % num_nodes;
1258
+ client_send_announce_request(onion_c, 0, onion_c->path_nodes[num].ip_port, onion_c->path_nodes[num].client_id, 0, ~0);
1259
+ }
1260
+ }
1261
+ }
1262
+ }
1263
+
1264
+ #define NODE_POPULATE_TIMES 4
1265
+
1266
+ void do_onion_client(Onion_Client *onion_c)
1267
+ {
1268
+ uint32_t i;
1269
+
1270
+ if (onion_c->last_run == unix_time())
1271
+ return;
1272
+
1273
+ for (i = 0; i < NODE_POPULATE_TIMES; ++i)
1274
+ populate_path_nodes(onion_c);
1275
+
1276
+ do_announce(onion_c);
1277
+
1278
+ if (onion_isconnected(onion_c)) {
1279
+ for (i = 0; i < onion_c->num_friends; ++i) {
1280
+ do_friend(onion_c, i);
1281
+ cleanup_friend(onion_c, i);
1282
+ }
1283
+ }
1284
+
1285
+ onion_c->last_run = unix_time();
1286
+ }
1287
+
1288
+ Onion_Client *new_onion_client(Net_Crypto *c)
1289
+ {
1290
+ if (c == NULL)
1291
+ return NULL;
1292
+
1293
+ Onion_Client *onion_c = calloc(1, sizeof(Onion_Client));
1294
+
1295
+ if (onion_c == NULL)
1296
+ return NULL;
1297
+
1298
+ if (ping_array_init(&onion_c->announce_ping_array, ANNOUNCE_ARRAY_SIZE, ANNOUNCE_TIMEOUT) != 0) {
1299
+ free(onion_c);
1300
+ return NULL;
1301
+ }
1302
+
1303
+ onion_c->dht = c->dht;
1304
+ onion_c->net = c->dht->net;
1305
+ onion_c->c = c;
1306
+ new_symmetric_key(onion_c->secret_symmetric_key);
1307
+ crypto_box_keypair(onion_c->temp_public_key, onion_c->temp_secret_key);
1308
+ networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_announce_response, onion_c);
1309
+ networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_data_response, onion_c);
1310
+ oniondata_registerhandler(onion_c, FAKEID_DATA_ID, &handle_fakeid_announce, onion_c);
1311
+ cryptopacket_registerhandler(onion_c->dht, FAKEID_DATA_ID, &handle_dht_fakeid, onion_c);
1312
+ tcp_onion_response_handler(onion_c->c, &handle_tcp_onion, onion_c);
1313
+
1314
+ return onion_c;
1315
+ }
1316
+
1317
+ void kill_onion_client(Onion_Client *onion_c)
1318
+ {
1319
+ if (onion_c == NULL)
1320
+ return;
1321
+
1322
+ ping_array_free_all(&onion_c->announce_ping_array);
1323
+ realloc_onion_friends(onion_c, 0);
1324
+ networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, NULL, NULL);
1325
+ networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, NULL, NULL);
1326
+ oniondata_registerhandler(onion_c, FAKEID_DATA_ID, NULL, NULL);
1327
+ cryptopacket_registerhandler(onion_c->dht, FAKEID_DATA_ID, NULL, NULL);
1328
+ tcp_onion_response_handler(onion_c->c, NULL, NULL);
1329
+ memset(onion_c, 0, sizeof(Onion_Client));
1330
+ free(onion_c);
1331
+ }
1332
+
1333
+
1334
+ /* return 0 if we are not connected to the network.
1335
+ * return 1 if we are.
1336
+ */
1337
+ int onion_isconnected(const Onion_Client *onion_c)
1338
+ {
1339
+ unsigned int i;
1340
+
1341
+ for (i = 0; i < MAX_ONION_CLIENTS; ++i) {
1342
+ if (!is_timeout(onion_c->clients_announce_list[i].timestamp, ONION_NODE_TIMEOUT))
1343
+ return 1;
1344
+ }
1345
+
1346
+ return 0;
1347
+ }