mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
Merge branch 'master' into harden
Conflicts: toxcore/DHT.c
This commit is contained in:
commit
57763f2737
|
@ -54,6 +54,11 @@ make check
|
|||
sudo make install
|
||||
cd ..
|
||||
```
|
||||
If your default prefix is /usr/local and you happen to get an error that says "error while loading shared libraries: libtoxcore.so.0: cannot open shared object file: No such file or directory", then you can try running ```sudo ldconfig```. If that doesn't fix it, run:
|
||||
```
|
||||
sudo echo "/usr/local/lib/" >> /etc/ld.so.conf.d/locallib.conf
|
||||
sudo ldconfig
|
||||
```
|
||||
|
||||
You also need recent [FFmpeg](http://git.videolan.org/?p=ffmpeg.git) libraries:
|
||||
```bash
|
||||
|
|
|
@ -4,15 +4,12 @@ TESTS = messenger_autotest crypto_test network_test
|
|||
|
||||
check_PROGRAMS = messenger_autotest crypto_test network_test
|
||||
|
||||
messenger_autotest_SOURCES = \
|
||||
../auto_tests/messenger_test.c
|
||||
|
||||
messenger_autotest_CFLAGS = \
|
||||
$(LIBSODIUM_CFLAGS) \
|
||||
$(NACL_CFLAGS) \
|
||||
$(CHECK_CFLAGS)
|
||||
|
||||
messenger_autotest_LDADD = \
|
||||
AUTOTEST_CFLAGS = \
|
||||
$(LIBSODIUM_CFLAGS) \
|
||||
$(NACL_CFLAGS) \
|
||||
$(CHECK_CFLAGS)
|
||||
|
||||
AUTOTEST_LDADD = \
|
||||
$(LIBSODIUM_LDFLAGS) \
|
||||
$(NACL_LDFLAGS) \
|
||||
libtoxcore.la \
|
||||
|
@ -20,35 +17,26 @@ messenger_autotest_LDADD = \
|
|||
$(NACL_LIBS) \
|
||||
$(CHECK_LIBS)
|
||||
|
||||
messenger_autotest_SOURCES = ../auto_tests/messenger_test.c
|
||||
|
||||
messenger_autotest_CFLAGS = $(AUTOTEST_CFLAGS)
|
||||
|
||||
messenger_autotest_LDADD = $(AUTOTEST_LDADD)
|
||||
|
||||
|
||||
crypto_test_SOURCES = ../auto_tests/crypto_test.c
|
||||
|
||||
crypto_test_CFLAGS = $(LIBSODIUM_CFLAGS) \
|
||||
$(NACL_CFLAGS) \
|
||||
$(CHECK_CFLAGS)
|
||||
crypto_test_CFLAGS = $(AUTOTEST_CFLAGS)
|
||||
|
||||
crypto_test_LDADD = $(LIBSODIUM_LDFLAGS) \
|
||||
$(NACL_LDFLAGS) \
|
||||
libtoxcore.la \
|
||||
$(LIBSODIUM_LIBS) \
|
||||
$(NACL_LIBS) \
|
||||
$(CHECK_LIBS)
|
||||
crypto_test_LDADD = $(AUTOTEST_LDADD)
|
||||
|
||||
network_test_SOURCES = \
|
||||
../auto_tests/network_test.c
|
||||
|
||||
network_test_CFLAGS = \
|
||||
$(LIBSODIUM_CFLAGS) \
|
||||
$(NACL_CFLAGS) \
|
||||
$(CHECK_CFLAGS)
|
||||
network_test_SOURCES = ../auto_tests/network_test.c
|
||||
|
||||
network_test_CFLAGS = $(AUTOTEST_CFLAGS)
|
||||
|
||||
network_test_LDADD = $(AUTOTEST_LDADD)
|
||||
|
||||
network_test_LDADD = \
|
||||
$(LIBSODIUM_LDFLAGS) \
|
||||
$(NACL_LDFLAGS) \
|
||||
libtoxcore.la \
|
||||
$(LIBSODIUM_LIBS) \
|
||||
$(NACL_LIBS) \
|
||||
$(CHECK_LIBS)
|
||||
|
||||
endif
|
||||
|
||||
|
|
53
auto_tests/skeleton_test.c
Normal file
53
auto_tests/skeleton_test.c
Normal file
|
@ -0,0 +1,53 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <check.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
/*
|
||||
#include "../<stuff to test>"
|
||||
*/
|
||||
|
||||
START_TEST(test_creativetestnamegoeshere)
|
||||
{
|
||||
uint8_t test = 0;
|
||||
ck_assert_msg(test == 0, "test: expected result 0, got %u.", test);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
||||
#define DEFTESTCASE(NAME) \
|
||||
TCase *tc_##NAME = tcase_create(#NAME); \
|
||||
tcase_add_test(tc_##NAME, test_##NAME); \
|
||||
suite_add_tcase(s, tc_##NAME);
|
||||
|
||||
Suite *creativesuitenamegoeshere_suite(void)
|
||||
{
|
||||
Suite *s = suite_create("creativesuitedescritptiongoeshere");
|
||||
|
||||
DEFTESTCASE(/* remove test_ from test function names */ creativetestnamegoeshere);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
srand((unsigned int) time(NULL));
|
||||
|
||||
Suite *creativesuitenamegoeshere = creativesuitenamegoeshere_suite();
|
||||
SRunner *test_runner = srunner_create(creativesuitenamegoeshere);
|
||||
|
||||
int number_failed = 0;
|
||||
srunner_run_all(test_runner, CK_NORMAL);
|
||||
number_failed = srunner_ntests_failed(test_runner);
|
||||
|
||||
srunner_free(test_runner);
|
||||
|
||||
return number_failed;
|
||||
}
|
||||
|
|
@ -45,4 +45,16 @@ to us then it is good.
|
|||
|
||||
Problems with this: People don't always have at least one online friend.
|
||||
|
||||
2. ...
|
||||
2. Pick random nodes (add ourselves some random (fake) friends to increase the
|
||||
pool of available nodes) and make then send requests to other nodes, the
|
||||
response is then relayed back to us and compared to how the node should have
|
||||
behaved. If the node is found to be behaving correctly, it is set as trusted.
|
||||
Only trusted nodes are sent in send node packets, that is unless the exact node
|
||||
being queried for in the getnode packet is present, it will be sent in the
|
||||
sendnode packet even if it is not trusted.
|
||||
|
||||
The hypothesis is that if to be part of the network nodes have to behave
|
||||
correctly it should prevent disruption from nodes that behave incorrectly.
|
||||
|
||||
(This idea is currently being implemented in the harden branch.)
|
||||
...
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
A/V API reference
|
||||
#A/V API reference
|
||||
|
||||
Take toxmsi/phone.c as a reference
|
||||
##Take toxmsi/phone.c as a reference
|
||||
|
||||
Initialization:
|
||||
###Initialization:
|
||||
|
||||
```
|
||||
phone_t* initPhone(uint16_t _listen_port, uint16_t _send_port);
|
||||
```
|
||||
|
||||
function initializes sample phone. _listen_port and _send_port are variables only meant
|
||||
for local testing. You will not have to do anything regarding to that since
|
||||
everything will be started within a mesenger.
|
||||
|
@ -13,17 +16,22 @@ everything will be started within a mesenger.
|
|||
Phone requires one msi session and two rtp sessions ( one for audio and one for
|
||||
video ).
|
||||
|
||||
```
|
||||
msi_session_t* msi_init_session( void* _core_handler, const uint8_t* _user_agent );
|
||||
```
|
||||
|
||||
initializes msi session.
|
||||
Params:
|
||||
|
||||
```
|
||||
void* _core_handler - pointer to an object handling networking,
|
||||
const uint8_t* _user_agent - string describing phone client version.
|
||||
```
|
||||
|
||||
Return value:
|
||||
msi_session_t* - pointer to a newly created msi session handler.
|
||||
|
||||
msi_session_t reference:
|
||||
###msi_session_t reference:
|
||||
|
||||
How to handle msi session:
|
||||
Controling is done via callbacks and action handlers.
|
||||
|
@ -32,6 +40,7 @@ NOT TO PLACE SOMETHING LIKE LOOPS THAT TAKES A LOT OF TIME TO EXECUTE; every cal
|
|||
directly from event loop. You can find examples in phone.c.
|
||||
|
||||
Register callbacks:
|
||||
```
|
||||
void msi_register_callback_call_started ( MCALLBACK );
|
||||
void msi_register_callback_call_canceled ( MCALLBACK );
|
||||
void msi_register_callback_call_rejected ( MCALLBACK );
|
||||
|
@ -44,52 +53,72 @@ void msi_register_callback_recv_ending ( MCALLBACK );
|
|||
void msi_register_callback_recv_error ( MCALLBACK );
|
||||
|
||||
void msi_register_callback_requ_timeout ( MCALLBACK );
|
||||
```
|
||||
|
||||
MCALLBACK is defined as: void (*callback) (void* _arg)
|
||||
msi_session_t* handler is being thrown as _arg so you can use that and _agent_handler to get to your own phone handler
|
||||
msi_session_t* handler is being thrown as \_arg so you can use that and \_agent_handler to get to your own phone handler
|
||||
directly from callback.
|
||||
|
||||
|
||||
Actions:
|
||||
|
||||
```
|
||||
int msi_invite ( msi_session_t* _session, call_type _call_type, uint32_t _timeoutms );
|
||||
```
|
||||
|
||||
Sends call invite. Before calling/sending invite msi_session_t::_friend_id is needed to be set or else
|
||||
it will not work. _call_type is type of the call ( Audio/Video ) and _timeoutms is how long
|
||||
will poll wait until request is terminated.
|
||||
|
||||
```
|
||||
int msi_hangup ( msi_session_t* _session );
|
||||
```
|
||||
Hangs up active call
|
||||
|
||||
```
|
||||
int msi_answer ( msi_session_t* _session, call_type _call_type );
|
||||
```
|
||||
Answer incomming call. _call_type set's callee call type.
|
||||
|
||||
```
|
||||
int msi_cancel ( msi_session_t* _session );
|
||||
```
|
||||
Cancel current request.
|
||||
|
||||
```
|
||||
int msi_reject ( msi_session_t* _session );
|
||||
```
|
||||
Reject incomming call.
|
||||
|
||||
|
||||
###Now for rtp:
|
||||
|
||||
|
||||
Now for rtp:
|
||||
You will need 2 sessions; one for audio one for video.
|
||||
You start them with:
|
||||
|
||||
```
|
||||
rtp_session_t* rtp_init_session ( int _max_users, int _multi_session );
|
||||
```
|
||||
|
||||
Params:
|
||||
```
|
||||
int _max_users - max users. -1 if undefined
|
||||
int _multi_session - any positive number means uses multi session; -1 if not.
|
||||
```
|
||||
|
||||
Return value:
|
||||
```
|
||||
rtp_session_t* - pointer to a newly created rtp session handler.
|
||||
```
|
||||
|
||||
How to handle rtp session:
|
||||
###How to handle rtp session:
|
||||
Take a look at
|
||||
```
|
||||
void* phone_handle_media_transport_poll ( void* _hmtc_args_p ) in phone.c
|
||||
```
|
||||
on example. Basically what you do is just receive a message via:
|
||||
|
||||
```
|
||||
struct rtp_msg_s* rtp_recv_msg ( rtp_session_t* _session );
|
||||
```
|
||||
|
||||
and then you use payload within the rtp_msg_s struct. Don't forget to deallocate it with:
|
||||
void rtp_free_msg ( rtp_session_t* _session, struct rtp_msg_s* _msg );
|
||||
|
@ -98,17 +127,20 @@ Receiving should be thread safe so don't worry about that.
|
|||
When you capture and encode a payload you want to send it ( obviously ).
|
||||
|
||||
first create a new message with:
|
||||
```
|
||||
struct rtp_msg_s* rtp_msg_new ( rtp_session_t* _session, const uint8_t* _data, uint32_t _length );
|
||||
```
|
||||
|
||||
and then send it with:
|
||||
```
|
||||
int rtp_send_msg ( rtp_session_t* _session, struct rtp_msg_s* _msg, void* _core_handler );
|
||||
```
|
||||
|
||||
_core_handler is the same network handler as in msi_session_s struct.
|
||||
|
||||
|
||||
|
||||
A/V initialization:
|
||||
|
||||
##A/V initialization:
|
||||
```
|
||||
int init_receive_audio(codec_state *cs);
|
||||
int init_receive_video(codec_state *cs);
|
||||
Initialises the A/V decoders. On failure it will print the reason and return 0. On success it will return 1.
|
||||
|
@ -122,30 +154,36 @@ int video_encoder_refresh(codec_state *cs, int bps);
|
|||
Reinitialises the video encoder with a new bitrate. ffmpeg does not expose the needed VP8 feature to change the bitrate on the fly, so this serves as a workaround.
|
||||
In the future, VP8 should be used directly and ffmpeg should be dropped from the dependencies.
|
||||
The variable bps is the required bitrate in bits per second.
|
||||
```
|
||||
|
||||
|
||||
|
||||
A/V encoding/decoding:
|
||||
|
||||
###A/V encoding/decoding:
|
||||
```
|
||||
void *encode_video_thread(void *arg);
|
||||
```
|
||||
Spawns the video encoding thread. The argument should hold a pointer to a codec_state.
|
||||
This function should only be called if video encoding is supported (when init_send_video returns 1).
|
||||
Each video frame gets encoded into a packet, which is sent via RTP. Every 60 frames a new bidirectional interframe is encoded.
|
||||
|
||||
```
|
||||
void *encode_audio_thread(void *arg);
|
||||
```
|
||||
Spawns the audio encoding thread. The argument should hold a pointer to a codec_state.
|
||||
This function should only be called if audio encoding is supported (when init_send_audio returns 1).
|
||||
Audio frames are read from the selected audio capture device during intitialisation. This audio capturing can be rerouted to a different device on the fly.
|
||||
Each audio frame is encoded into a packet, and sent via RTP. All audio frames have the same amount of samples, which is defined in AV_codec.h.
|
||||
|
||||
```
|
||||
int video_decoder_refresh(codec_state *cs, int width, int height);
|
||||
```
|
||||
Sets the SDL window dimensions and creates a pixel buffer with the requested size. It also creates a scaling context, which will be used to convert the input image format to YUV420P.
|
||||
|
||||
```
|
||||
void *decode_video_thread(void *arg);
|
||||
```
|
||||
Spawns a video decoding thread. The argument should hold a pointer to a codec_state. The codec_state is assumed to contain a successfully initialised video decoder.
|
||||
This function reads video packets and feeds them to the video decoder. If the video frame's resolution has changed, video_decoder_refresh() is called. Afterwards, the frame is displayed on the SDL window.
|
||||
|
||||
```
|
||||
void *decode_audio_thread(void *arg);
|
||||
```
|
||||
Spawns an audio decoding thread. The argument should hold a pointer to a codec_state. The codec_state is assumed to contain a successfully initialised audio decoder.
|
||||
All received audio packets are pushed into a jitter buffer and are reordered. If there is a missing packet, or a packet has arrived too late, it is treated as a lost packet and the audio decoder is informed of the packet loss. The audio decoder will then try to reconstruct the lost packet, based on information from previous packets.
|
||||
Audio is played on the default OpenAL output device.
|
||||
|
@ -153,4 +191,4 @@ Audio is played on the default OpenAL output device.
|
|||
|
||||
If you have any more qustions/bug reports/feature request contact the following users on the irc channel #tox-dev on irc.freenode.net:
|
||||
For RTP and MSI: mannol
|
||||
For audio and video: Martijnvdc
|
||||
For audio and video: Martijnvdc
|
||||
|
|
131
toxcore/DHT.c
131
toxcore/DHT.c
|
@ -814,110 +814,109 @@ static uint8_t sent_getnode_to_node(DHT *dht, uint8_t *client_id, IP_Port node_i
|
|||
/* Function is needed in following functions. */
|
||||
static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, Node_format *list, uint16_t num_nodes);
|
||||
|
||||
static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length)
|
||||
static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet, uint32_t length,
|
||||
size_t node_format_size, uint8_t *plain, uint16_t plain_length, uint32_t *num_nodes_out, Node_format *sendback_node)
|
||||
{
|
||||
DHT *dht = object;
|
||||
uint32_t cid_size = 1 + CLIENT_ID_SIZE;
|
||||
cid_size += crypto_box_NONCEBYTES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES;
|
||||
|
||||
size_t Node4_format_size = sizeof(Node4_format);
|
||||
|
||||
if (length > (cid_size + Node4_format_size * MAX_SENT_NODES) ||
|
||||
((length - cid_size) % Node4_format_size) != 0 ||
|
||||
(length < cid_size + Node4_format_size))
|
||||
if (plain_length != MAX_SENT_NODES * node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH)
|
||||
return 1;
|
||||
|
||||
uint32_t num_nodes = (length - cid_size) / Node4_format_size;
|
||||
uint8_t plain[Node4_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH];
|
||||
DHT *dht = object;
|
||||
uint32_t cid_size = 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES;
|
||||
|
||||
if (length <= cid_size) /* too short */
|
||||
return 1;
|
||||
|
||||
uint32_t data_size = length - cid_size;
|
||||
|
||||
if ((data_size % node_format_size) != 0) /* invalid length */
|
||||
return 1;
|
||||
|
||||
uint32_t num_nodes = data_size / node_format_size;
|
||||
|
||||
if (num_nodes > MAX_SENT_NODES) /* too long */
|
||||
return 1;
|
||||
|
||||
int len = decrypt_data(
|
||||
packet + 1,
|
||||
dht->c->self_secret_key,
|
||||
packet + 1 + CLIENT_ID_SIZE,
|
||||
packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
|
||||
num_nodes * Node4_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES, plain );
|
||||
num_nodes * node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES,
|
||||
plain);
|
||||
|
||||
if ((unsigned int)len != num_nodes * Node4_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH)
|
||||
if ((unsigned int)len != num_nodes * node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH)
|
||||
return 1;
|
||||
|
||||
if (!sent_getnode_to_node(dht, packet + 1, source, plain + num_nodes * node_format_size, sendback_node))
|
||||
return 1;
|
||||
|
||||
/* store the address the *request* was sent to */
|
||||
addto_lists(dht, source, packet + 1);
|
||||
|
||||
*num_nodes_out = num_nodes;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length)
|
||||
{
|
||||
DHT *dht = object;
|
||||
size_t node4_format_size = sizeof(Node4_format);
|
||||
uint8_t plain[node4_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH];
|
||||
uint32_t num_nodes;
|
||||
|
||||
Node_format sendback_node;
|
||||
|
||||
if (!sent_getnode_to_node(dht, packet + 1, source, plain + num_nodes * Node4_format_size, &sendback_node))
|
||||
if (handle_sendnodes_core(object, source, packet, length, node4_format_size, plain, sizeof(plain), &num_nodes,
|
||||
&sendback_node))
|
||||
return 1;
|
||||
|
||||
Node4_format *nodes4_list = (Node4_format *)(plain);
|
||||
Node_format nodes_list[MAX_SENT_NODES];
|
||||
uint32_t i, num_nodes_ok = 0;
|
||||
uint32_t i;
|
||||
|
||||
IP_Port ipp;
|
||||
ipp.ip.family = AF_INET;
|
||||
|
||||
Node_format nodes_list[MAX_SENT_NODES];
|
||||
|
||||
/* blow up from Node4 (IPv4) wire format to Node (IPv4/IPv6) structure */
|
||||
for (i = 0; i < num_nodes; i++)
|
||||
if ((nodes4_list[i].ip_port.ip.uint32 != 0) && (nodes4_list[i].ip_port.ip.uint32 != (uint32_t)~0)) {
|
||||
memcpy(nodes_list[num_nodes_ok].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE);
|
||||
nodes_list[num_nodes_ok].ip_port.ip.family = AF_INET;
|
||||
nodes_list[num_nodes_ok].ip_port.ip.ip4.uint32 = nodes4_list[i].ip_port.ip.uint32;
|
||||
nodes_list[num_nodes_ok].ip_port.port = nodes4_list[i].ip_port.port;
|
||||
ipp.ip.ip4.uint32 = nodes4_list[i].ip_port.ip.uint32;
|
||||
ipp.port = nodes4_list[i].ip_port.port;
|
||||
|
||||
num_nodes_ok++;
|
||||
send_ping_request(dht->ping, ipp, nodes4_list[i].client_id);
|
||||
returnedip_ports(dht, ipp, nodes4_list[i].client_id, packet + 1);
|
||||
|
||||
memcpy(nodes_list[i].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE);
|
||||
ipport_copy(&nodes_list[i].ip_port, &ipp);
|
||||
}
|
||||
|
||||
if (num_nodes_ok < num_nodes) {
|
||||
/* shouldn't happen */
|
||||
num_nodes = num_nodes_ok;
|
||||
}
|
||||
|
||||
send_hardening_getnode_res(dht, &sendback_node, nodes_list, num_nodes);
|
||||
addto_lists(dht, source, packet + 1);
|
||||
|
||||
for (i = 0; i < num_nodes; ++i) {
|
||||
send_ping_request(dht->ping, nodes_list[i].ip_port, nodes_list[i].client_id);
|
||||
returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet, uint32_t length)
|
||||
{
|
||||
DHT *dht = object;
|
||||
uint32_t cid_size = 1 + CLIENT_ID_SIZE;
|
||||
cid_size += crypto_box_NONCEBYTES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES;
|
||||
|
||||
size_t Node_format_size = sizeof(Node_format);
|
||||
|
||||
if (length > (cid_size + Node_format_size * MAX_SENT_NODES) ||
|
||||
((length - cid_size) % Node_format_size) != 0 ||
|
||||
(length < cid_size + Node_format_size))
|
||||
return 1;
|
||||
|
||||
uint32_t num_nodes = (length - cid_size) / Node_format_size;
|
||||
uint8_t plain[Node_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH];
|
||||
|
||||
int len = decrypt_data(
|
||||
packet + 1,
|
||||
dht->c->self_secret_key,
|
||||
packet + 1 + CLIENT_ID_SIZE,
|
||||
packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
|
||||
num_nodes * Node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES, plain );
|
||||
|
||||
if ((unsigned int)len != num_nodes * Node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH)
|
||||
return 1;
|
||||
size_t node_format_size = sizeof(Node_format);
|
||||
uint8_t plain[node_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH];
|
||||
uint32_t num_nodes;
|
||||
|
||||
Node_format sendback_node;
|
||||
|
||||
if (!sent_getnode_to_node(dht, packet + 1, source, plain + num_nodes * Node_format_size, &sendback_node))
|
||||
if (handle_sendnodes_core(object, source, packet, length, node_format_size, plain, sizeof(plain), &num_nodes,
|
||||
&sendback_node))
|
||||
return 1;
|
||||
|
||||
Node_format *nodes_list = (Node_format *)(plain);
|
||||
uint32_t i;
|
||||
Node_format nodes_list[MAX_SENT_NODES];
|
||||
memcpy(nodes_list, plain, num_nodes * sizeof(Node_format));
|
||||
|
||||
send_hardening_getnode_res(dht, &sendback_node, nodes_list, num_nodes);
|
||||
addto_lists(dht, source, packet + 1);
|
||||
|
||||
for (i = 0; i < num_nodes; ++i) {
|
||||
send_ping_request(dht->ping, nodes_list[i].ip_port, nodes_list[i].client_id);
|
||||
returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1);
|
||||
}
|
||||
for (i = 0; i < num_nodes; i++)
|
||||
if (ipport_isset(&nodes_list[i].ip_port)) {
|
||||
send_ping_request(dht->ping, nodes_list[i].ip_port, nodes_list[i].client_id);
|
||||
returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -833,8 +833,7 @@ static int handle_SYNC2(Lossless_UDP *ludp, int connection_id, uint8_t counter,
|
|||
{
|
||||
Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
|
||||
|
||||
if (recv_packetnum == connection->orecv_packetnum) {
|
||||
/* && sent_packetnum == connection->osent_packetnum) */
|
||||
if (recv_packetnum == connection->orecv_packetnum && sent_packetnum == connection->osent_packetnum) {
|
||||
connection->status = LUDP_ESTABLISHED;
|
||||
connection->recv_counter = counter;
|
||||
++connection->send_counter;
|
||||
|
@ -862,8 +861,8 @@ static void adjust_datasendspeed(Connection *connection, uint32_t req_packets)
|
|||
return;
|
||||
}
|
||||
|
||||
if (req_packets <= (connection->data_rate / connection->SYNC_rate) / 5 || req_packets <= 10) {
|
||||
connection->data_rate += (connection->data_rate / 8) + 1;
|
||||
if (req_packets <= (connection->data_rate / connection->SYNC_rate) / 4 || req_packets <= 10) {
|
||||
connection->data_rate += (connection->data_rate / 4) + 1;
|
||||
|
||||
if (connection->data_rate > connection->sendbuffer_length * connection->SYNC_rate)
|
||||
connection->data_rate = connection->sendbuffer_length * connection->SYNC_rate;
|
||||
|
|
|
@ -868,13 +868,36 @@ int m_group_peername(Messenger *m, int groupnumber, int peernumber, uint8_t *nam
|
|||
|
||||
return group_peername(m->chats[groupnumber], peernumber, name);
|
||||
}
|
||||
|
||||
/* Store the fact that we invited a specific friend.
|
||||
*/
|
||||
static void group_store_friendinvite(Messenger *m, int friendnumber, int groupnumber)
|
||||
{
|
||||
/* Add 1 to the groupchat number because 0 (default value in invited_groups) is a valid groupchat number */
|
||||
m->friendlist[friendnumber].invited_groups[m->friendlist[friendnumber].invited_groups_num % MAX_INVITED_GROUPS] =
|
||||
groupnumber + 1;
|
||||
++m->friendlist[friendnumber].invited_groups_num;
|
||||
}
|
||||
|
||||
/* return 1 if that friend was invited to the group
|
||||
* return 0 if the friend was not or error.
|
||||
*/
|
||||
static uint8_t group_invited(Messenger *m, int friendnumber, int groupnumber)
|
||||
{
|
||||
//TODO: this function;
|
||||
return 1;
|
||||
|
||||
uint32_t i;
|
||||
uint16_t num = MAX_INVITED_GROUPS;
|
||||
|
||||
if (MAX_INVITED_GROUPS > m->friendlist[friendnumber].invited_groups_num)
|
||||
num = m->friendlist[friendnumber].invited_groups_num;
|
||||
|
||||
for (i = 0; i < num; ++i) {
|
||||
if (m->friendlist[friendnumber].invited_groups[i] == groupnumber + 1) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* invite friendnumber to groupnumber
|
||||
|
@ -892,7 +915,8 @@ int invite_friend(Messenger *m, int friendnumber, int groupnumber)
|
|||
if (m->friendlist[friendnumber].status == NOFRIEND || m->chats[groupnumber] == NULL)
|
||||
return -1;
|
||||
|
||||
//TODO: store invited friends.
|
||||
group_store_friendinvite(m, friendnumber, groupnumber);
|
||||
|
||||
if (write_cryptpacket_id(m, friendnumber, PACKET_ID_INVITE_GROUPCHAT, m->chats[groupnumber]->self_public_key,
|
||||
crypto_box_PUBLICKEYBYTES) == 0)
|
||||
return -1;
|
||||
|
@ -1782,10 +1806,10 @@ void do_messenger(Messenger *m)
|
|||
|
||||
#ifdef LOGGING
|
||||
|
||||
if (now() > lastdump + DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS) {
|
||||
if (unix_time() > lastdump + DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS) {
|
||||
loglog(" = = = = = = = = \n");
|
||||
|
||||
lastdump = now();
|
||||
lastdump = unix_time();
|
||||
uint32_t client, last_pinged;
|
||||
|
||||
for (client = 0; client < LCLIENT_LIST; client++) {
|
||||
|
|
|
@ -52,6 +52,9 @@
|
|||
#define PACKET_ID_JOIN_GROUPCHAT 145
|
||||
#define PACKET_ID_ACCEPT_GROUPCHAT 146
|
||||
|
||||
/* Max number of groups we can invite someone at the same time to. */
|
||||
#define MAX_INVITED_GROUPS 64
|
||||
|
||||
/* Status definitions. */
|
||||
enum {
|
||||
NOFRIEND,
|
||||
|
@ -148,6 +151,8 @@ typedef struct {
|
|||
uint64_t ping_lastsent;
|
||||
struct File_Transfers file_sending[MAX_CONCURRENT_FILE_PIPES];
|
||||
struct File_Transfers file_receiving[MAX_CONCURRENT_FILE_PIPES];
|
||||
int invited_groups[MAX_INVITED_GROUPS];
|
||||
uint16_t invited_groups_num;
|
||||
} Friend;
|
||||
|
||||
typedef struct Messenger {
|
||||
|
|
|
@ -205,13 +205,15 @@ static int addpeer(Group_Chat *chat, uint8_t *client_id)
|
|||
|
||||
Group_Peer *temp;
|
||||
temp = realloc(chat->group, sizeof(Group_Peer) * (chat->numpeers + 1));
|
||||
memset(&(temp[chat->numpeers]), 0, sizeof(Group_Peer));
|
||||
|
||||
if (temp == NULL)
|
||||
return -1;
|
||||
|
||||
memset(&(temp[chat->numpeers]), 0, sizeof(Group_Peer));
|
||||
chat->group = temp;
|
||||
id_copy(chat->group[chat->numpeers].client_id, client_id);
|
||||
chat->group[chat->numpeers].last_recv = unix_time();
|
||||
chat->group[chat->numpeers].last_recv_msgping = unix_time();
|
||||
++chat->numpeers;
|
||||
return (chat->numpeers - 1);
|
||||
}
|
||||
|
@ -287,7 +289,8 @@ static int send_getnodes(Group_Chat *chat, IP_Port ip_port, int peernum)
|
|||
chat->group[peernum].last_pinged = unix_time();
|
||||
chat->group[peernum].pingid = contents.pingid;
|
||||
|
||||
return send_groupchatpacket(chat, ip_port, chat->group[peernum].client_id, (uint8_t *)&contents, sizeof(contents), 48);
|
||||
return send_groupchatpacket(chat, ip_port, chat->group[peernum].client_id, (uint8_t *)&contents, sizeof(contents),
|
||||
CRYPTO_PACKET_GROUP_CHAT_GET_NODES);
|
||||
}
|
||||
|
||||
static int send_sendnodes(Group_Chat *chat, IP_Port ip_port, int peernum, uint64_t pingid)
|
||||
|
@ -308,7 +311,7 @@ static int send_sendnodes(Group_Chat *chat, IP_Port ip_port, int peernum, uint64
|
|||
}
|
||||
|
||||
return send_groupchatpacket(chat, ip_port, chat->group[peernum].client_id, (uint8_t *)&contents,
|
||||
sizeof(contents.pingid) + sizeof(groupchat_nodes) * j, 49);
|
||||
sizeof(contents.pingid) + sizeof(groupchat_nodes) * j, CRYPTO_PACKET_GROUP_CHAT_SEND_NODES);
|
||||
}
|
||||
|
||||
static int handle_getnodes(Group_Chat *chat, IP_Port source, int peernum, uint8_t *data, uint32_t len)
|
||||
|
@ -392,9 +395,9 @@ static int handle_data(Group_Chat *chat, uint8_t *data, uint32_t len)
|
|||
|
||||
if (chat->group[peernum].last_recv == temp_time)
|
||||
return 1;
|
||||
|
||||
chat->group[peernum].last_recv = temp_time;
|
||||
*/
|
||||
chat->group[peernum].last_recv = unix_time();
|
||||
|
||||
uint32_t message_num;
|
||||
memcpy(&message_num, data + crypto_box_PUBLICKEYBYTES, sizeof(uint32_t));
|
||||
message_num = ntohl(message_num);
|
||||
|
@ -412,21 +415,21 @@ static int handle_data(Group_Chat *chat, uint8_t *data, uint32_t len)
|
|||
uint16_t contents_len = len - GROUP_DATA_MIN_SIZE;
|
||||
|
||||
switch (data[crypto_box_PUBLICKEYBYTES + sizeof(message_num)]) {
|
||||
case 0: /* If message is ping */
|
||||
case GROUP_CHAT_PING: /* If message is ping */
|
||||
if (contents_len != 0)
|
||||
return 1;
|
||||
|
||||
chat->group[peernum].last_recv_msgping = unix_time();
|
||||
break;
|
||||
|
||||
case 16: /* If message is new peer */
|
||||
case GROUP_CHAT_NEW_PEER: /* If message is new peer */
|
||||
if (contents_len != crypto_box_PUBLICKEYBYTES)
|
||||
return 1;
|
||||
|
||||
addpeer(chat, contents);
|
||||
break;
|
||||
|
||||
case 64: /* If message is chat message */
|
||||
case GROUP_CHAT_CHAT_MESSAGE: /* If message is chat message */
|
||||
if (chat->group_message != NULL)
|
||||
(*chat->group_message)(chat, peernum, contents, contents_len, chat->group_message_userdata);
|
||||
|
||||
|
@ -439,7 +442,7 @@ static int handle_data(Group_Chat *chat, uint8_t *data, uint32_t len)
|
|||
}
|
||||
|
||||
if (handled == 1) {
|
||||
sendto_allpeers(chat, data, len, 50);
|
||||
sendto_allpeers(chat, data, len, CRYPTO_PACKET_GROUP_CHAT_BROADCAST);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -461,9 +464,12 @@ static uint8_t send_data(Group_Chat *chat, uint8_t *data, uint32_t len, uint8_t
|
|||
//TODO
|
||||
id_copy(packet, chat->self_public_key);
|
||||
memcpy(packet + crypto_box_PUBLICKEYBYTES, &message_num, sizeof(message_num));
|
||||
memcpy(packet + GROUP_DATA_MIN_SIZE, data, len);
|
||||
|
||||
if (len != 0)
|
||||
memcpy(packet + GROUP_DATA_MIN_SIZE, data, len);
|
||||
|
||||
packet[crypto_box_PUBLICKEYBYTES + sizeof(message_num)] = message_id;
|
||||
return sendto_allpeers(chat, packet, len + GROUP_DATA_MIN_SIZE, 50);
|
||||
return sendto_allpeers(chat, packet, len + GROUP_DATA_MIN_SIZE, CRYPTO_PACKET_GROUP_CHAT_BROADCAST);
|
||||
}
|
||||
/*
|
||||
* Handle get nodes group packet.
|
||||
|
@ -494,13 +500,13 @@ int handle_groupchatpacket(Group_Chat *chat, IP_Port source, uint8_t *packet, ui
|
|||
return 1;
|
||||
|
||||
switch (number) {
|
||||
case 48:
|
||||
case CRYPTO_PACKET_GROUP_CHAT_GET_NODES:
|
||||
return handle_getnodes(chat, source, peernum, data, len);
|
||||
|
||||
case 49:
|
||||
case CRYPTO_PACKET_GROUP_CHAT_SEND_NODES:
|
||||
return handle_sendnodes(chat, source, peernum, data, len);
|
||||
|
||||
case 50:
|
||||
case CRYPTO_PACKET_GROUP_CHAT_BROADCAST:
|
||||
return handle_data(chat, data, len);
|
||||
|
||||
default:
|
||||
|
@ -512,13 +518,13 @@ int handle_groupchatpacket(Group_Chat *chat, IP_Port source, uint8_t *packet, ui
|
|||
|
||||
uint32_t group_sendmessage(Group_Chat *chat, uint8_t *message, uint32_t length)
|
||||
{
|
||||
return send_data(chat, message, length, 64); //TODO: better return values?
|
||||
return send_data(chat, message, length, GROUP_CHAT_CHAT_MESSAGE); //TODO: better return values?
|
||||
}
|
||||
|
||||
uint32_t group_newpeer(Group_Chat *chat, uint8_t *client_id)
|
||||
{
|
||||
addpeer(chat, client_id);
|
||||
return send_data(chat, client_id, crypto_box_PUBLICKEYBYTES, 16); //TODO: better return values?
|
||||
return send_data(chat, client_id, crypto_box_PUBLICKEYBYTES, GROUP_CHAT_NEW_PEER); //TODO: better return values?
|
||||
}
|
||||
|
||||
void callback_groupmessage(Group_Chat *chat, void (*function)(Group_Chat *chat, int, uint8_t *, uint16_t, void *),
|
||||
|
@ -561,10 +567,35 @@ static void ping_close(Group_Chat *chat)
|
|||
}
|
||||
}
|
||||
|
||||
/* Interval in seconds to send ping messages */
|
||||
#define GROUP_PING_INTERVAL 30
|
||||
|
||||
static void ping_group(Group_Chat *chat)
|
||||
{
|
||||
if (is_timeout(chat->last_sent_ping, GROUP_PING_INTERVAL)) {
|
||||
if (send_data(chat, 0, 0, GROUP_CHAT_PING) != 0) /* Ping */
|
||||
chat->last_sent_ping = unix_time();
|
||||
}
|
||||
}
|
||||
|
||||
static void del_dead_peers(Group_Chat *chat)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < chat->numpeers; ++i) {
|
||||
if (is_timeout(chat->group[i].last_recv_msgping, GROUP_PING_INTERVAL * 2)) {
|
||||
delpeer(chat, chat->group[i].client_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void do_groupchat(Group_Chat *chat)
|
||||
{
|
||||
unix_time_update();
|
||||
ping_close(chat);
|
||||
ping_group(chat);
|
||||
/* TODO: Maybe run this less? */
|
||||
del_dead_peers(chat);
|
||||
}
|
||||
|
||||
void kill_groupchat(Group_Chat *chat)
|
||||
|
|
|
@ -63,9 +63,14 @@ typedef struct Group_Chat {
|
|||
uint32_t message_number;
|
||||
void (*group_message)(struct Group_Chat *m, int, uint8_t *, uint16_t, void *);
|
||||
void *group_message_userdata;
|
||||
uint64_t last_sent_ping;
|
||||
|
||||
} Group_Chat;
|
||||
|
||||
#define GROUP_CHAT_PING 0
|
||||
#define GROUP_CHAT_NEW_PEER 16
|
||||
#define GROUP_CHAT_CHAT_MESSAGE 64
|
||||
|
||||
/* Copy the name of peernum to name.
|
||||
* name must be at least MAX_NICK_BYTES long.
|
||||
*
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
#define CRYPTO_PACKET_FRIEND_REQ 32 /* Friend request crypto packet ID. */
|
||||
#define CRYPTO_PACKET_HARDENING 48 /* Hardening crypto packet ID. */
|
||||
#define CRYPTO_PACKET_NAT_PING 254 /* NAT ping crypto packet ID. */
|
||||
#define CRYPTO_PACKET_GROUP_CHAT_GET_NODES 48 /* Group chat get Nodes packet */
|
||||
#define CRYPTO_PACKET_GROUP_CHAT_SEND_NODES 49 /* Group chat send Nodes packet */
|
||||
#define CRYPTO_PACKET_GROUP_CHAT_BROADCAST 50 /* Group chat broadcast packet */
|
||||
#define CRYPTO_HANDSHAKE_TIMEOUT (CONNECTION_TIMEOUT * 2)
|
||||
|
||||
#define CRYPTO_CONN_NO_CONNECTION 0
|
||||
|
|
|
@ -114,28 +114,35 @@ static uint64_t add_ping(PING *ping, IP_Port ipp) // O(n)
|
|||
return ping->pings[p].id;
|
||||
}
|
||||
|
||||
static bool is_pinging(PING *ping, IP_Port ipp, uint64_t ping_id) // O(n) TODO: Replace this with something else.
|
||||
/* checks if ip/port or ping_id are already in the list to ping
|
||||
* if both are set, both must match, otherwise the set must match
|
||||
*
|
||||
* returns 0 if neither is set or no match was found
|
||||
* returns the (index + 1) of the match if one was found
|
||||
*/
|
||||
static int is_pinging(PING *ping, IP_Port ipp, uint64_t ping_id)
|
||||
{
|
||||
// O(n) TODO: Replace this with something else.
|
||||
|
||||
/* shouldn't that be an OR ? */
|
||||
if (!ip_isset(&ipp.ip) && ping_id == 0)
|
||||
return false;
|
||||
/* at least one MUST be set */
|
||||
uint8_t ip_valid = ip_isset(&ipp.ip);
|
||||
|
||||
size_t i, id;
|
||||
if (!ip_valid && !ping_id)
|
||||
return 0;
|
||||
|
||||
size_t i;
|
||||
|
||||
remove_timeouts(ping);
|
||||
|
||||
for (i = 0; i < ping->num_pings; i++) {
|
||||
id = (ping->pos_pings + i) % PING_NUM_MAX;
|
||||
size_t id = (ping->pos_pings + i) % PING_NUM_MAX;
|
||||
|
||||
/* ping_id = 0 means match any id. */
|
||||
if ((!ip_isset(&ipp.ip) || ipport_equal(&ping->pings[id].ip_port, &ipp)) &&
|
||||
(ping->pings[id].id == ping_id || ping_id == 0)) {
|
||||
return true;
|
||||
}
|
||||
if (!ping_id || (ping->pings[id].id == ping_id))
|
||||
if (!ip_valid || ipport_equal(&ping->pings[id].ip_port, &ipp))
|
||||
return id + 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define DHT_PING_SIZE (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(uint64_t) + crypto_box_MACBYTES)
|
||||
|
@ -252,11 +259,13 @@ static int handle_ping_response(void *_dht, IP_Port source, uint8_t *packet, uin
|
|||
return 1;
|
||||
|
||||
/* Make sure ping_id is correct. */
|
||||
if (!is_pinging(ping, source, ping_id))
|
||||
int ping_index = is_pinging(ping, source, ping_id);
|
||||
|
||||
if (!ping_index)
|
||||
return 1;
|
||||
|
||||
// Associate source ip with client_id
|
||||
addto_lists(dht, source, packet + 1);
|
||||
/* Associate client_id with the ip the request was sent to */
|
||||
addto_lists(dht, ping->pings[ping_index - 1].ip_port, packet + 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -521,7 +521,7 @@ uint64_t tox_file_dataremaining(Tox *tox, int friendnumber, uint8_t filenumber,
|
|||
void tox_bootstrap_from_ip(Tox *tox, tox_IP_Port ip_port, uint8_t *public_key);
|
||||
|
||||
/* Resolves address into an IP address. If successful, sends a "get nodes"
|
||||
* request to the given node with ip, port (in network byte order, HINT: use htons())
|
||||
* request to the given node with ip, port (in network byte order, HINT: use htons())
|
||||
* and public_key to setup connections
|
||||
*
|
||||
* address can be a hostname or an IP address (IPv4 or IPv6).
|
||||
|
|
|
@ -139,8 +139,10 @@ void loginit(uint16_t port)
|
|||
if (logfile)
|
||||
fclose(logfile);
|
||||
|
||||
if (!starttime)
|
||||
starttime = now();
|
||||
if (!starttime) {
|
||||
unix_time_update();
|
||||
starttime = unix_time();
|
||||
}
|
||||
|
||||
struct tm *tm = localtime(&starttime);
|
||||
|
||||
|
@ -164,7 +166,7 @@ void loginit(uint16_t port)
|
|||
void loglog(char *text)
|
||||
{
|
||||
if (logfile) {
|
||||
fprintf(logfile, "%4u %s", (uint32_t)(now() - starttime), text);
|
||||
fprintf(logfile, "%4u %s", (uint32_t)(unix_time() - starttime), text);
|
||||
fflush(logfile);
|
||||
|
||||
return;
|
||||
|
@ -175,7 +177,9 @@ void loglog(char *text)
|
|||
size_t len = strlen(text);
|
||||
|
||||
if (!starttime) {
|
||||
starttime = now();
|
||||
unix_time_update();
|
||||
starttime = unix_time();
|
||||
|
||||
logbufferprelen = 1024 + len - (len % 1024);
|
||||
logbufferpredata = malloc(logbufferprelen);
|
||||
logbufferprehead = logbufferpredata;
|
||||
|
@ -193,7 +197,7 @@ void loglog(char *text)
|
|||
logbufferprelen = lennew;
|
||||
}
|
||||
|
||||
int written = sprintf(logbufferprehead, "%4u %s", (uint32_t)(now() - starttime), text);
|
||||
int written = sprintf(logbufferprehead, "%4u %s", (uint32_t)(unix_time() - starttime), text);
|
||||
logbufferprehead += written;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user