mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
Added TCP_client.
Some work done on the TCP part.
This commit is contained in:
parent
ef744ebbc2
commit
bd0d24fc9c
|
@ -10,6 +10,8 @@
|
|||
#include <time.h>
|
||||
|
||||
#include "../toxcore/TCP_server.h"
|
||||
#include "../toxcore/TCP_client.h"
|
||||
|
||||
#include "../toxcore/util.h"
|
||||
|
||||
#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
|
||||
|
@ -21,7 +23,7 @@
|
|||
|
||||
#define NUM_PORTS 3
|
||||
|
||||
uint16_t ports[NUM_PORTS] = {12345, 33445, 25643};
|
||||
uint16_t ports[NUM_PORTS] = {1234, 33445, 25643};
|
||||
|
||||
START_TEST(test_basic)
|
||||
{
|
||||
|
@ -30,6 +32,7 @@ START_TEST(test_basic)
|
|||
crypto_box_keypair(self_public_key, self_secret_key);
|
||||
TCP_Server *tcp_s = new_TCP_server(1, NUM_PORTS, ports, self_public_key, self_secret_key, NULL);
|
||||
ck_assert_msg(tcp_s != NULL, "Failed to create TCP relay server");
|
||||
ck_assert_msg(tcp_s->num_listening_socks == NUM_PORTS, "Failed to bind to all ports");
|
||||
|
||||
sock_t sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
|
||||
struct sockaddr_in6 addr6_loopback = {0};
|
||||
|
@ -204,6 +207,7 @@ START_TEST(test_some)
|
|||
crypto_box_keypair(self_public_key, self_secret_key);
|
||||
TCP_Server *tcp_s = new_TCP_server(1, NUM_PORTS, ports, self_public_key, self_secret_key, NULL);
|
||||
ck_assert_msg(tcp_s != NULL, "Failed to create TCP relay server");
|
||||
ck_assert_msg(tcp_s->num_listening_socks == NUM_PORTS, "Failed to bind to all ports");
|
||||
|
||||
struct sec_TCP_con *con1 = new_TCP_con(tcp_s);
|
||||
struct sec_TCP_con *con2 = new_TCP_con(tcp_s);
|
||||
|
@ -287,6 +291,69 @@ START_TEST(test_some)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_client)
|
||||
{
|
||||
unix_time_update();
|
||||
uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
|
||||
uint8_t self_secret_key[crypto_box_SECRETKEYBYTES];
|
||||
crypto_box_keypair(self_public_key, self_secret_key);
|
||||
TCP_Server *tcp_s = new_TCP_server(1, NUM_PORTS, ports, self_public_key, self_secret_key, NULL);
|
||||
ck_assert_msg(tcp_s != NULL, "Failed to create TCP relay server");
|
||||
ck_assert_msg(tcp_s->num_listening_socks == NUM_PORTS, "Failed to bind to all ports");
|
||||
|
||||
uint8_t f_public_key[crypto_box_PUBLICKEYBYTES];
|
||||
uint8_t f_secret_key[crypto_box_SECRETKEYBYTES];
|
||||
crypto_box_keypair(f_public_key, f_secret_key);
|
||||
IP_Port ip_port_tcp_s;
|
||||
|
||||
ip_port_tcp_s.port = htons(ports[rand() % NUM_PORTS]);
|
||||
ip_port_tcp_s.ip.family = AF_INET6;
|
||||
ip_port_tcp_s.ip.ip6.in6_addr = in6addr_loopback;
|
||||
TCP_Client_Connection *conn = new_TCP_connection(ip_port_tcp_s, self_public_key, f_public_key, f_secret_key);
|
||||
c_sleep(50);
|
||||
do_TCP_connection(conn);
|
||||
ck_assert_msg(conn->status == TCP_CLIENT_UNCONFIRMED, "Wrong status. Expected: %u, is: %u", TCP_CLIENT_UNCONFIRMED,
|
||||
conn->status);
|
||||
c_sleep(50);
|
||||
do_TCP_server(tcp_s);
|
||||
c_sleep(50);
|
||||
do_TCP_connection(conn);
|
||||
ck_assert_msg(conn->status == TCP_CLIENT_CONFIRMED, "Wrong status. Expected: %u, is: %u", TCP_CLIENT_CONFIRMED,
|
||||
conn->status);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_client_invalid)
|
||||
{
|
||||
unix_time_update();
|
||||
uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
|
||||
uint8_t self_secret_key[crypto_box_SECRETKEYBYTES];
|
||||
crypto_box_keypair(self_public_key, self_secret_key);
|
||||
|
||||
uint8_t f_public_key[crypto_box_PUBLICKEYBYTES];
|
||||
uint8_t f_secret_key[crypto_box_SECRETKEYBYTES];
|
||||
crypto_box_keypair(f_public_key, f_secret_key);
|
||||
IP_Port ip_port_tcp_s;
|
||||
|
||||
ip_port_tcp_s.port = htons(ports[rand() % NUM_PORTS]);
|
||||
ip_port_tcp_s.ip.family = AF_INET6;
|
||||
ip_port_tcp_s.ip.ip6.in6_addr = in6addr_loopback;
|
||||
TCP_Client_Connection *conn = new_TCP_connection(ip_port_tcp_s, self_public_key, f_public_key, f_secret_key);
|
||||
c_sleep(50);
|
||||
do_TCP_connection(conn);
|
||||
ck_assert_msg(conn->status == TCP_CLIENT_CONNECTING, "Wrong status. Expected: %u, is: %u", TCP_CLIENT_CONNECTING,
|
||||
conn->status);
|
||||
c_sleep(5000);
|
||||
do_TCP_connection(conn);
|
||||
ck_assert_msg(conn->status == TCP_CLIENT_CONNECTING, "Wrong status. Expected: %u, is: %u", TCP_CLIENT_CONNECTING,
|
||||
conn->status);
|
||||
c_sleep(6000);
|
||||
do_TCP_connection(conn);
|
||||
ck_assert_msg(conn->status == TCP_CLIENT_DISCONNECTED, "Wrong status. Expected: %u, is: %u", TCP_CLIENT_DISCONNECTED,
|
||||
conn->status);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
#define DEFTESTCASE(NAME) \
|
||||
TCase *tc_##NAME = tcase_create(#NAME); \
|
||||
tcase_add_test(tc_##NAME, test_##NAME); \
|
||||
|
@ -301,6 +368,8 @@ Suite *TCP_suite(void)
|
|||
|
||||
DEFTESTCASE_SLOW(basic, 5);
|
||||
DEFTESTCASE_SLOW(some, 10);
|
||||
DEFTESTCASE_SLOW(client, 10);
|
||||
DEFTESTCASE_SLOW(client_invalid, 15);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
237
toxcore/TCP_client.c
Normal file
237
toxcore/TCP_client.c
Normal file
|
@ -0,0 +1,237 @@
|
|||
/*
|
||||
* TCP_client.c -- Implementation of the TCP relay client part of Tox.
|
||||
*
|
||||
* Copyright (C) 2014 Tox project All Rights Reserved.
|
||||
*
|
||||
* This file is part of Tox.
|
||||
*
|
||||
* Tox is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tox is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tox. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "TCP_client.h"
|
||||
|
||||
#if !defined(_WIN32) && !defined(__WIN32__) && !defined (WIN32)
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#include "util.h"
|
||||
|
||||
/* return 1 on success
|
||||
* return 0 on failure
|
||||
*/
|
||||
static int connect_sock_to(sock_t sock, IP_Port ip_port)
|
||||
{
|
||||
struct sockaddr_storage addr = {0};
|
||||
size_t addrsize;
|
||||
|
||||
if (ip_port.ip.family == AF_INET) {
|
||||
struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
|
||||
|
||||
addrsize = sizeof(struct sockaddr_in);
|
||||
addr4->sin_family = AF_INET;
|
||||
addr4->sin_addr = ip_port.ip.ip4.in_addr;
|
||||
addr4->sin_port = ip_port.port;
|
||||
} else if (ip_port.ip.family == AF_INET6) {
|
||||
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
|
||||
|
||||
addrsize = sizeof(struct sockaddr_in6);
|
||||
addr6->sin6_family = AF_INET6;
|
||||
addr6->sin6_addr = ip_port.ip.ip6.in6_addr;
|
||||
addr6->sin6_port = ip_port.port;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* nonblocking socket, connect will never return success */
|
||||
connect(sock, (struct sockaddr *)&addr, addrsize);
|
||||
return 1;
|
||||
}
|
||||
/* return 0 on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
static int generate_handshake(TCP_Client_Connection *TCP_conn, uint8_t *self_public_key, uint8_t *self_secret_key)
|
||||
{
|
||||
uint8_t plain[crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES];
|
||||
crypto_box_keypair(plain, TCP_conn->temp_secret_key);
|
||||
encrypt_precompute(TCP_conn->public_key, self_secret_key, TCP_conn->shared_key);
|
||||
random_nonce(TCP_conn->sent_nonce);
|
||||
memcpy(plain + crypto_box_PUBLICKEYBYTES, TCP_conn->sent_nonce, crypto_box_NONCEBYTES);
|
||||
memcpy(TCP_conn->last_packet, self_public_key, crypto_box_PUBLICKEYBYTES);
|
||||
new_nonce(TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES);
|
||||
int len = encrypt_data_fast(TCP_conn->shared_key, TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES, plain,
|
||||
sizeof(plain), TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES);
|
||||
|
||||
if (len != sizeof(plain) + crypto_box_MACBYTES)
|
||||
return -1;
|
||||
|
||||
TCP_conn->last_packet_length = crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + sizeof(plain) + crypto_box_MACBYTES;
|
||||
TCP_conn->last_packet_sent = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* data must be of length TCP_SERVER_HANDSHAKE_SIZE
|
||||
*
|
||||
* return 0 on success.
|
||||
* return -1 on failure.
|
||||
*/
|
||||
static int handle_handshake(TCP_Client_Connection *TCP_conn, uint8_t *data)
|
||||
{
|
||||
uint8_t plain[crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES];
|
||||
int len = decrypt_data_fast(TCP_conn->shared_key, data, data + crypto_box_NONCEBYTES,
|
||||
TCP_SERVER_HANDSHAKE_SIZE - crypto_box_NONCEBYTES, plain);
|
||||
|
||||
if (len != sizeof(plain))
|
||||
return -1;
|
||||
|
||||
memcpy(TCP_conn->recv_nonce, plain + crypto_box_PUBLICKEYBYTES, crypto_box_NONCEBYTES);
|
||||
encrypt_precompute(plain, TCP_conn->temp_secret_key, TCP_conn->shared_key);
|
||||
memset(TCP_conn->temp_secret_key, 0, crypto_box_SECRETKEYBYTES);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* return 0 if pending data was sent completely
|
||||
* return -1 if it wasn't
|
||||
*/
|
||||
static int send_pending_data(TCP_Client_Connection *con)
|
||||
{
|
||||
if (con->last_packet_length == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t left = con->last_packet_length - con->last_packet_sent;
|
||||
int len = send(con->sock, con->last_packet + con->last_packet_sent, left, MSG_NOSIGNAL);
|
||||
|
||||
if (len <= 0)
|
||||
return -1;
|
||||
|
||||
if (len == left) {
|
||||
con->last_packet_length = 0;
|
||||
con->last_packet_sent = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (len > left)
|
||||
return -1;
|
||||
|
||||
con->last_packet_sent += len;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int send_disconnect_packet(TCP_Client_Connection *TCP_connection)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create new TCP connection to ip_port/public_key
|
||||
*/
|
||||
TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, uint8_t *public_key, uint8_t *self_public_key,
|
||||
uint8_t *self_secret_key)
|
||||
{
|
||||
if (networking_at_startup() != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ip_port.ip.family != AF_INET && ip_port.ip.family != AF_INET6)
|
||||
return NULL;
|
||||
|
||||
sock_t sock = socket(ip_port.ip.family, SOCK_STREAM, IPPROTO_TCP);
|
||||
|
||||
if (!sock_valid(sock)) {
|
||||
printf("fail1 %u\n", sock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(set_socket_nonblock(sock) && connect_sock_to(sock, ip_port))) {
|
||||
kill_sock(sock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TCP_Client_Connection *temp = calloc(sizeof(TCP_Client_Connection), 1);
|
||||
|
||||
if (temp == NULL) {
|
||||
kill_sock(sock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
temp->status = TCP_CLIENT_CONNECTING;
|
||||
temp->sock = sock;
|
||||
memcpy(temp->public_key, public_key, crypto_box_PUBLICKEYBYTES);
|
||||
|
||||
if (generate_handshake(temp, self_public_key, self_secret_key) == -1) {
|
||||
kill_sock(sock);
|
||||
free(temp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
temp->kill_at = unix_time() + TCP_CONNECTION_TIMEOUT;
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
static int do_confirmed_TCP(TCP_Client_Connection *TCP_connection)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Run the TCP connection
|
||||
*/
|
||||
void do_TCP_connection(TCP_Client_Connection *TCP_connection)
|
||||
{
|
||||
unix_time_update();
|
||||
|
||||
if (TCP_connection->status == TCP_CLIENT_DISCONNECTED) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (TCP_connection->status == TCP_CLIENT_CONNECTING) {
|
||||
if (send_pending_data(TCP_connection) == 0) {
|
||||
TCP_connection->status = TCP_CLIENT_UNCONFIRMED;
|
||||
}
|
||||
}
|
||||
|
||||
if (TCP_connection->status == TCP_CLIENT_UNCONFIRMED) {
|
||||
uint8_t data[TCP_SERVER_HANDSHAKE_SIZE];
|
||||
int len = read_TCP_packet(TCP_connection->sock, data, sizeof(data));
|
||||
|
||||
if (sizeof(data) == len) {
|
||||
if (handle_handshake(TCP_connection, data) == 0) {
|
||||
TCP_connection->status = TCP_CLIENT_CONFIRMED;
|
||||
} else {
|
||||
TCP_connection->kill_at = 0;
|
||||
TCP_connection->status = TCP_CLIENT_DISCONNECTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (TCP_connection->status == TCP_CLIENT_CONFIRMED) {
|
||||
do_confirmed_TCP(TCP_connection);
|
||||
}
|
||||
|
||||
if (TCP_connection->kill_at <= unix_time()) {
|
||||
TCP_connection->status = TCP_CLIENT_DISCONNECTED;
|
||||
}
|
||||
}
|
||||
|
||||
/* Kill the TCP connection
|
||||
*/
|
||||
void kill_TCP_connection(TCP_Client_Connection *TCP_connection)
|
||||
{
|
||||
kill_sock(TCP_connection->sock);
|
||||
memset(TCP_connection, 0, sizeof(TCP_Client_Connection));
|
||||
free(TCP_connection);
|
||||
}
|
78
toxcore/TCP_client.h
Normal file
78
toxcore/TCP_client.h
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* TCP_client.h -- Implementation of the TCP relay client part of Tox.
|
||||
*
|
||||
* Copyright (C) 2014 Tox project All Rights Reserved.
|
||||
*
|
||||
* This file is part of Tox.
|
||||
*
|
||||
* Tox is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tox is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tox. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef TCP_CLIENT_H
|
||||
#define TCP_CLIENT_H
|
||||
|
||||
#include "net_crypto.h"
|
||||
#include "TCP_server.h"
|
||||
|
||||
#define TCP_CONNECTION_TIMEOUT 10
|
||||
|
||||
enum {
|
||||
TCP_CLIENT_NO_STATUS,
|
||||
TCP_CLIENT_CONNECTING,
|
||||
TCP_CLIENT_UNCONFIRMED,
|
||||
TCP_CLIENT_CONFIRMED,
|
||||
TCP_CLIENT_DISCONNECTED,
|
||||
};
|
||||
typedef struct {
|
||||
uint8_t status;
|
||||
sock_t sock;
|
||||
uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* public key of the server */
|
||||
uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* Nonce of received packets. */
|
||||
uint8_t sent_nonce[crypto_box_NONCEBYTES]; /* Nonce of sent packets. */
|
||||
uint8_t shared_key[crypto_box_BEFORENMBYTES];
|
||||
uint16_t next_packet_length;
|
||||
|
||||
uint8_t temp_secret_key[crypto_box_SECRETKEYBYTES];
|
||||
|
||||
uint8_t last_packet[2 + MAX_PACKET_SIZE];
|
||||
uint16_t last_packet_length;
|
||||
uint16_t last_packet_sent;
|
||||
|
||||
uint64_t kill_at;
|
||||
|
||||
uint64_t last_pinged;
|
||||
uint64_t ping_id;
|
||||
} TCP_Client_Connection;
|
||||
|
||||
/* Create new TCP connection to ip_port/public_key
|
||||
*/
|
||||
TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, uint8_t *public_key, uint8_t *self_public_key,
|
||||
uint8_t *self_secret_key);
|
||||
|
||||
/* Run the TCP connection
|
||||
*/
|
||||
void do_TCP_connection(TCP_Client_Connection *TCP_connection);
|
||||
|
||||
/* Kill the TCP connection
|
||||
*/
|
||||
void kill_TCP_connection(TCP_Client_Connection *TCP_connection);
|
||||
|
||||
int get_TCP_connection_status(TCP_Client_Connection *TCP_connection);
|
||||
|
||||
int read_TCP_connection(TCP_Client_Connection *TCP_connection, uint8_t *data);
|
||||
|
||||
|
||||
#endif
|
|
@ -157,11 +157,14 @@ static int get_TCP_connection_index(TCP_Server *TCP_server, uint8_t *public_key)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* return length on success
|
||||
/* Read the next two bytes in TCP stream then convert them to
|
||||
* length (host byte order).
|
||||
*
|
||||
* return length on success
|
||||
* return 0 if nothing has been read from socket.
|
||||
* return ~0 on failure.
|
||||
*/
|
||||
static uint16_t read_length(sock_t sock)
|
||||
uint16_t read_TCP_length(sock_t sock)
|
||||
{
|
||||
#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
|
||||
unsigned long count = 0;
|
||||
|
@ -173,7 +176,7 @@ static uint16_t read_length(sock_t sock)
|
|||
|
||||
if ((unsigned int)count >= sizeof(uint16_t)) {
|
||||
uint16_t length;
|
||||
int len = recv(sock, (uint8_t *)&length, sizeof(uint16_t), 0);
|
||||
int len = recv(sock, (uint8_t *)&length, sizeof(uint16_t), MSG_NOSIGNAL);
|
||||
|
||||
if (len != sizeof(uint16_t)) {
|
||||
fprintf(stderr, "FAIL recv packet\n");
|
||||
|
@ -192,10 +195,12 @@ static uint16_t read_length(sock_t sock)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* return length on success
|
||||
* return -1 on failure
|
||||
/* Read length bytes from socket.
|
||||
*
|
||||
* return length on success
|
||||
* return -1 on failure/no data in buffer.
|
||||
*/
|
||||
static int read_TCP_packet(sock_t sock, uint8_t *data, uint16_t length)
|
||||
int read_TCP_packet(sock_t sock, uint8_t *data, uint16_t length)
|
||||
{
|
||||
#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
|
||||
unsigned long count = 0;
|
||||
|
@ -206,7 +211,7 @@ static int read_TCP_packet(sock_t sock, uint8_t *data, uint16_t length)
|
|||
#endif
|
||||
|
||||
if (count >= length) {
|
||||
int len = recv(sock, data, length, 0);
|
||||
int len = recv(sock, data, length, MSG_NOSIGNAL);
|
||||
|
||||
if (len != length) {
|
||||
fprintf(stderr, "FAIL recv packet\n");
|
||||
|
@ -226,7 +231,7 @@ static int read_TCP_packet(sock_t sock, uint8_t *data, uint16_t length)
|
|||
static int read_packet_TCP_secure_connection(TCP_Secure_Connection *con, uint8_t *data, uint16_t max_len)
|
||||
{
|
||||
if (con->next_packet_length == 0) {
|
||||
uint16_t len = read_length(con->sock);
|
||||
uint16_t len = read_TCP_length(con->sock);
|
||||
|
||||
if (len == (uint16_t)~0)
|
||||
return -1;
|
||||
|
@ -268,7 +273,7 @@ static int send_pending_data(TCP_Secure_Connection *con)
|
|||
}
|
||||
|
||||
uint16_t left = con->last_packet_length - con->last_packet_sent;
|
||||
int len = send(con->sock, con->last_packet + con->last_packet_sent, left, 0);
|
||||
int len = send(con->sock, con->last_packet + con->last_packet_sent, left, MSG_NOSIGNAL);
|
||||
|
||||
if (len <= 0)
|
||||
return -1;
|
||||
|
@ -310,7 +315,7 @@ static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, uint8_
|
|||
|
||||
increment_nonce(con->sent_nonce);
|
||||
|
||||
len = send(con->sock, packet, sizeof(packet), 0);
|
||||
len = send(con->sock, packet, sizeof(packet), MSG_NOSIGNAL);
|
||||
|
||||
if ((unsigned int)len == sizeof(packet))
|
||||
return 1;
|
||||
|
@ -368,7 +373,7 @@ static int handle_TCP_handshake(TCP_Secure_Connection *con, uint8_t *data, uint1
|
|||
if (len != TCP_HANDSHAKE_PLAIN_SIZE + crypto_box_MACBYTES)
|
||||
return -1;
|
||||
|
||||
if (TCP_SERVER_HANDSHAKE_SIZE != send(con->sock, response, TCP_SERVER_HANDSHAKE_SIZE, 0))
|
||||
if (TCP_SERVER_HANDSHAKE_SIZE != send(con->sock, response, TCP_SERVER_HANDSHAKE_SIZE, MSG_NOSIGNAL))
|
||||
return -1;
|
||||
|
||||
encrypt_precompute(plain, temp_secret_key, con->shared_key);
|
||||
|
@ -740,16 +745,15 @@ TCP_Server *new_TCP_server(uint8_t ipv6_enabled, uint16_t num_sockets, uint16_t
|
|||
if (num_sockets == 0 || ports == NULL)
|
||||
return NULL;
|
||||
|
||||
if (networking_at_startup() != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TCP_Server *temp = calloc(1, sizeof(TCP_Server));
|
||||
|
||||
if (temp == NULL)
|
||||
return NULL;
|
||||
|
||||
if (onion) {
|
||||
temp->onion = onion;
|
||||
set_callback_handle_recv_1(onion, &handle_onion_recv_1, temp);
|
||||
}
|
||||
|
||||
temp->socks_listening = calloc(num_sockets, sizeof(sock_t));
|
||||
|
||||
if (temp->socks_listening == NULL) {
|
||||
|
@ -776,6 +780,16 @@ TCP_Server *new_TCP_server(uint8_t ipv6_enabled, uint16_t num_sockets, uint16_t
|
|||
}
|
||||
}
|
||||
|
||||
if (temp->num_listening_socks == 0) {
|
||||
free(temp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (onion) {
|
||||
temp->onion = onion;
|
||||
set_callback_handle_recv_1(onion, &handle_onion_recv_1, temp);
|
||||
}
|
||||
|
||||
memcpy(temp->public_key, public_key, crypto_box_PUBLICKEYBYTES);
|
||||
memcpy(temp->secret_key, secret_key, crypto_box_SECRETKEYBYTES);
|
||||
return temp;
|
||||
|
|
|
@ -20,9 +20,16 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#ifndef TCP_SERVER_H
|
||||
#define TCP_SERVER_H
|
||||
|
||||
#include "net_crypto.h"
|
||||
#include "onion.h"
|
||||
|
||||
#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
|
||||
#define MSG_NOSIGNAL 0
|
||||
#endif
|
||||
|
||||
#define MAX_INCOMMING_CONNECTIONS 32
|
||||
|
||||
#define TCP_MAX_BACKLOG MAX_INCOMMING_CONNECTIONS
|
||||
|
@ -116,3 +123,21 @@ void do_TCP_server(TCP_Server *TCP_server);
|
|||
/* Kill the TCP server
|
||||
*/
|
||||
void kill_TCP_server(TCP_Server *TCP_server);
|
||||
|
||||
/* Read the next two bytes in TCP stream then convert them to
|
||||
* length (host byte order).
|
||||
*
|
||||
* return length on success
|
||||
* return 0 if nothing has been read from socket.
|
||||
* return ~0 on failure.
|
||||
*/
|
||||
uint16_t read_TCP_length(sock_t sock);
|
||||
|
||||
/* Read length bytes from socket.
|
||||
*
|
||||
* return length on success
|
||||
* return -1 on failure/no data in buffer.
|
||||
*/
|
||||
int read_TCP_packet(sock_t sock, uint8_t *data, uint16_t length);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -500,7 +500,7 @@ int networking_wait_cleanup(Networking_Core *net, uint8_t *data)
|
|||
}
|
||||
|
||||
uint8_t at_startup_ran = 0;
|
||||
static int at_startup(void)
|
||||
int networking_at_startup(void)
|
||||
{
|
||||
if (at_startup_ran != 0)
|
||||
return 0;
|
||||
|
@ -556,7 +556,7 @@ Networking_Core *new_networking(IP ip, uint16_t port)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (at_startup() != 0)
|
||||
if (networking_at_startup() != 0)
|
||||
return NULL;
|
||||
|
||||
Networking_Core *temp = calloc(1, sizeof(Networking_Core));
|
||||
|
@ -946,7 +946,7 @@ int addr_resolve(const char *address, IP *to, IP *extra)
|
|||
hints.ai_family = family;
|
||||
hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses.
|
||||
|
||||
if (at_startup() != 0)
|
||||
if (networking_at_startup() != 0)
|
||||
return 0;
|
||||
|
||||
rc = getaddrinfo(address, NULL, &hints, &server);
|
||||
|
|
|
@ -307,6 +307,13 @@ typedef struct {
|
|||
uint64_t send_fail_eagain;
|
||||
} Networking_Core;
|
||||
|
||||
/* Run this before creating sockets.
|
||||
*
|
||||
* return 0 on success
|
||||
* return -1 on failure
|
||||
*/
|
||||
int networking_at_startup(void);
|
||||
|
||||
/* Check if socket is valid.
|
||||
*
|
||||
* return 1 if valid
|
||||
|
|
Loading…
Reference in New Issue
Block a user