diff --git a/README.md b/README.md
index cbe53af5..ff3a6bba 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
With the rise of governmental monitoring programs, Tox, a FOSS initiative, aims to be an easy to use, all-in-one communication platform that ensures their users full privacy and secure message delivery.
-[**Website**](https://tox.im) **|** [**Wiki**](https://wiki.tox.im/) **|** [**Blog**](https://blog.libtoxcore.so/) **|** [**FAQ**](http://wiki.tox.im/FAQ) **|** [**Binaries**](https://wiki.tox.im/Binaries) **|** [**Clients**](https://wiki.tox.im/Client) **|** [**Compiling**](https://wiki.tox.im/Installing) **|** [**API**](https://libtoxcore.so/) **|** **IRC:** #tox@freenode
+[**Website**](https://tox.im) **|** [**Download**](https://wiki.tox.im/Binaries) **|** [**Wiki**](https://wiki.tox.im/) **|** [**Blog**](https://blog.libtoxcore.so/) **|** [**FAQ**](http://wiki.tox.im/FAQ) **|** [**Binaries**](https://wiki.tox.im/Binaries) **|** [**Clients**](https://wiki.tox.im/Client) **|** [**Compiling**](https://wiki.tox.im/Installing) **|** [**API**](https://libtoxcore.so/) **|** **IRC:** #tox@freenode
## The Complex Stuff:
@@ -33,7 +33,7 @@ The goal of this project is to create a configuration-free P2P Skype replacement
## Documentation:
-- [Installation](/INSTALL.md)
+- [Compiling](/INSTALL.md)
- [DHT Protocol](https://wiki.tox.im/index.php/DHT)
- [Lossless UDP Protocol](https://wiki.tox.im/index.php/Lossless_UDP)
- [Crypto](https://wiki.tox.im/index.php/Crypto)
diff --git a/other/fun/bootstrap_node_info.py b/other/fun/bootstrap_node_info.py
new file mode 100644
index 00000000..17349334
--- /dev/null
+++ b/other/fun/bootstrap_node_info.py
@@ -0,0 +1,98 @@
+#!/usr/bin/env python
+"""
+Copyright (c) 2014 by nurupo
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+"""
+
+from socket import *
+import sys
+
+if sys.version_info[0] == 2:
+ print("This script requires Python 3+ in order to run.")
+ sys.exit(1)
+
+def printHelp():
+ print("Usage: " + sys.argv[0] + " ")
+ print(" Example: " + sys.argv[0] + " ipv4 192.210.149.121 33445")
+ print(" Example: " + sys.argv[0] + " ipv4 23.226.230.47 33445")
+ print(" Example: " + sys.argv[0] + " ipv4 biribiri.org 33445")
+ print(" Example: " + sys.argv[0] + " ipv4 cerberus.zodiaclabs.org 33445")
+ print(" Example: " + sys.argv[0] + " ipv6 2604:180:1::3ded:b280 33445")
+ print("")
+ print("Return values:")
+ print(" 0 - received info reply from a node")
+ print(" 1 - incorrect command line arguments")
+ print(" 2 - didn't receive any reply from a node")
+ print(" 3 - received a malformed/unexpected reply")
+
+if len(sys.argv) != 4:
+ printHelp()
+ sys.exit(1)
+
+protocol = sys.argv[1]
+ip = sys.argv[2]
+port = int(sys.argv[3])
+
+INFO_PACKET_ID = b"\xF0" # https://github.com/irungentoo/toxcore/blob/4940c4c62b6014d1f0586aa6aca7bf6e4ecfcf29/toxcore/network.h#L128
+INFO_REQUEST_PACKET_LENGTH = 78 # https://github.com/irungentoo/toxcore/blob/881b2d900d1998981fb6b9938ec66012d049635f/other/bootstrap_node_packets.c#L28
+# first byte is INFO_REQUEST_ID, other bytes don't matter as long as reqest's length matches INFO_REQUEST_LENGTH
+INFO_REQUEST_PACKET = INFO_PACKET_ID + ( b"0" * (INFO_REQUEST_PACKET_LENGTH - len(INFO_PACKET_ID)) )
+
+PACKET_ID_LENGTH = len(INFO_PACKET_ID)
+VERSION_LENGTH = 4 # https://github.com/irungentoo/toxcore/blob/881b2d900d1998981fb6b9938ec66012d049635f/other/bootstrap_node_packets.c#L44
+MAX_MOTD_LENGTH = 256 # https://github.com/irungentoo/toxcore/blob/881b2d900d1998981fb6b9938ec66012d049635f/other/bootstrap_node_packets.c#L26
+
+MAX_INFO_RESPONSE_PACKET_LENGTH = PACKET_ID_LENGTH + VERSION_LENGTH + MAX_MOTD_LENGTH
+
+SOCK_TIMEOUT_SECONDS = 1.0
+
+sock = None
+
+if protocol == "ipv4":
+ sock = socket(AF_INET, SOCK_DGRAM)
+elif protocol == "ipv6":
+ sock = socket(AF_INET6, SOCK_DGRAM)
+else:
+ print("Invalid first argument")
+ printHelp()
+ sys.exit(1)
+
+sock.sendto(INFO_REQUEST_PACKET, (ip, port))
+
+sock.settimeout(SOCK_TIMEOUT_SECONDS)
+
+try:
+ data, addr = sock.recvfrom(MAX_INFO_RESPONSE_PACKET_LENGTH)
+except timeout:
+ print("The DHT bootstrap node didn't reply in " + str(SOCK_TIMEOUT_SECONDS) + " sec.")
+ print("The likely reason for that is that the DHT bootstrap node is either offline or has no info set.")
+ sys.exit(2)
+
+packetId = data[:PACKET_ID_LENGTH]
+if packetId != INFO_PACKET_ID:
+ print("Bad response, first byte should be", INFO_PACKET_ID, "but got", packetId, "(", data, ")")
+ print("Are you sure that you are pointing the script at a Tox DHT bootstrap node and that the script is up to date?")
+ sys.exit(3)
+
+version = int.from_bytes(data[PACKET_ID_LENGTH:PACKET_ID_LENGTH + VERSION_LENGTH], byteorder='big')
+motd = data[PACKET_ID_LENGTH + VERSION_LENGTH:].decode("utf-8")
+print("Version: " + str(version))
+print("MOTD: " + motd)
+sys.exit(0)
\ No newline at end of file
diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c
index 087188f7..82720ae8 100644
--- a/toxcore/TCP_client.c
+++ b/toxcore/TCP_client.c
@@ -197,6 +197,8 @@ void routing_status_handler(TCP_Client_Connection *con, int (*status_callback)(v
con->status_callback_object = object;
}
+static int send_ping_response(TCP_Client_Connection *con);
+
/* return 1 on success.
* return 0 if could not send packet.
* return -1 on failure.
@@ -209,6 +211,9 @@ int send_data(TCP_Client_Connection *con, uint8_t con_id, const uint8_t *data, u
if (con->connections[con_id].status != 2)
return -1;
+ if (send_ping_response(con) == 0)
+ return 0;
+
uint8_t packet[1 + length];
packet[0] = con_id + NUM_RESERVED_PORTS;
memcpy(packet + 1, data, length);
@@ -293,12 +298,21 @@ static int send_ping_request(TCP_Client_Connection *con, uint64_t ping_id)
* return 0 if could not send packet.
* return -1 on failure (connection must be killed).
*/
-static int send_ping_response(TCP_Client_Connection *con, uint64_t ping_id)
+static int send_ping_response(TCP_Client_Connection *con)
{
+ if (!con->ping_response_id)
+ return 1;
+
uint8_t packet[1 + sizeof(uint64_t)];
packet[0] = TCP_PACKET_PONG;
- memcpy(packet + 1, &ping_id, sizeof(uint64_t));
- return write_packet_TCP_secure_connection(con, packet, sizeof(packet));
+ memcpy(packet + 1, &con->ping_response_id, sizeof(uint64_t));
+ int ret;
+
+ if ((ret = write_packet_TCP_secure_connection(con, packet, sizeof(packet))) == 1) {
+ con->ping_response_id = 0;
+ }
+
+ return ret;
}
/* return 1 on success.
@@ -468,7 +482,8 @@ static int handle_TCP_packet(TCP_Client_Connection *conn, const uint8_t *data, u
uint64_t ping_id;
memcpy(&ping_id, data + 1, sizeof(uint64_t));
- send_ping_response(conn, ping_id);
+ conn->ping_response_id = ping_id;
+ send_ping_response(conn);
return 0;
}
@@ -523,6 +538,7 @@ static int handle_TCP_packet(TCP_Client_Connection *conn, const uint8_t *data, u
static int do_confirmed_TCP(TCP_Client_Connection *conn)
{
send_pending_data(conn);
+ send_ping_response(conn);
uint8_t packet[MAX_PACKET_SIZE];
int len;
diff --git a/toxcore/TCP_client.h b/toxcore/TCP_client.h
index 2622b4f7..e6d232ed 100644
--- a/toxcore/TCP_client.h
+++ b/toxcore/TCP_client.h
@@ -57,6 +57,7 @@ typedef struct {
uint64_t last_pinged;
uint64_t ping_id;
+ uint64_t ping_response_id;
void *net_crypto_pointer;
uint32_t net_crypto_location;
struct {