summaryrefslogtreecommitdiff
path: root/toxcore
diff options
context:
space:
mode:
Diffstat (limited to 'toxcore')
-rw-r--r--toxcore/TCP_client.c101
-rw-r--r--toxcore/TCP_client.h6
-rw-r--r--toxcore/network.c35
-rw-r--r--toxcore/network.h20
-rw-r--r--toxcore/tox.c1
-rw-r--r--toxcore/tox.h1
6 files changed, 151 insertions, 13 deletions
diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c
index 23ab28c0..dfb4005c 100644
--- a/toxcore/TCP_client.c
+++ b/toxcore/TCP_client.c
@@ -66,8 +66,67 @@ static int connect_sock_to(sock_t sock, IP_Port ip_port, TCP_Proxy_Info *proxy_i
66 return 1; 66 return 1;
67} 67}
68 68
69/* return 1 on success.
70 * return 0 on failure.
71 */
72static int proxy_http_generate_connection_request(TCP_Client_Connection *TCP_conn)
73{
74 char one[] = "CONNECT ";
75 char two[] = " HTTP/1.1\nHost: ";
76 char three[] = "\r\n\r\n";
77
78 char ip[INET6_ADDRSTRLEN];
79 if (!ip_parse_addr(&TCP_conn->ip_port.ip, ip, sizeof(ip))) {
80 return 0;
81 }
82 const uint16_t port = ntohs(TCP_conn->ip_port.port);
83 const int written = sprintf(TCP_conn->last_packet, "%s%s:%hu%s%s:%hu%s", one, ip, port, two, ip, port, three);
84 if (written < 0) {
85 return 0;
86 }
87
88 TCP_conn->last_packet_length = written;
89 TCP_conn->last_packet_sent = 0;
90
91 return 1;
92}
69 93
70static void socks5_generate_handshake(TCP_Client_Connection *TCP_conn) 94/* return 1 on success.
95 * return 0 if no data received.
96 * return -1 on failure (connection refused).
97 */
98static int proxy_http_read_connection_response(TCP_Client_Connection *TCP_conn)
99{
100 char success[] = "200";
101 uint8_t data[16]; // draining works the best if the length is a power of 2
102
103 int ret = read_TCP_packet(TCP_conn->sock, data, sizeof(data) - 1);
104
105 if (ret == -1) {
106 return 0;
107 }
108
109 data[sizeof(data) - 1] = '\0';
110
111 if (strstr(data, success)) {
112 // drain all data
113 // instead of drainining it byte by byte do it in bigger chunks
114 // decrementing to 1
115 size_t step = sizeof(data);
116 do {
117 if (ret <= 0) {
118 step = step % 2 == 0 ? step/2 : 1;
119 }
120 ret = read_TCP_packet(TCP_conn->sock, data, step);
121 } while (ret > 0 || step != 1);
122
123 return 1;
124 }
125
126 return -1;
127}
128
129static void proxy_socks5_generate_handshake(TCP_Client_Connection *TCP_conn)
71{ 130{
72 TCP_conn->last_packet[0] = 5; /* SOCKSv5 */ 131 TCP_conn->last_packet[0] = 5; /* SOCKSv5 */
73 TCP_conn->last_packet[1] = 1; /* number of authentication methods supported */ 132 TCP_conn->last_packet[1] = 1; /* number of authentication methods supported */
@@ -95,7 +154,7 @@ static int socks5_read_handshake_response(TCP_Client_Connection *TCP_conn)
95 return -1; 154 return -1;
96} 155}
97 156
98static void socks5_generate_connection_request(TCP_Client_Connection *TCP_conn) 157static void proxy_socks5_generate_connection_request(TCP_Client_Connection *TCP_conn)
99{ 158{
100 TCP_conn->last_packet[0] = 5; /* SOCKSv5 */ 159 TCP_conn->last_packet[0] = 5; /* SOCKSv5 */
101 TCP_conn->last_packet[1] = 1; /* command code: establish a TCP/IP stream connection */ 160 TCP_conn->last_packet[1] = 1; /* command code: establish a TCP/IP stream connection */
@@ -125,7 +184,7 @@ static void socks5_generate_connection_request(TCP_Client_Connection *TCP_conn)
125 * return 0 if no data received. 184 * return 0 if no data received.
126 * return -1 on failure (connection refused). 185 * return -1 on failure (connection refused).
127 */ 186 */
128static int socks5_read_connection_response(TCP_Client_Connection *TCP_conn) 187static int proxy_socks5_read_connection_response(TCP_Client_Connection *TCP_conn)
129{ 188{
130 if (TCP_conn->ip_port.ip.family == AF_INET) { 189 if (TCP_conn->ip_port.ip.family == AF_INET) {
131 uint8_t data[4 + sizeof(IP4) + sizeof(uint16_t)]; 190 uint8_t data[4 + sizeof(IP4) + sizeof(uint16_t)];
@@ -578,10 +637,14 @@ TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, const uint8_t *public
578 encrypt_precompute(temp->public_key, self_secret_key, temp->shared_key); 637 encrypt_precompute(temp->public_key, self_secret_key, temp->shared_key);
579 temp->ip_port = ip_port; 638 temp->ip_port = ip_port;
580 639
581 if (proxy_info) { 640 if (proxy_info && proxy_info->is_http) {
582 temp->status = TCP_CLIENT_PROXY_CONNECTING; 641 temp->status = TCP_CLIENT_PROXY_HTTP_CONNECTING;
642 temp->proxy_info = *proxy_info;
643 proxy_http_generate_connection_request(temp);
644 } else if (proxy_info && !proxy_info->is_http) {
645 temp->status = TCP_CLIENT_PROXY_SOCKS5_CONNECTING;
583 temp->proxy_info = *proxy_info; 646 temp->proxy_info = *proxy_info;
584 socks5_generate_handshake(temp); 647 proxy_socks5_generate_handshake(temp);
585 } else { 648 } else {
586 temp->status = TCP_CLIENT_CONNECTING; 649 temp->status = TCP_CLIENT_CONNECTING;
587 650
@@ -783,7 +846,23 @@ void do_TCP_connection(TCP_Client_Connection *TCP_connection)
783 return; 846 return;
784 } 847 }
785 848
786 if (TCP_connection->status == TCP_CLIENT_PROXY_CONNECTING) { 849 if (TCP_connection->status == TCP_CLIENT_PROXY_HTTP_CONNECTING) {
850 if (send_pending_data(TCP_connection) == 0) {
851 int ret = proxy_http_read_connection_response(TCP_connection);
852
853 if (ret == -1) {
854 TCP_connection->kill_at = 0;
855 TCP_connection->status = TCP_CLIENT_DISCONNECTED;
856 }
857
858 if (ret == 1) {
859 generate_handshake(TCP_connection);
860 TCP_connection->status = TCP_CLIENT_CONNECTING;
861 }
862 }
863 }
864
865 if (TCP_connection->status == TCP_CLIENT_PROXY_SOCKS5_CONNECTING) {
787 if (send_pending_data(TCP_connection) == 0) { 866 if (send_pending_data(TCP_connection) == 0) {
788 int ret = socks5_read_handshake_response(TCP_connection); 867 int ret = socks5_read_handshake_response(TCP_connection);
789 868
@@ -793,15 +872,15 @@ void do_TCP_connection(TCP_Client_Connection *TCP_connection)
793 } 872 }
794 873
795 if (ret == 1) { 874 if (ret == 1) {
796 socks5_generate_connection_request(TCP_connection); 875 proxy_socks5_generate_connection_request(TCP_connection);
797 TCP_connection->status = TCP_CLIENT_PROXY_UNCONFIRMED; 876 TCP_connection->status = TCP_CLIENT_PROXY_SOCKS5_UNCONFIRMED;
798 } 877 }
799 } 878 }
800 } 879 }
801 880
802 if (TCP_connection->status == TCP_CLIENT_PROXY_UNCONFIRMED) { 881 if (TCP_connection->status == TCP_CLIENT_PROXY_SOCKS5_UNCONFIRMED) {
803 if (send_pending_data(TCP_connection) == 0) { 882 if (send_pending_data(TCP_connection) == 0) {
804 int ret = socks5_read_connection_response(TCP_connection); 883 int ret = proxy_socks5_read_connection_response(TCP_connection);
805 884
806 if (ret == -1) { 885 if (ret == -1) {
807 TCP_connection->kill_at = 0; 886 TCP_connection->kill_at = 0;
diff --git a/toxcore/TCP_client.h b/toxcore/TCP_client.h
index 83cb48ba..8a1aeec1 100644
--- a/toxcore/TCP_client.h
+++ b/toxcore/TCP_client.h
@@ -31,12 +31,14 @@
31 31
32typedef struct { 32typedef struct {
33 IP_Port ip_port; 33 IP_Port ip_port;
34 int is_http; /* HTTP proxy on true, SOCKS5 on false */
34} TCP_Proxy_Info; 35} TCP_Proxy_Info;
35 36
36enum { 37enum {
37 TCP_CLIENT_NO_STATUS, 38 TCP_CLIENT_NO_STATUS,
38 TCP_CLIENT_PROXY_CONNECTING, 39 TCP_CLIENT_PROXY_HTTP_CONNECTING,
39 TCP_CLIENT_PROXY_UNCONFIRMED, 40 TCP_CLIENT_PROXY_SOCKS5_CONNECTING,
41 TCP_CLIENT_PROXY_SOCKS5_UNCONFIRMED,
40 TCP_CLIENT_CONNECTING, 42 TCP_CLIENT_CONNECTING,
41 TCP_CLIENT_UNCONFIRMED, 43 TCP_CLIENT_UNCONFIRMED,
42 TCP_CLIENT_CONFIRMED, 44 TCP_CLIENT_CONFIRMED,
diff --git a/toxcore/network.c b/toxcore/network.c
index 35ef5221..5539de6b 100644
--- a/toxcore/network.c
+++ b/toxcore/network.c
@@ -784,6 +784,9 @@ void ipport_unpack(IP_Port *target, const uint8_t *data)
784/* ip_ntoa 784/* ip_ntoa
785 * converts ip into a string 785 * converts ip into a string
786 * uses a static buffer, so mustn't used multiple times in the same output 786 * uses a static buffer, so mustn't used multiple times in the same output
787 *
788 * IPv6 addresses are enclosed into square brackets, i.e. "[IPv6]"
789 * writes error message into the buffer on error
787 */ 790 */
788/* there would be INET6_ADDRSTRLEN, but it might be too short for the error message */ 791/* there would be INET6_ADDRSTRLEN, but it might be too short for the error message */
789static char addresstext[96]; 792static char addresstext[96];
@@ -816,6 +819,38 @@ const char *ip_ntoa(const IP *ip)
816} 819}
817 820
818/* 821/*
822 * ip_parse_addr
823 * parses IP structure into an address string
824 *
825 * input
826 * ip: ip of AF_INET or AF_INET6 families
827 * length: length of the address buffer
828 * Must be at least INET_ADDRSTRLEN for AF_INET
829 * and INET6_ADDRSTRLEN for AF_INET6
830 *
831 * output
832 * address: dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6)
833 *
834 * returns 1 on success, 0 on failure
835 */
836int ip_parse_addr(const IP *ip, char *address, size_t length)
837{
838 if (!address || !ip) {
839 return 0;
840 }
841
842 if (ip->family == AF_INET) {
843 struct in_addr *addr = (struct in_addr *)&ip->ip4;
844 return inet_ntop(ip->family, addr, address, length) != NULL;
845 } else if (ip->family == AF_INET6) {
846 struct in6_addr *addr = (struct in6_addr *)&ip->ip6;
847 return inet_ntop(ip->family, addr, address, length) != NULL;
848 }
849
850 return 0;
851}
852
853/*
819 * addr_parse_ip 854 * addr_parse_ip
820 * directly parses the input into an IP structure 855 * directly parses the input into an IP structure
821 * tries IPv4 first, then IPv6 856 * tries IPv4 first, then IPv6
diff --git a/toxcore/network.h b/toxcore/network.h
index ccda7ae9..5f9af490 100644
--- a/toxcore/network.h
+++ b/toxcore/network.h
@@ -180,10 +180,30 @@ IP_Port;
180/* ip_ntoa 180/* ip_ntoa
181 * converts ip into a string 181 * converts ip into a string
182 * uses a static buffer, so mustn't used multiple times in the same output 182 * uses a static buffer, so mustn't used multiple times in the same output
183 *
184 * IPv6 addresses are enclosed into square brackets, i.e. "[IPv6]"
185 * writes error message into the buffer on error
183 */ 186 */
184const char *ip_ntoa(const IP *ip); 187const char *ip_ntoa(const IP *ip);
185 188
186/* 189/*
190 * ip_parse_addr
191 * parses IP structure into an address string
192 *
193 * input
194 * ip: ip of AF_INET or AF_INET6 families
195 * length: length of the address buffer
196 * Must be at least INET_ADDRSTRLEN for AF_INET
197 * and INET6_ADDRSTRLEN for AF_INET6
198 *
199 * output
200 * address: dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6)
201 *
202 * returns 1 on success, 0 on failure
203 */
204int ip_parse_addr(const IP *ip, char *address, size_t length);
205
206/*
187 * addr_parse_ip 207 * addr_parse_ip
188 * directly parses the input into an IP structure 208 * directly parses the input into an IP structure
189 * tries IPv4 first, then IPv6 209 * tries IPv4 first, then IPv6
diff --git a/toxcore/tox.c b/toxcore/tox.c
index 66587011..3f3a05b0 100644
--- a/toxcore/tox.c
+++ b/toxcore/tox.c
@@ -1021,6 +1021,7 @@ Tox *tox_new(Tox_Options *options)
1021 m_options.ipv6enabled = options->ipv6enabled; 1021 m_options.ipv6enabled = options->ipv6enabled;
1022 m_options.udp_disabled = options->udp_disabled; 1022 m_options.udp_disabled = options->udp_disabled;
1023 m_options.proxy_enabled = options->proxy_enabled; 1023 m_options.proxy_enabled = options->proxy_enabled;
1024 m_options.proxy_info.is_http = options->proxy_is_http;
1024 1025
1025 if (m_options.proxy_enabled) { 1026 if (m_options.proxy_enabled) {
1026 ip_init(&m_options.proxy_info.ip_port.ip, m_options.ipv6enabled); 1027 ip_init(&m_options.proxy_info.ip_port.ip, m_options.ipv6enabled);
diff --git a/toxcore/tox.h b/toxcore/tox.h
index 3b72eede..f2c102ab 100644
--- a/toxcore/tox.h
+++ b/toxcore/tox.h
@@ -892,6 +892,7 @@ typedef struct {
892 uint8_t proxy_enabled; 892 uint8_t proxy_enabled;
893 char proxy_address[256]; /* Proxy ip or domain in NULL terminated string format. */ 893 char proxy_address[256]; /* Proxy ip or domain in NULL terminated string format. */
894 uint16_t proxy_port; /* Proxy port: in host byte order. */ 894 uint16_t proxy_port; /* Proxy port: in host byte order. */
895 uint8_t proxy_is_http; /*1: HTTP proxy, 0: SOCKS5 proxy*/
895} Tox_Options; 896} Tox_Options;
896 897
897/* 898/*