mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
Merge branch 'http-proxy-feature' of https://github.com/nurupo/InsertProjectNameHere
This commit is contained in:
commit
fe57a72659
4
INSTALL
4
INSTALL
|
@ -12,8 +12,8 @@ without warranty of any kind.
|
|||
Basic Installation
|
||||
==================
|
||||
|
||||
Briefly, the shell commands `./configure; make; make install' should
|
||||
configure, build, and install this package. The following
|
||||
Briefly, the shell command `./configure && make && make install'
|
||||
should configure, build, and install this package. The following
|
||||
more-detailed instructions are generic; see the `README' file for
|
||||
instructions specific to this package. Some packages provide this
|
||||
`INSTALL' file but do not implement all of the features documented
|
||||
|
|
|
@ -1595,11 +1595,7 @@ Messenger *new_messenger(Messenger_Options *options)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (options->proxy_enabled) {
|
||||
m->net_crypto = new_net_crypto(m->dht, &options->proxy_info);
|
||||
} else {
|
||||
m->net_crypto = new_net_crypto(m->dht, 0);
|
||||
}
|
||||
m->net_crypto = new_net_crypto(m->dht, &options->proxy_info);
|
||||
|
||||
if (m->net_crypto == NULL) {
|
||||
kill_networking(m->net);
|
||||
|
|
|
@ -75,7 +75,6 @@
|
|||
typedef struct {
|
||||
uint8_t ipv6enabled;
|
||||
uint8_t udp_disabled;
|
||||
uint8_t proxy_enabled;
|
||||
TCP_Proxy_Info proxy_info;
|
||||
} Messenger_Options;
|
||||
|
||||
|
|
|
@ -37,8 +37,9 @@
|
|||
*/
|
||||
static int connect_sock_to(sock_t sock, IP_Port ip_port, TCP_Proxy_Info *proxy_info)
|
||||
{
|
||||
if (proxy_info)
|
||||
ip_port = proxy_info->ip_port;
|
||||
if (proxy_info->proxy_type != TCP_PROXY_NONE) {
|
||||
ip_port =proxy_info->ip_port;
|
||||
}
|
||||
|
||||
struct sockaddr_storage addr = {0};
|
||||
size_t addrsize;
|
||||
|
@ -66,8 +67,67 @@ static int connect_sock_to(sock_t sock, IP_Port ip_port, TCP_Proxy_Info *proxy_i
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* return 1 on success.
|
||||
* return 0 on failure.
|
||||
*/
|
||||
static int proxy_http_generate_connection_request(TCP_Client_Connection *TCP_conn)
|
||||
{
|
||||
char one[] = "CONNECT ";
|
||||
char two[] = " HTTP/1.1\nHost: ";
|
||||
char three[] = "\r\n\r\n";
|
||||
|
||||
static void socks5_generate_handshake(TCP_Client_Connection *TCP_conn)
|
||||
char ip[INET6_ADDRSTRLEN];
|
||||
if (!ip_parse_addr(&TCP_conn->ip_port.ip, ip, sizeof(ip))) {
|
||||
return 0;
|
||||
}
|
||||
const uint16_t port = ntohs(TCP_conn->ip_port.port);
|
||||
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);
|
||||
if (written < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
TCP_conn->last_packet_length = written;
|
||||
TCP_conn->last_packet_sent = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* return 1 on success.
|
||||
* return 0 if no data received.
|
||||
* return -1 on failure (connection refused).
|
||||
*/
|
||||
static int proxy_http_read_connection_response(TCP_Client_Connection *TCP_conn)
|
||||
{
|
||||
char success[] = "200";
|
||||
uint8_t data[16]; // draining works the best if the length is a power of 2
|
||||
|
||||
int ret = read_TCP_packet(TCP_conn->sock, data, sizeof(data) - 1);
|
||||
|
||||
if (ret == -1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
data[sizeof(data) - 1] = '\0';
|
||||
|
||||
if (strstr(data, success)) {
|
||||
// drain all data
|
||||
// instead of drainining it byte by byte do it in bigger chunks
|
||||
// decrementing to 1
|
||||
size_t step = sizeof(data);
|
||||
do {
|
||||
if (ret <= 0) {
|
||||
step = step % 2 == 0 ? step/2 : 1;
|
||||
}
|
||||
ret = read_TCP_packet(TCP_conn->sock, data, step);
|
||||
} while (ret > 0 || step != 1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void proxy_socks5_generate_handshake(TCP_Client_Connection *TCP_conn)
|
||||
{
|
||||
TCP_conn->last_packet[0] = 5; /* SOCKSv5 */
|
||||
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)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static void socks5_generate_connection_request(TCP_Client_Connection *TCP_conn)
|
||||
static void proxy_socks5_generate_connection_request(TCP_Client_Connection *TCP_conn)
|
||||
{
|
||||
TCP_conn->last_packet[0] = 5; /* SOCKSv5 */
|
||||
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)
|
|||
* return 0 if no data received.
|
||||
* return -1 on failure (connection refused).
|
||||
*/
|
||||
static int socks5_read_connection_response(TCP_Client_Connection *TCP_conn)
|
||||
static int proxy_socks5_read_connection_response(TCP_Client_Connection *TCP_conn)
|
||||
{
|
||||
if (TCP_conn->ip_port.ip.family == AF_INET) {
|
||||
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
|
|||
|
||||
uint8_t family = ip_port.ip.family;
|
||||
|
||||
if (proxy_info)
|
||||
if (proxy_info->proxy_type != TCP_PROXY_NONE) {
|
||||
family = proxy_info->ip_port.ip.family;
|
||||
}
|
||||
|
||||
sock_t sock = socket(family, SOCK_STREAM, IPPROTO_TCP);
|
||||
|
||||
|
@ -577,19 +638,26 @@ TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, const uint8_t *public
|
|||
memcpy(temp->self_public_key, self_public_key, crypto_box_PUBLICKEYBYTES);
|
||||
encrypt_precompute(temp->public_key, self_secret_key, temp->shared_key);
|
||||
temp->ip_port = ip_port;
|
||||
temp->proxy_info = *proxy_info;
|
||||
|
||||
if (proxy_info) {
|
||||
temp->status = TCP_CLIENT_PROXY_CONNECTING;
|
||||
temp->proxy_info = *proxy_info;
|
||||
socks5_generate_handshake(temp);
|
||||
} else {
|
||||
temp->status = TCP_CLIENT_CONNECTING;
|
||||
switch (proxy_info->proxy_type) {
|
||||
case TCP_PROXY_HTTP:
|
||||
temp->status = TCP_CLIENT_PROXY_HTTP_CONNECTING;
|
||||
proxy_http_generate_connection_request(temp);
|
||||
break;
|
||||
case TCP_PROXY_SOCKS5:
|
||||
temp->status = TCP_CLIENT_PROXY_SOCKS5_CONNECTING;
|
||||
proxy_socks5_generate_handshake(temp);
|
||||
break;
|
||||
case TCP_PROXY_NONE:
|
||||
temp->status = TCP_CLIENT_CONNECTING;
|
||||
|
||||
if (generate_handshake(temp) == -1) {
|
||||
kill_sock(sock);
|
||||
free(temp);
|
||||
return NULL;
|
||||
}
|
||||
if (generate_handshake(temp) == -1) {
|
||||
kill_sock(sock);
|
||||
free(temp);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
temp->kill_at = unix_time() + TCP_CONNECTION_TIMEOUT;
|
||||
|
@ -783,7 +851,23 @@ void do_TCP_connection(TCP_Client_Connection *TCP_connection)
|
|||
return;
|
||||
}
|
||||
|
||||
if (TCP_connection->status == TCP_CLIENT_PROXY_CONNECTING) {
|
||||
if (TCP_connection->status == TCP_CLIENT_PROXY_HTTP_CONNECTING) {
|
||||
if (send_pending_data(TCP_connection) == 0) {
|
||||
int ret = proxy_http_read_connection_response(TCP_connection);
|
||||
|
||||
if (ret == -1) {
|
||||
TCP_connection->kill_at = 0;
|
||||
TCP_connection->status = TCP_CLIENT_DISCONNECTED;
|
||||
}
|
||||
|
||||
if (ret == 1) {
|
||||
generate_handshake(TCP_connection);
|
||||
TCP_connection->status = TCP_CLIENT_CONNECTING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (TCP_connection->status == TCP_CLIENT_PROXY_SOCKS5_CONNECTING) {
|
||||
if (send_pending_data(TCP_connection) == 0) {
|
||||
int ret = socks5_read_handshake_response(TCP_connection);
|
||||
|
||||
|
@ -793,15 +877,15 @@ void do_TCP_connection(TCP_Client_Connection *TCP_connection)
|
|||
}
|
||||
|
||||
if (ret == 1) {
|
||||
socks5_generate_connection_request(TCP_connection);
|
||||
TCP_connection->status = TCP_CLIENT_PROXY_UNCONFIRMED;
|
||||
proxy_socks5_generate_connection_request(TCP_connection);
|
||||
TCP_connection->status = TCP_CLIENT_PROXY_SOCKS5_UNCONFIRMED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (TCP_connection->status == TCP_CLIENT_PROXY_UNCONFIRMED) {
|
||||
if (TCP_connection->status == TCP_CLIENT_PROXY_SOCKS5_UNCONFIRMED) {
|
||||
if (send_pending_data(TCP_connection) == 0) {
|
||||
int ret = socks5_read_connection_response(TCP_connection);
|
||||
int ret = proxy_socks5_read_connection_response(TCP_connection);
|
||||
|
||||
if (ret == -1) {
|
||||
TCP_connection->kill_at = 0;
|
||||
|
|
|
@ -29,14 +29,22 @@
|
|||
|
||||
#define TCP_CONNECTION_TIMEOUT 10
|
||||
|
||||
typedef struct {
|
||||
typedef enum {
|
||||
TCP_PROXY_NONE,
|
||||
TCP_PROXY_HTTP,
|
||||
TCP_PROXY_SOCKS5
|
||||
} TCP_PROXY_TYPE;
|
||||
|
||||
typedef struct {
|
||||
IP_Port ip_port;
|
||||
uint8_t proxy_type; // a value from TCP_PROXY_TYPE
|
||||
} TCP_Proxy_Info;
|
||||
|
||||
enum {
|
||||
TCP_CLIENT_NO_STATUS,
|
||||
TCP_CLIENT_PROXY_CONNECTING,
|
||||
TCP_CLIENT_PROXY_UNCONFIRMED,
|
||||
TCP_CLIENT_PROXY_HTTP_CONNECTING,
|
||||
TCP_CLIENT_PROXY_SOCKS5_CONNECTING,
|
||||
TCP_CLIENT_PROXY_SOCKS5_UNCONFIRMED,
|
||||
TCP_CLIENT_CONNECTING,
|
||||
TCP_CLIENT_UNCONFIRMED,
|
||||
TCP_CLIENT_CONFIRMED,
|
||||
|
|
|
@ -2029,13 +2029,8 @@ int add_tcp_relay(Net_Crypto *c, IP_Port ip_port, const uint8_t *public_key)
|
|||
|
||||
for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) {
|
||||
if (c->tcp_connections_new[i] == NULL) {
|
||||
if (c->proxy_set) {
|
||||
c->tcp_connections_new[i] = new_TCP_connection(ip_port, public_key, c->dht->self_public_key, c->dht->self_secret_key,
|
||||
c->tcp_connections_new[i] = new_TCP_connection(ip_port, public_key, c->dht->self_public_key, c->dht->self_secret_key,
|
||||
&c->proxy_info);
|
||||
} else {
|
||||
c->tcp_connections_new[i] = new_TCP_connection(ip_port, public_key, c->dht->self_public_key, c->dht->self_secret_key,
|
||||
0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2768,10 +2763,7 @@ Net_Crypto *new_net_crypto(DHT *dht, TCP_Proxy_Info *proxy_info)
|
|||
|
||||
bs_list_init(&temp->ip_port_list, sizeof(IP_Port), 8);
|
||||
|
||||
if (proxy_info) {
|
||||
temp->proxy_info = *proxy_info;
|
||||
temp->proxy_set = 1;
|
||||
}
|
||||
temp->proxy_info = *proxy_info;
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
|
|
@ -215,7 +215,6 @@ typedef struct {
|
|||
int (*tcp_onion_callback)(void *object, const uint8_t *data, uint16_t length);
|
||||
void *tcp_onion_callback_object;
|
||||
|
||||
uint8_t proxy_set;
|
||||
TCP_Proxy_Info proxy_info;
|
||||
} Net_Crypto;
|
||||
|
||||
|
|
|
@ -784,6 +784,9 @@ void ipport_unpack(IP_Port *target, const uint8_t *data)
|
|||
/* ip_ntoa
|
||||
* converts ip into a string
|
||||
* uses a static buffer, so mustn't used multiple times in the same output
|
||||
*
|
||||
* IPv6 addresses are enclosed into square brackets, i.e. "[IPv6]"
|
||||
* writes error message into the buffer on error
|
||||
*/
|
||||
/* there would be INET6_ADDRSTRLEN, but it might be too short for the error message */
|
||||
static char addresstext[96];
|
||||
|
@ -815,6 +818,38 @@ const char *ip_ntoa(const IP *ip)
|
|||
return addresstext;
|
||||
}
|
||||
|
||||
/*
|
||||
* ip_parse_addr
|
||||
* parses IP structure into an address string
|
||||
*
|
||||
* input
|
||||
* ip: ip of AF_INET or AF_INET6 families
|
||||
* length: length of the address buffer
|
||||
* Must be at least INET_ADDRSTRLEN for AF_INET
|
||||
* and INET6_ADDRSTRLEN for AF_INET6
|
||||
*
|
||||
* output
|
||||
* address: dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6)
|
||||
*
|
||||
* returns 1 on success, 0 on failure
|
||||
*/
|
||||
int ip_parse_addr(const IP *ip, char *address, size_t length)
|
||||
{
|
||||
if (!address || !ip) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ip->family == AF_INET) {
|
||||
struct in_addr *addr = (struct in_addr *)&ip->ip4;
|
||||
return inet_ntop(ip->family, addr, address, length) != NULL;
|
||||
} else if (ip->family == AF_INET6) {
|
||||
struct in6_addr *addr = (struct in6_addr *)&ip->ip6;
|
||||
return inet_ntop(ip->family, addr, address, length) != NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* addr_parse_ip
|
||||
* directly parses the input into an IP structure
|
||||
|
|
|
@ -180,9 +180,29 @@ IP_Port;
|
|||
/* ip_ntoa
|
||||
* converts ip into a string
|
||||
* uses a static buffer, so mustn't used multiple times in the same output
|
||||
*
|
||||
* IPv6 addresses are enclosed into square brackets, i.e. "[IPv6]"
|
||||
* writes error message into the buffer on error
|
||||
*/
|
||||
const char *ip_ntoa(const IP *ip);
|
||||
|
||||
/*
|
||||
* ip_parse_addr
|
||||
* parses IP structure into an address string
|
||||
*
|
||||
* input
|
||||
* ip: ip of AF_INET or AF_INET6 families
|
||||
* length: length of the address buffer
|
||||
* Must be at least INET_ADDRSTRLEN for AF_INET
|
||||
* and INET6_ADDRSTRLEN for AF_INET6
|
||||
*
|
||||
* output
|
||||
* address: dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6)
|
||||
*
|
||||
* returns 1 on success, 0 on failure
|
||||
*/
|
||||
int ip_parse_addr(const IP *ip, char *address, size_t length);
|
||||
|
||||
/*
|
||||
* addr_parse_ip
|
||||
* directly parses the input into an IP structure
|
||||
|
|
|
@ -1020,9 +1020,20 @@ Tox *tox_new(Tox_Options *options)
|
|||
} else {
|
||||
m_options.ipv6enabled = options->ipv6enabled;
|
||||
m_options.udp_disabled = options->udp_disabled;
|
||||
m_options.proxy_enabled = options->proxy_enabled;
|
||||
|
||||
if (m_options.proxy_enabled) {
|
||||
switch (options->proxy_type) {
|
||||
case TOX_PROXY_HTTP:
|
||||
m_options.proxy_info.proxy_type = TCP_PROXY_HTTP;
|
||||
break;
|
||||
case TOX_PROXY_SOCKS5:
|
||||
m_options.proxy_info.proxy_type = TCP_PROXY_SOCKS5;
|
||||
break;
|
||||
case TOX_PROXY_NONE:
|
||||
m_options.proxy_info.proxy_type = TCP_PROXY_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_options.proxy_info.proxy_type != TCP_PROXY_NONE) {
|
||||
ip_init(&m_options.proxy_info.ip_port.ip, m_options.ipv6enabled);
|
||||
|
||||
if (m_options.ipv6enabled)
|
||||
|
|
|
@ -873,6 +873,12 @@ int tox_add_tcp_relay(Tox *tox, const char *address, uint16_t port, const uint8_
|
|||
*/
|
||||
int tox_isconnected(const Tox *tox);
|
||||
|
||||
typedef enum {
|
||||
TOX_PROXY_NONE,
|
||||
TOX_PROXY_HTTP,
|
||||
TOX_PROXY_SOCKS5
|
||||
} TOX_PROXY_TYPE;
|
||||
|
||||
typedef struct {
|
||||
/*
|
||||
* The type of UDP socket created depends on ipv6enabled:
|
||||
|
@ -885,13 +891,11 @@ typedef struct {
|
|||
|
||||
/* Set to 1 to disable udp support. (default: 0)
|
||||
This will force Tox to use TCP only which may slow things down.
|
||||
Disabling udp support is necessary when using anonymous proxies or Tor.*/
|
||||
Disabling udp support is necessary when using proxies or Tor.*/
|
||||
uint8_t udp_disabled;
|
||||
|
||||
/* Enable proxy support. (only basic TCP socks5 proxy currently supported.) (default: 0 (disabled))*/
|
||||
uint8_t proxy_enabled;
|
||||
uint8_t proxy_type; /* a value from TOX_PROXY_TYPE */
|
||||
char proxy_address[256]; /* Proxy ip or domain in NULL terminated string format. */
|
||||
uint16_t proxy_port; /* Proxy port: in host byte order. */
|
||||
uint16_t proxy_port; /* Proxy port in host byte order. */
|
||||
} Tox_Options;
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue
Block a user