summaryrefslogtreecommitdiff
path: root/toxcore/TCP_client.c
diff options
context:
space:
mode:
authorirungentoo <irungentoo@gmail.com>2014-12-26 19:38:19 -0500
committerirungentoo <irungentoo@gmail.com>2014-12-26 19:38:19 -0500
commitfe57a72659a8a298d8c11f7355d15815dee10195 (patch)
treeaa3064268b325cb1ceb145cb5a367d1df6c1c4f9 /toxcore/TCP_client.c
parenta4f0b65ad72682e6ca2becf3081f7e5e72a0f7af (diff)
parent35602e12c007aec38f65c860cad5f03953c4596d (diff)
Merge branch 'http-proxy-feature' of https://github.com/nurupo/InsertProjectNameHere
Diffstat (limited to 'toxcore/TCP_client.c')
-rw-r--r--toxcore/TCP_client.c128
1 files changed, 106 insertions, 22 deletions
diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c
index 23ab28c0..aee309ae 100644
--- a/toxcore/TCP_client.c
+++ b/toxcore/TCP_client.c
@@ -37,8 +37,9 @@
37 */ 37 */
38static int connect_sock_to(sock_t sock, IP_Port ip_port, TCP_Proxy_Info *proxy_info) 38static int connect_sock_to(sock_t sock, IP_Port ip_port, TCP_Proxy_Info *proxy_info)
39{ 39{
40 if (proxy_info) 40 if (proxy_info->proxy_type != TCP_PROXY_NONE) {
41 ip_port = proxy_info->ip_port; 41 ip_port =proxy_info->ip_port;
42 }
42 43
43 struct sockaddr_storage addr = {0}; 44 struct sockaddr_storage addr = {0};
44 size_t addrsize; 45 size_t addrsize;
@@ -66,8 +67,67 @@ static int connect_sock_to(sock_t sock, IP_Port ip_port, TCP_Proxy_Info *proxy_i
66 return 1; 67 return 1;
67} 68}
68 69
70/* return 1 on success.
71 * return 0 on failure.
72 */
73static int proxy_http_generate_connection_request(TCP_Client_Connection *TCP_conn)
74{
75 char one[] = "CONNECT ";
76 char two[] = " HTTP/1.1\nHost: ";
77 char three[] = "\r\n\r\n";
78
79 char ip[INET6_ADDRSTRLEN];
80 if (!ip_parse_addr(&TCP_conn->ip_port.ip, ip, sizeof(ip))) {
81 return 0;
82 }
83 const uint16_t port = ntohs(TCP_conn->ip_port.port);
84 const int written = snprintf(TCP_conn->last_packet, MAX_PACKET_SIZE, "%s%s:%hu%s%s:%hu%s", one, ip, port, two, ip, port, three);
85 if (written < 0) {
86 return 0;
87 }
88
89 TCP_conn->last_packet_length = written;
90 TCP_conn->last_packet_sent = 0;
91
92 return 1;
93}
94
95/* return 1 on success.
96 * return 0 if no data received.
97 * return -1 on failure (connection refused).
98 */
99static int proxy_http_read_connection_response(TCP_Client_Connection *TCP_conn)
100{
101 char success[] = "200";
102 uint8_t data[16]; // draining works the best if the length is a power of 2
103
104 int ret = read_TCP_packet(TCP_conn->sock, data, sizeof(data) - 1);
105
106 if (ret == -1) {
107 return 0;
108 }
109
110 data[sizeof(data) - 1] = '\0';
111
112 if (strstr(data, success)) {
113 // drain all data
114 // instead of drainining it byte by byte do it in bigger chunks
115 // decrementing to 1
116 size_t step = sizeof(data);
117 do {
118 if (ret <= 0) {
119 step = step % 2 == 0 ? step/2 : 1;
120 }
121 ret = read_TCP_packet(TCP_conn->sock, data, step);
122 } while (ret > 0 || step != 1);
123
124 return 1;
125 }
69 126
70static void socks5_generate_handshake(TCP_Client_Connection *TCP_conn) 127 return -1;
128}
129
130static void proxy_socks5_generate_handshake(TCP_Client_Connection *TCP_conn)
71{ 131{
72 TCP_conn->last_packet[0] = 5; /* SOCKSv5 */ 132 TCP_conn->last_packet[0] = 5; /* SOCKSv5 */
73 TCP_conn->last_packet[1] = 1; /* number of authentication methods supported */ 133 TCP_conn->last_packet[1] = 1; /* number of authentication methods supported */
@@ -95,7 +155,7 @@ static int socks5_read_handshake_response(TCP_Client_Connection *TCP_conn)
95 return -1; 155 return -1;
96} 156}
97 157
98static void socks5_generate_connection_request(TCP_Client_Connection *TCP_conn) 158static void proxy_socks5_generate_connection_request(TCP_Client_Connection *TCP_conn)
99{ 159{
100 TCP_conn->last_packet[0] = 5; /* SOCKSv5 */ 160 TCP_conn->last_packet[0] = 5; /* SOCKSv5 */
101 TCP_conn->last_packet[1] = 1; /* command code: establish a TCP/IP stream connection */ 161 TCP_conn->last_packet[1] = 1; /* command code: establish a TCP/IP stream connection */
@@ -125,7 +185,7 @@ static void socks5_generate_connection_request(TCP_Client_Connection *TCP_conn)
125 * return 0 if no data received. 185 * return 0 if no data received.
126 * return -1 on failure (connection refused). 186 * return -1 on failure (connection refused).
127 */ 187 */
128static int socks5_read_connection_response(TCP_Client_Connection *TCP_conn) 188static int proxy_socks5_read_connection_response(TCP_Client_Connection *TCP_conn)
129{ 189{
130 if (TCP_conn->ip_port.ip.family == AF_INET) { 190 if (TCP_conn->ip_port.ip.family == AF_INET) {
131 uint8_t data[4 + sizeof(IP4) + sizeof(uint16_t)]; 191 uint8_t data[4 + sizeof(IP4) + sizeof(uint16_t)];
@@ -546,8 +606,9 @@ TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, const uint8_t *public
546 606
547 uint8_t family = ip_port.ip.family; 607 uint8_t family = ip_port.ip.family;
548 608
549 if (proxy_info) 609 if (proxy_info->proxy_type != TCP_PROXY_NONE) {
550 family = proxy_info->ip_port.ip.family; 610 family = proxy_info->ip_port.ip.family;
611 }
551 612
552 sock_t sock = socket(family, SOCK_STREAM, IPPROTO_TCP); 613 sock_t sock = socket(family, SOCK_STREAM, IPPROTO_TCP);
553 614
@@ -577,19 +638,26 @@ TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, const uint8_t *public
577 memcpy(temp->self_public_key, self_public_key, crypto_box_PUBLICKEYBYTES); 638 memcpy(temp->self_public_key, self_public_key, crypto_box_PUBLICKEYBYTES);
578 encrypt_precompute(temp->public_key, self_secret_key, temp->shared_key); 639 encrypt_precompute(temp->public_key, self_secret_key, temp->shared_key);
579 temp->ip_port = ip_port; 640 temp->ip_port = ip_port;
641 temp->proxy_info = *proxy_info;
580 642
581 if (proxy_info) { 643 switch (proxy_info->proxy_type) {
582 temp->status = TCP_CLIENT_PROXY_CONNECTING; 644 case TCP_PROXY_HTTP:
583 temp->proxy_info = *proxy_info; 645 temp->status = TCP_CLIENT_PROXY_HTTP_CONNECTING;
584 socks5_generate_handshake(temp); 646 proxy_http_generate_connection_request(temp);
585 } else { 647 break;
586 temp->status = TCP_CLIENT_CONNECTING; 648 case TCP_PROXY_SOCKS5:
649 temp->status = TCP_CLIENT_PROXY_SOCKS5_CONNECTING;
650 proxy_socks5_generate_handshake(temp);
651 break;
652 case TCP_PROXY_NONE:
653 temp->status = TCP_CLIENT_CONNECTING;
587 654
588 if (generate_handshake(temp) == -1) { 655 if (generate_handshake(temp) == -1) {
589 kill_sock(sock); 656 kill_sock(sock);
590 free(temp); 657 free(temp);
591 return NULL; 658 return NULL;
592 } 659 }
660 break;
593 } 661 }
594 662
595 temp->kill_at = unix_time() + TCP_CONNECTION_TIMEOUT; 663 temp->kill_at = unix_time() + TCP_CONNECTION_TIMEOUT;
@@ -783,7 +851,23 @@ void do_TCP_connection(TCP_Client_Connection *TCP_connection)
783 return; 851 return;
784 } 852 }
785 853
786 if (TCP_connection->status == TCP_CLIENT_PROXY_CONNECTING) { 854 if (TCP_connection->status == TCP_CLIENT_PROXY_HTTP_CONNECTING) {
855 if (send_pending_data(TCP_connection) == 0) {
856 int ret = proxy_http_read_connection_response(TCP_connection);
857
858 if (ret == -1) {
859 TCP_connection->kill_at = 0;
860 TCP_connection->status = TCP_CLIENT_DISCONNECTED;
861 }
862
863 if (ret == 1) {
864 generate_handshake(TCP_connection);
865 TCP_connection->status = TCP_CLIENT_CONNECTING;
866 }
867 }
868 }
869
870 if (TCP_connection->status == TCP_CLIENT_PROXY_SOCKS5_CONNECTING) {
787 if (send_pending_data(TCP_connection) == 0) { 871 if (send_pending_data(TCP_connection) == 0) {
788 int ret = socks5_read_handshake_response(TCP_connection); 872 int ret = socks5_read_handshake_response(TCP_connection);
789 873
@@ -793,15 +877,15 @@ void do_TCP_connection(TCP_Client_Connection *TCP_connection)
793 } 877 }
794 878
795 if (ret == 1) { 879 if (ret == 1) {
796 socks5_generate_connection_request(TCP_connection); 880 proxy_socks5_generate_connection_request(TCP_connection);
797 TCP_connection->status = TCP_CLIENT_PROXY_UNCONFIRMED; 881 TCP_connection->status = TCP_CLIENT_PROXY_SOCKS5_UNCONFIRMED;
798 } 882 }
799 } 883 }
800 } 884 }
801 885
802 if (TCP_connection->status == TCP_CLIENT_PROXY_UNCONFIRMED) { 886 if (TCP_connection->status == TCP_CLIENT_PROXY_SOCKS5_UNCONFIRMED) {
803 if (send_pending_data(TCP_connection) == 0) { 887 if (send_pending_data(TCP_connection) == 0) {
804 int ret = socks5_read_connection_response(TCP_connection); 888 int ret = proxy_socks5_read_connection_response(TCP_connection);
805 889
806 if (ret == -1) { 890 if (ret == -1) {
807 TCP_connection->kill_at = 0; 891 TCP_connection->kill_at = 0;