summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--INSTALL.md5
-rw-r--r--auto_tests/Makefile.inc50
-rw-r--r--auto_tests/skeleton_test.c53
-rw-r--r--docs/Hardening.txt14
-rw-r--r--docs/av_api.md78
-rw-r--r--toxcore/DHT.c123
-rw-r--r--toxcore/Lossless_UDP.c7
-rw-r--r--toxcore/Messenger.c34
-rw-r--r--toxcore/Messenger.h5
-rw-r--r--toxcore/group_chats.c63
-rw-r--r--toxcore/group_chats.h5
-rw-r--r--toxcore/net_crypto.h3
-rw-r--r--toxcore/ping.c39
-rw-r--r--toxcore/tox.h2
-rw-r--r--toxcore/util.c14
15 files changed, 335 insertions, 160 deletions
diff --git a/INSTALL.md b/INSTALL.md
index b8265951..9eea323a 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -54,6 +54,11 @@ make check
54sudo make install 54sudo make install
55cd .. 55cd ..
56``` 56```
57If 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:
58```
59sudo echo "/usr/local/lib/" >> /etc/ld.so.conf.d/locallib.conf
60sudo ldconfig
61```
57 62
58You also need recent [FFmpeg](http://git.videolan.org/?p=ffmpeg.git) libraries: 63You also need recent [FFmpeg](http://git.videolan.org/?p=ffmpeg.git) libraries:
59```bash 64```bash
diff --git a/auto_tests/Makefile.inc b/auto_tests/Makefile.inc
index 6c59eebb..9c06bc78 100644
--- a/auto_tests/Makefile.inc
+++ b/auto_tests/Makefile.inc
@@ -4,15 +4,12 @@ TESTS = messenger_autotest crypto_test network_test
4 4
5check_PROGRAMS = messenger_autotest crypto_test network_test 5check_PROGRAMS = messenger_autotest crypto_test network_test
6 6
7messenger_autotest_SOURCES = \ 7AUTOTEST_CFLAGS = \
8 ../auto_tests/messenger_test.c 8 $(LIBSODIUM_CFLAGS) \
9 9 $(NACL_CFLAGS) \
10messenger_autotest_CFLAGS = \ 10 $(CHECK_CFLAGS)
11 $(LIBSODIUM_CFLAGS) \ 11
12 $(NACL_CFLAGS) \ 12AUTOTEST_LDADD = \
13 $(CHECK_CFLAGS)
14
15messenger_autotest_LDADD = \
16 $(LIBSODIUM_LDFLAGS) \ 13 $(LIBSODIUM_LDFLAGS) \
17 $(NACL_LDFLAGS) \ 14 $(NACL_LDFLAGS) \
18 libtoxcore.la \ 15 libtoxcore.la \
@@ -20,35 +17,26 @@ messenger_autotest_LDADD = \
20 $(NACL_LIBS) \ 17 $(NACL_LIBS) \
21 $(CHECK_LIBS) 18 $(CHECK_LIBS)
22 19
20messenger_autotest_SOURCES = ../auto_tests/messenger_test.c
21
22messenger_autotest_CFLAGS = $(AUTOTEST_CFLAGS)
23
24messenger_autotest_LDADD = $(AUTOTEST_LDADD)
25
23 26
24crypto_test_SOURCES = ../auto_tests/crypto_test.c 27crypto_test_SOURCES = ../auto_tests/crypto_test.c
25 28
26crypto_test_CFLAGS = $(LIBSODIUM_CFLAGS) \ 29crypto_test_CFLAGS = $(AUTOTEST_CFLAGS)
27 $(NACL_CFLAGS) \
28 $(CHECK_CFLAGS)
29 30
30crypto_test_LDADD = $(LIBSODIUM_LDFLAGS) \ 31crypto_test_LDADD = $(AUTOTEST_LDADD)
31 $(NACL_LDFLAGS) \
32 libtoxcore.la \
33 $(LIBSODIUM_LIBS) \
34 $(NACL_LIBS) \
35 $(CHECK_LIBS)
36 32
37network_test_SOURCES = \
38 ../auto_tests/network_test.c
39 33
40network_test_CFLAGS = \ 34network_test_SOURCES = ../auto_tests/network_test.c
41 $(LIBSODIUM_CFLAGS) \ 35
42 $(NACL_CFLAGS) \ 36network_test_CFLAGS = $(AUTOTEST_CFLAGS)
43 $(CHECK_CFLAGS) 37
38network_test_LDADD = $(AUTOTEST_LDADD)
44 39
45network_test_LDADD = \
46 $(LIBSODIUM_LDFLAGS) \
47 $(NACL_LDFLAGS) \
48 libtoxcore.la \
49 $(LIBSODIUM_LIBS) \
50 $(NACL_LIBS) \
51 $(CHECK_LIBS)
52 40
53endif 41endif
54 42
diff --git a/auto_tests/skeleton_test.c b/auto_tests/skeleton_test.c
new file mode 100644
index 00000000..89ef1b8b
--- /dev/null
+++ b/auto_tests/skeleton_test.c
@@ -0,0 +1,53 @@
1#ifdef HAVE_CONFIG_H
2#include "config.h"
3#endif
4
5#include <sys/types.h>
6#include <stdint.h>
7#include <string.h>
8#include <check.h>
9#include <stdlib.h>
10#include <time.h>
11
12/*
13#include "../<stuff to test>"
14*/
15
16START_TEST(test_creativetestnamegoeshere)
17{
18 uint8_t test = 0;
19 ck_assert_msg(test == 0, "test: expected result 0, got %u.", test);
20}
21END_TEST
22
23
24#define DEFTESTCASE(NAME) \
25 TCase *tc_##NAME = tcase_create(#NAME); \
26 tcase_add_test(tc_##NAME, test_##NAME); \
27 suite_add_tcase(s, tc_##NAME);
28
29Suite *creativesuitenamegoeshere_suite(void)
30{
31 Suite *s = suite_create("creativesuitedescritptiongoeshere");
32
33 DEFTESTCASE(/* remove test_ from test function names */ creativetestnamegoeshere);
34
35 return s;
36}
37
38int main(int argc, char *argv[])
39{
40 srand((unsigned int) time(NULL));
41
42 Suite *creativesuitenamegoeshere = creativesuitenamegoeshere_suite();
43 SRunner *test_runner = srunner_create(creativesuitenamegoeshere);
44
45 int number_failed = 0;
46 srunner_run_all(test_runner, CK_NORMAL);
47 number_failed = srunner_ntests_failed(test_runner);
48
49 srunner_free(test_runner);
50
51 return number_failed;
52}
53
diff --git a/docs/Hardening.txt b/docs/Hardening.txt
index 838b3566..d95b2cda 100644
--- a/docs/Hardening.txt
+++ b/docs/Hardening.txt
@@ -45,4 +45,16 @@ to us then it is good.
45 45
46Problems with this: People don't always have at least one online friend. 46Problems with this: People don't always have at least one online friend.
47 47
482. ... 482. Pick random nodes (add ourselves some random (fake) friends to increase the
49pool of available nodes) and make then send requests to other nodes, the
50response is then relayed back to us and compared to how the node should have
51behaved. If the node is found to be behaving correctly, it is set as trusted.
52Only trusted nodes are sent in send node packets, that is unless the exact node
53being queried for in the getnode packet is present, it will be sent in the
54sendnode packet even if it is not trusted.
55
56The hypothesis is that if to be part of the network nodes have to behave
57correctly it should prevent disruption from nodes that behave incorrectly.
58
59(This idea is currently being implemented in the harden branch.)
60...
diff --git a/docs/av_api.md b/docs/av_api.md
index 08e05a6d..17930144 100644
--- a/docs/av_api.md
+++ b/docs/av_api.md
@@ -1,10 +1,13 @@
1A/V API reference 1#A/V API reference
2 2
3Take toxmsi/phone.c as a reference 3##Take toxmsi/phone.c as a reference
4 4
5Initialization: 5###Initialization:
6 6
7```
7phone_t* initPhone(uint16_t _listen_port, uint16_t _send_port); 8phone_t* initPhone(uint16_t _listen_port, uint16_t _send_port);
9```
10
8function initializes sample phone. _listen_port and _send_port are variables only meant 11function initializes sample phone. _listen_port and _send_port are variables only meant
9for local testing. You will not have to do anything regarding to that since 12for local testing. You will not have to do anything regarding to that since
10everything will be started within a mesenger. 13everything will be started within a mesenger.
@@ -13,17 +16,22 @@ everything will be started within a mesenger.
13Phone requires one msi session and two rtp sessions ( one for audio and one for 16Phone requires one msi session and two rtp sessions ( one for audio and one for
14video ). 17video ).
15 18
19```
16msi_session_t* msi_init_session( void* _core_handler, const uint8_t* _user_agent ); 20msi_session_t* msi_init_session( void* _core_handler, const uint8_t* _user_agent );
21```
17 22
18initializes msi session. 23initializes msi session.
19Params: 24Params:
25
26```
20void* _core_handler - pointer to an object handling networking, 27void* _core_handler - pointer to an object handling networking,
21const uint8_t* _user_agent - string describing phone client version. 28const uint8_t* _user_agent - string describing phone client version.
29```
22 30
23Return value: 31Return value:
24msi_session_t* - pointer to a newly created msi session handler. 32msi_session_t* - pointer to a newly created msi session handler.
25 33
26msi_session_t reference: 34###msi_session_t reference:
27 35
28How to handle msi session: 36How to handle msi session:
29Controling is done via callbacks and action handlers. 37Controling 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
32directly from event loop. You can find examples in phone.c. 40directly from event loop. You can find examples in phone.c.
33 41
34Register callbacks: 42Register callbacks:
43```
35void msi_register_callback_call_started ( MCALLBACK ); 44void msi_register_callback_call_started ( MCALLBACK );
36void msi_register_callback_call_canceled ( MCALLBACK ); 45void msi_register_callback_call_canceled ( MCALLBACK );
37void msi_register_callback_call_rejected ( MCALLBACK ); 46void msi_register_callback_call_rejected ( MCALLBACK );
@@ -44,52 +53,72 @@ void msi_register_callback_recv_ending ( MCALLBACK );
44void msi_register_callback_recv_error ( MCALLBACK ); 53void msi_register_callback_recv_error ( MCALLBACK );
45 54
46void msi_register_callback_requ_timeout ( MCALLBACK ); 55void msi_register_callback_requ_timeout ( MCALLBACK );
56```
47 57
48MCALLBACK is defined as: void (*callback) (void* _arg) 58MCALLBACK is defined as: void (*callback) (void* _arg)
49msi_session_t* handler is being thrown as _arg so you can use that and _agent_handler to get to your own phone handler 59msi_session_t* handler is being thrown as \_arg so you can use that and \_agent_handler to get to your own phone handler
50directly from callback. 60directly from callback.
51 61
52 62
53Actions: 63Actions:
64
65```
54int msi_invite ( msi_session_t* _session, call_type _call_type, uint32_t _timeoutms ); 66int msi_invite ( msi_session_t* _session, call_type _call_type, uint32_t _timeoutms );
67```
68
55Sends call invite. Before calling/sending invite msi_session_t::_friend_id is needed to be set or else 69Sends call invite. Before calling/sending invite msi_session_t::_friend_id is needed to be set or else
56it will not work. _call_type is type of the call ( Audio/Video ) and _timeoutms is how long 70it will not work. _call_type is type of the call ( Audio/Video ) and _timeoutms is how long
57will poll wait until request is terminated. 71will poll wait until request is terminated.
58 72
73```
59int msi_hangup ( msi_session_t* _session ); 74int msi_hangup ( msi_session_t* _session );
75```
60Hangs up active call 76Hangs up active call
61 77
78```
62int msi_answer ( msi_session_t* _session, call_type _call_type ); 79int msi_answer ( msi_session_t* _session, call_type _call_type );
80```
63Answer incomming call. _call_type set's callee call type. 81Answer incomming call. _call_type set's callee call type.
64 82
83```
65int msi_cancel ( msi_session_t* _session ); 84int msi_cancel ( msi_session_t* _session );
85```
66Cancel current request. 86Cancel current request.
67 87
88```
68int msi_reject ( msi_session_t* _session ); 89int msi_reject ( msi_session_t* _session );
90```
69Reject incomming call. 91Reject incomming call.
70 92
71 93
94###Now for rtp:
72 95
73
74Now for rtp:
75You will need 2 sessions; one for audio one for video. 96You will need 2 sessions; one for audio one for video.
76You start them with: 97You start them with:
77 98```
78rtp_session_t* rtp_init_session ( int _max_users, int _multi_session ); 99rtp_session_t* rtp_init_session ( int _max_users, int _multi_session );
100```
79 101
80Params: 102Params:
103```
81int _max_users - max users. -1 if undefined 104int _max_users - max users. -1 if undefined
82int _multi_session - any positive number means uses multi session; -1 if not. 105int _multi_session - any positive number means uses multi session; -1 if not.
106```
83 107
84Return value: 108Return value:
109```
85rtp_session_t* - pointer to a newly created rtp session handler. 110rtp_session_t* - pointer to a newly created rtp session handler.
111```
86 112
87How to handle rtp session: 113###How to handle rtp session:
88Take a look at 114Take a look at
115```
89void* phone_handle_media_transport_poll ( void* _hmtc_args_p ) in phone.c 116void* phone_handle_media_transport_poll ( void* _hmtc_args_p ) in phone.c
117```
90on example. Basically what you do is just receive a message via: 118on example. Basically what you do is just receive a message via:
91 119```
92struct rtp_msg_s* rtp_recv_msg ( rtp_session_t* _session ); 120struct rtp_msg_s* rtp_recv_msg ( rtp_session_t* _session );
121```
93 122
94and then you use payload within the rtp_msg_s struct. Don't forget to deallocate it with: 123and then you use payload within the rtp_msg_s struct. Don't forget to deallocate it with:
95void rtp_free_msg ( rtp_session_t* _session, struct rtp_msg_s* _msg ); 124void 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.
98When you capture and encode a payload you want to send it ( obviously ). 127When you capture and encode a payload you want to send it ( obviously ).
99 128
100first create a new message with: 129first create a new message with:
130```
101struct rtp_msg_s* rtp_msg_new ( rtp_session_t* _session, const uint8_t* _data, uint32_t _length ); 131struct rtp_msg_s* rtp_msg_new ( rtp_session_t* _session, const uint8_t* _data, uint32_t _length );
132```
102 133
103and then send it with: 134and then send it with:
135```
104int rtp_send_msg ( rtp_session_t* _session, struct rtp_msg_s* _msg, void* _core_handler ); 136int rtp_send_msg ( rtp_session_t* _session, struct rtp_msg_s* _msg, void* _core_handler );
137```
105 138
106_core_handler is the same network handler as in msi_session_s struct. 139_core_handler is the same network handler as in msi_session_s struct.
107 140
108 141
109 142##A/V initialization:
110A/V initialization: 143```
111
112int init_receive_audio(codec_state *cs); 144int init_receive_audio(codec_state *cs);
113int init_receive_video(codec_state *cs); 145int init_receive_video(codec_state *cs);
114Initialises the A/V decoders. On failure it will print the reason and return 0. On success it will return 1. 146Initialises 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);
122Reinitialises 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. 154Reinitialises 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.
123In the future, VP8 should be used directly and ffmpeg should be dropped from the dependencies. 155In the future, VP8 should be used directly and ffmpeg should be dropped from the dependencies.
124The variable bps is the required bitrate in bits per second. 156The variable bps is the required bitrate in bits per second.
157```
125 158
126 159
127 160###A/V encoding/decoding:
128A/V encoding/decoding: 161```
129
130void *encode_video_thread(void *arg); 162void *encode_video_thread(void *arg);
163```
131Spawns the video encoding thread. The argument should hold a pointer to a codec_state. 164Spawns the video encoding thread. The argument should hold a pointer to a codec_state.
132This function should only be called if video encoding is supported (when init_send_video returns 1). 165This function should only be called if video encoding is supported (when init_send_video returns 1).
133Each video frame gets encoded into a packet, which is sent via RTP. Every 60 frames a new bidirectional interframe is encoded. 166Each video frame gets encoded into a packet, which is sent via RTP. Every 60 frames a new bidirectional interframe is encoded.
134 167```
135void *encode_audio_thread(void *arg); 168void *encode_audio_thread(void *arg);
169```
136Spawns the audio encoding thread. The argument should hold a pointer to a codec_state. 170Spawns the audio encoding thread. The argument should hold a pointer to a codec_state.
137This function should only be called if audio encoding is supported (when init_send_audio returns 1). 171This function should only be called if audio encoding is supported (when init_send_audio returns 1).
138Audio frames are read from the selected audio capture device during intitialisation. This audio capturing can be rerouted to a different device on the fly. 172Audio frames are read from the selected audio capture device during intitialisation. This audio capturing can be rerouted to a different device on the fly.
139Each 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. 173Each 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.
140 174```
141int video_decoder_refresh(codec_state *cs, int width, int height); 175int video_decoder_refresh(codec_state *cs, int width, int height);
176```
142Sets 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. 177Sets 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.
143 178
179```
144void *decode_video_thread(void *arg); 180void *decode_video_thread(void *arg);
181```
145Spawns 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. 182Spawns 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.
146This 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. 183This 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.
147 184```
148void *decode_audio_thread(void *arg); 185void *decode_audio_thread(void *arg);
186```
149Spawns 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. 187Spawns 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.
150All 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. 188All 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.
151Audio is played on the default OpenAL output device. 189Audio is played on the default OpenAL output device.
@@ -153,4 +191,4 @@ Audio is played on the default OpenAL output device.
153 191
154If you have any more qustions/bug reports/feature request contact the following users on the irc channel #tox-dev on irc.freenode.net: 192If you have any more qustions/bug reports/feature request contact the following users on the irc channel #tox-dev on irc.freenode.net:
155For RTP and MSI: mannol 193For RTP and MSI: mannol
156For audio and video: Martijnvdc \ No newline at end of file 194For audio and video: Martijnvdc
diff --git a/toxcore/DHT.c b/toxcore/DHT.c
index c43382ed..b9ba7e1d 100644
--- a/toxcore/DHT.c
+++ b/toxcore/DHT.c
@@ -814,110 +814,109 @@ static uint8_t sent_getnode_to_node(DHT *dht, uint8_t *client_id, IP_Port node_i
814/* Function is needed in following functions. */ 814/* Function is needed in following functions. */
815static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, Node_format *list, uint16_t num_nodes); 815static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, Node_format *list, uint16_t num_nodes);
816 816
817static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length) 817static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet, uint32_t length,
818 size_t node_format_size, uint8_t *plain, uint16_t plain_length, uint32_t *num_nodes_out, Node_format *sendback_node)
818{ 819{
820 if (plain_length != MAX_SENT_NODES * node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH)
821 return 1;
822
819 DHT *dht = object; 823 DHT *dht = object;
820 uint32_t cid_size = 1 + CLIENT_ID_SIZE; 824 uint32_t cid_size = 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES;
821 cid_size += crypto_box_NONCEBYTES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES;
822 825
823 size_t Node4_format_size = sizeof(Node4_format); 826 if (length <= cid_size) /* too short */
827 return 1;
828
829 uint32_t data_size = length - cid_size;
824 830
825 if (length > (cid_size + Node4_format_size * MAX_SENT_NODES) || 831 if ((data_size % node_format_size) != 0) /* invalid length */
826 ((length - cid_size) % Node4_format_size) != 0 ||
827 (length < cid_size + Node4_format_size))
828 return 1; 832 return 1;
829 833
830 uint32_t num_nodes = (length - cid_size) / Node4_format_size; 834 uint32_t num_nodes = data_size / node_format_size;
831 uint8_t plain[Node4_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH]; 835
836 if (num_nodes > MAX_SENT_NODES) /* too long */
837 return 1;
832 838
833 int len = decrypt_data( 839 int len = decrypt_data(
834 packet + 1, 840 packet + 1,
835 dht->c->self_secret_key, 841 dht->c->self_secret_key,
836 packet + 1 + CLIENT_ID_SIZE, 842 packet + 1 + CLIENT_ID_SIZE,
837 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, 843 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
838 num_nodes * Node4_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES, plain ); 844 num_nodes * node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES,
845 plain);
846
847 if ((unsigned int)len != num_nodes * node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH)
848 return 1;
839 849
840 if ((unsigned int)len != num_nodes * Node4_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH) 850 if (!sent_getnode_to_node(dht, packet + 1, source, plain + num_nodes * node_format_size, sendback_node))
841 return 1; 851 return 1;
842 852
853 /* store the address the *request* was sent to */
854 addto_lists(dht, source, packet + 1);
855
856 *num_nodes_out = num_nodes;
857
858 return 0;
859}
860
861static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length)
862{
863 DHT *dht = object;
864 size_t node4_format_size = sizeof(Node4_format);
865 uint8_t plain[node4_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH];
866 uint32_t num_nodes;
867
843 Node_format sendback_node; 868 Node_format sendback_node;
844 869
845 if (!sent_getnode_to_node(dht, packet + 1, source, plain + num_nodes * Node4_format_size, &sendback_node)) 870 if (handle_sendnodes_core(object, source, packet, length, node4_format_size, plain, sizeof(plain), &num_nodes,
871 &sendback_node))
846 return 1; 872 return 1;
847 873
848 Node4_format *nodes4_list = (Node4_format *)(plain); 874 Node4_format *nodes4_list = (Node4_format *)(plain);
875 uint32_t i;
876
877 IP_Port ipp;
878 ipp.ip.family = AF_INET;
879
849 Node_format nodes_list[MAX_SENT_NODES]; 880 Node_format nodes_list[MAX_SENT_NODES];
850 uint32_t i, num_nodes_ok = 0;
851 881
852 /* blow up from Node4 (IPv4) wire format to Node (IPv4/IPv6) structure */
853 for (i = 0; i < num_nodes; i++) 882 for (i = 0; i < num_nodes; i++)
854 if ((nodes4_list[i].ip_port.ip.uint32 != 0) && (nodes4_list[i].ip_port.ip.uint32 != (uint32_t)~0)) { 883 if ((nodes4_list[i].ip_port.ip.uint32 != 0) && (nodes4_list[i].ip_port.ip.uint32 != (uint32_t)~0)) {
855 memcpy(nodes_list[num_nodes_ok].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE); 884 ipp.ip.ip4.uint32 = nodes4_list[i].ip_port.ip.uint32;
856 nodes_list[num_nodes_ok].ip_port.ip.family = AF_INET; 885 ipp.port = nodes4_list[i].ip_port.port;
857 nodes_list[num_nodes_ok].ip_port.ip.ip4.uint32 = nodes4_list[i].ip_port.ip.uint32;
858 nodes_list[num_nodes_ok].ip_port.port = nodes4_list[i].ip_port.port;
859 886
860 num_nodes_ok++; 887 send_ping_request(dht->ping, ipp, nodes4_list[i].client_id);
861 } 888 returnedip_ports(dht, ipp, nodes4_list[i].client_id, packet + 1);
862 889
863 if (num_nodes_ok < num_nodes) { 890 memcpy(nodes_list[i].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE);
864 /* shouldn't happen */ 891 ipport_copy(&nodes_list[i].ip_port, &ipp);
865 num_nodes = num_nodes_ok; 892 }
866 }
867 893
868 send_hardening_getnode_res(dht, &sendback_node, nodes_list, num_nodes); 894 send_hardening_getnode_res(dht, &sendback_node, nodes_list, num_nodes);
869 addto_lists(dht, source, packet + 1);
870
871 for (i = 0; i < num_nodes; ++i) {
872 send_ping_request(dht->ping, nodes_list[i].ip_port, nodes_list[i].client_id);
873 returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1);
874 }
875
876 return 0; 895 return 0;
877} 896}
878 897
879static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet, uint32_t length) 898static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet, uint32_t length)
880{ 899{
881 DHT *dht = object; 900 DHT *dht = object;
882 uint32_t cid_size = 1 + CLIENT_ID_SIZE; 901 size_t node_format_size = sizeof(Node_format);
883 cid_size += crypto_box_NONCEBYTES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES; 902 uint8_t plain[node_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH];
884 903 uint32_t num_nodes;
885 size_t Node_format_size = sizeof(Node_format);
886
887 if (length > (cid_size + Node_format_size * MAX_SENT_NODES) ||
888 ((length - cid_size) % Node_format_size) != 0 ||
889 (length < cid_size + Node_format_size))
890 return 1;
891
892 uint32_t num_nodes = (length - cid_size) / Node_format_size;
893 uint8_t plain[Node_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH];
894
895 int len = decrypt_data(
896 packet + 1,
897 dht->c->self_secret_key,
898 packet + 1 + CLIENT_ID_SIZE,
899 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
900 num_nodes * Node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES, plain );
901
902 if ((unsigned int)len != num_nodes * Node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH)
903 return 1;
904 904
905 Node_format sendback_node; 905 Node_format sendback_node;
906 906
907 if (!sent_getnode_to_node(dht, packet + 1, source, plain + num_nodes * Node_format_size, &sendback_node)) 907 if (handle_sendnodes_core(object, source, packet, length, node_format_size, plain, sizeof(plain), &num_nodes,
908 &sendback_node))
908 return 1; 909 return 1;
909 910
911 Node_format *nodes_list = (Node_format *)(plain);
910 uint32_t i; 912 uint32_t i;
911 Node_format nodes_list[MAX_SENT_NODES];
912 memcpy(nodes_list, plain, num_nodes * sizeof(Node_format));
913
914 send_hardening_getnode_res(dht, &sendback_node, nodes_list, num_nodes); 913 send_hardening_getnode_res(dht, &sendback_node, nodes_list, num_nodes);
915 addto_lists(dht, source, packet + 1);
916 914
917 for (i = 0; i < num_nodes; ++i) { 915 for (i = 0; i < num_nodes; i++)
918 send_ping_request(dht->ping, nodes_list[i].ip_port, nodes_list[i].client_id); 916 if (ipport_isset(&nodes_list[i].ip_port)) {
919 returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1); 917 send_ping_request(dht->ping, nodes_list[i].ip_port, nodes_list[i].client_id);
920 } 918 returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1);
919 }
921 920
922 return 0; 921 return 0;
923} 922}
diff --git a/toxcore/Lossless_UDP.c b/toxcore/Lossless_UDP.c
index 04533a3b..79ee32c3 100644
--- a/toxcore/Lossless_UDP.c
+++ b/toxcore/Lossless_UDP.c
@@ -833,8 +833,7 @@ static int handle_SYNC2(Lossless_UDP *ludp, int connection_id, uint8_t counter,
833{ 833{
834 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); 834 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
835 835
836 if (recv_packetnum == connection->orecv_packetnum) { 836 if (recv_packetnum == connection->orecv_packetnum && sent_packetnum == connection->osent_packetnum) {
837 /* && sent_packetnum == connection->osent_packetnum) */
838 connection->status = LUDP_ESTABLISHED; 837 connection->status = LUDP_ESTABLISHED;
839 connection->recv_counter = counter; 838 connection->recv_counter = counter;
840 ++connection->send_counter; 839 ++connection->send_counter;
@@ -862,8 +861,8 @@ static void adjust_datasendspeed(Connection *connection, uint32_t req_packets)
862 return; 861 return;
863 } 862 }
864 863
865 if (req_packets <= (connection->data_rate / connection->SYNC_rate) / 5 || req_packets <= 10) { 864 if (req_packets <= (connection->data_rate / connection->SYNC_rate) / 4 || req_packets <= 10) {
866 connection->data_rate += (connection->data_rate / 8) + 1; 865 connection->data_rate += (connection->data_rate / 4) + 1;
867 866
868 if (connection->data_rate > connection->sendbuffer_length * connection->SYNC_rate) 867 if (connection->data_rate > connection->sendbuffer_length * connection->SYNC_rate)
869 connection->data_rate = connection->sendbuffer_length * connection->SYNC_rate; 868 connection->data_rate = connection->sendbuffer_length * connection->SYNC_rate;
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c
index be3d82e0..659c837b 100644
--- a/toxcore/Messenger.c
+++ b/toxcore/Messenger.c
@@ -868,13 +868,36 @@ int m_group_peername(Messenger *m, int groupnumber, int peernumber, uint8_t *nam
868 868
869 return group_peername(m->chats[groupnumber], peernumber, name); 869 return group_peername(m->chats[groupnumber], peernumber, name);
870} 870}
871
872/* Store the fact that we invited a specific friend.
873 */
874static void group_store_friendinvite(Messenger *m, int friendnumber, int groupnumber)
875{
876 /* Add 1 to the groupchat number because 0 (default value in invited_groups) is a valid groupchat number */
877 m->friendlist[friendnumber].invited_groups[m->friendlist[friendnumber].invited_groups_num % MAX_INVITED_GROUPS] =
878 groupnumber + 1;
879 ++m->friendlist[friendnumber].invited_groups_num;
880}
881
871/* return 1 if that friend was invited to the group 882/* return 1 if that friend was invited to the group
872 * return 0 if the friend was not or error. 883 * return 0 if the friend was not or error.
873 */ 884 */
874static uint8_t group_invited(Messenger *m, int friendnumber, int groupnumber) 885static uint8_t group_invited(Messenger *m, int friendnumber, int groupnumber)
875{ 886{
876 //TODO: this function; 887
877 return 1; 888 uint32_t i;
889 uint16_t num = MAX_INVITED_GROUPS;
890
891 if (MAX_INVITED_GROUPS > m->friendlist[friendnumber].invited_groups_num)
892 num = m->friendlist[friendnumber].invited_groups_num;
893
894 for (i = 0; i < num; ++i) {
895 if (m->friendlist[friendnumber].invited_groups[i] == groupnumber + 1) {
896 return 1;
897 }
898 }
899
900 return 0;
878} 901}
879 902
880/* invite friendnumber to groupnumber 903/* invite friendnumber to groupnumber
@@ -892,7 +915,8 @@ int invite_friend(Messenger *m, int friendnumber, int groupnumber)
892 if (m->friendlist[friendnumber].status == NOFRIEND || m->chats[groupnumber] == NULL) 915 if (m->friendlist[friendnumber].status == NOFRIEND || m->chats[groupnumber] == NULL)
893 return -1; 916 return -1;
894 917
895 //TODO: store invited friends. 918 group_store_friendinvite(m, friendnumber, groupnumber);
919
896 if (write_cryptpacket_id(m, friendnumber, PACKET_ID_INVITE_GROUPCHAT, m->chats[groupnumber]->self_public_key, 920 if (write_cryptpacket_id(m, friendnumber, PACKET_ID_INVITE_GROUPCHAT, m->chats[groupnumber]->self_public_key,
897 crypto_box_PUBLICKEYBYTES) == 0) 921 crypto_box_PUBLICKEYBYTES) == 0)
898 return -1; 922 return -1;
@@ -1782,10 +1806,10 @@ void do_messenger(Messenger *m)
1782 1806
1783#ifdef LOGGING 1807#ifdef LOGGING
1784 1808
1785 if (now() > lastdump + DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS) { 1809 if (unix_time() > lastdump + DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS) {
1786 loglog(" = = = = = = = = \n"); 1810 loglog(" = = = = = = = = \n");
1787 1811
1788 lastdump = now(); 1812 lastdump = unix_time();
1789 uint32_t client, last_pinged; 1813 uint32_t client, last_pinged;
1790 1814
1791 for (client = 0; client < LCLIENT_LIST; client++) { 1815 for (client = 0; client < LCLIENT_LIST; client++) {
diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h
index aa9d8632..10ac0eae 100644
--- a/toxcore/Messenger.h
+++ b/toxcore/Messenger.h
@@ -52,6 +52,9 @@
52#define PACKET_ID_JOIN_GROUPCHAT 145 52#define PACKET_ID_JOIN_GROUPCHAT 145
53#define PACKET_ID_ACCEPT_GROUPCHAT 146 53#define PACKET_ID_ACCEPT_GROUPCHAT 146
54 54
55/* Max number of groups we can invite someone at the same time to. */
56#define MAX_INVITED_GROUPS 64
57
55/* Status definitions. */ 58/* Status definitions. */
56enum { 59enum {
57 NOFRIEND, 60 NOFRIEND,
@@ -148,6 +151,8 @@ typedef struct {
148 uint64_t ping_lastsent; 151 uint64_t ping_lastsent;
149 struct File_Transfers file_sending[MAX_CONCURRENT_FILE_PIPES]; 152 struct File_Transfers file_sending[MAX_CONCURRENT_FILE_PIPES];
150 struct File_Transfers file_receiving[MAX_CONCURRENT_FILE_PIPES]; 153 struct File_Transfers file_receiving[MAX_CONCURRENT_FILE_PIPES];
154 int invited_groups[MAX_INVITED_GROUPS];
155 uint16_t invited_groups_num;
151} Friend; 156} Friend;
152 157
153typedef struct Messenger { 158typedef struct Messenger {
diff --git a/toxcore/group_chats.c b/toxcore/group_chats.c
index 5831e7d4..6ad41c7f 100644
--- a/toxcore/group_chats.c
+++ b/toxcore/group_chats.c
@@ -205,13 +205,15 @@ static int addpeer(Group_Chat *chat, uint8_t *client_id)
205 205
206 Group_Peer *temp; 206 Group_Peer *temp;
207 temp = realloc(chat->group, sizeof(Group_Peer) * (chat->numpeers + 1)); 207 temp = realloc(chat->group, sizeof(Group_Peer) * (chat->numpeers + 1));
208 memset(&(temp[chat->numpeers]), 0, sizeof(Group_Peer));
209 208
210 if (temp == NULL) 209 if (temp == NULL)
211 return -1; 210 return -1;
212 211
212 memset(&(temp[chat->numpeers]), 0, sizeof(Group_Peer));
213 chat->group = temp; 213 chat->group = temp;
214 id_copy(chat->group[chat->numpeers].client_id, client_id); 214 id_copy(chat->group[chat->numpeers].client_id, client_id);
215 chat->group[chat->numpeers].last_recv = unix_time();
216 chat->group[chat->numpeers].last_recv_msgping = unix_time();
215 ++chat->numpeers; 217 ++chat->numpeers;
216 return (chat->numpeers - 1); 218 return (chat->numpeers - 1);
217} 219}
@@ -287,7 +289,8 @@ static int send_getnodes(Group_Chat *chat, IP_Port ip_port, int peernum)
287 chat->group[peernum].last_pinged = unix_time(); 289 chat->group[peernum].last_pinged = unix_time();
288 chat->group[peernum].pingid = contents.pingid; 290 chat->group[peernum].pingid = contents.pingid;
289 291
290 return send_groupchatpacket(chat, ip_port, chat->group[peernum].client_id, (uint8_t *)&contents, sizeof(contents), 48); 292 return send_groupchatpacket(chat, ip_port, chat->group[peernum].client_id, (uint8_t *)&contents, sizeof(contents),
293 CRYPTO_PACKET_GROUP_CHAT_GET_NODES);
291} 294}
292 295
293static int send_sendnodes(Group_Chat *chat, IP_Port ip_port, int peernum, uint64_t pingid) 296static 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
308 } 311 }
309 312
310 return send_groupchatpacket(chat, ip_port, chat->group[peernum].client_id, (uint8_t *)&contents, 313 return send_groupchatpacket(chat, ip_port, chat->group[peernum].client_id, (uint8_t *)&contents,
311 sizeof(contents.pingid) + sizeof(groupchat_nodes) * j, 49); 314 sizeof(contents.pingid) + sizeof(groupchat_nodes) * j, CRYPTO_PACKET_GROUP_CHAT_SEND_NODES);
312} 315}
313 316
314static int handle_getnodes(Group_Chat *chat, IP_Port source, int peernum, uint8_t *data, uint32_t len) 317static 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)
392 395
393 if (chat->group[peernum].last_recv == temp_time) 396 if (chat->group[peernum].last_recv == temp_time)
394 return 1; 397 return 1;
395
396 chat->group[peernum].last_recv = temp_time;
397 */ 398 */
399 chat->group[peernum].last_recv = unix_time();
400
398 uint32_t message_num; 401 uint32_t message_num;
399 memcpy(&message_num, data + crypto_box_PUBLICKEYBYTES, sizeof(uint32_t)); 402 memcpy(&message_num, data + crypto_box_PUBLICKEYBYTES, sizeof(uint32_t));
400 message_num = ntohl(message_num); 403 message_num = ntohl(message_num);
@@ -412,21 +415,21 @@ static int handle_data(Group_Chat *chat, uint8_t *data, uint32_t len)
412 uint16_t contents_len = len - GROUP_DATA_MIN_SIZE; 415 uint16_t contents_len = len - GROUP_DATA_MIN_SIZE;
413 416
414 switch (data[crypto_box_PUBLICKEYBYTES + sizeof(message_num)]) { 417 switch (data[crypto_box_PUBLICKEYBYTES + sizeof(message_num)]) {
415 case 0: /* If message is ping */ 418 case GROUP_CHAT_PING: /* If message is ping */
416 if (contents_len != 0) 419 if (contents_len != 0)
417 return 1; 420 return 1;
418 421
419 chat->group[peernum].last_recv_msgping = unix_time(); 422 chat->group[peernum].last_recv_msgping = unix_time();
420 break; 423 break;
421 424
422 case 16: /* If message is new peer */ 425 case GROUP_CHAT_NEW_PEER: /* If message is new peer */
423 if (contents_len != crypto_box_PUBLICKEYBYTES) 426 if (contents_len != crypto_box_PUBLICKEYBYTES)
424 return 1; 427 return 1;
425 428
426 addpeer(chat, contents); 429 addpeer(chat, contents);
427 break; 430 break;
428 431
429 case 64: /* If message is chat message */ 432 case GROUP_CHAT_CHAT_MESSAGE: /* If message is chat message */
430 if (chat->group_message != NULL) 433 if (chat->group_message != NULL)
431 (*chat->group_message)(chat, peernum, contents, contents_len, chat->group_message_userdata); 434 (*chat->group_message)(chat, peernum, contents, contents_len, chat->group_message_userdata);
432 435
@@ -439,7 +442,7 @@ static int handle_data(Group_Chat *chat, uint8_t *data, uint32_t len)
439 } 442 }
440 443
441 if (handled == 1) { 444 if (handled == 1) {
442 sendto_allpeers(chat, data, len, 50); 445 sendto_allpeers(chat, data, len, CRYPTO_PACKET_GROUP_CHAT_BROADCAST);
443 return 0; 446 return 0;
444 } 447 }
445 448
@@ -461,9 +464,12 @@ static uint8_t send_data(Group_Chat *chat, uint8_t *data, uint32_t len, uint8_t
461//TODO 464//TODO
462 id_copy(packet, chat->self_public_key); 465 id_copy(packet, chat->self_public_key);
463 memcpy(packet + crypto_box_PUBLICKEYBYTES, &message_num, sizeof(message_num)); 466 memcpy(packet + crypto_box_PUBLICKEYBYTES, &message_num, sizeof(message_num));
464 memcpy(packet + GROUP_DATA_MIN_SIZE, data, len); 467
468 if (len != 0)
469 memcpy(packet + GROUP_DATA_MIN_SIZE, data, len);
470
465 packet[crypto_box_PUBLICKEYBYTES + sizeof(message_num)] = message_id; 471 packet[crypto_box_PUBLICKEYBYTES + sizeof(message_num)] = message_id;
466 return sendto_allpeers(chat, packet, len + GROUP_DATA_MIN_SIZE, 50); 472 return sendto_allpeers(chat, packet, len + GROUP_DATA_MIN_SIZE, CRYPTO_PACKET_GROUP_CHAT_BROADCAST);
467} 473}
468/* 474/*
469 * Handle get nodes group packet. 475 * Handle get nodes group packet.
@@ -494,13 +500,13 @@ int handle_groupchatpacket(Group_Chat *chat, IP_Port source, uint8_t *packet, ui
494 return 1; 500 return 1;
495 501
496 switch (number) { 502 switch (number) {
497 case 48: 503 case CRYPTO_PACKET_GROUP_CHAT_GET_NODES:
498 return handle_getnodes(chat, source, peernum, data, len); 504 return handle_getnodes(chat, source, peernum, data, len);
499 505
500 case 49: 506 case CRYPTO_PACKET_GROUP_CHAT_SEND_NODES:
501 return handle_sendnodes(chat, source, peernum, data, len); 507 return handle_sendnodes(chat, source, peernum, data, len);
502 508
503 case 50: 509 case CRYPTO_PACKET_GROUP_CHAT_BROADCAST:
504 return handle_data(chat, data, len); 510 return handle_data(chat, data, len);
505 511
506 default: 512 default:
@@ -512,13 +518,13 @@ int handle_groupchatpacket(Group_Chat *chat, IP_Port source, uint8_t *packet, ui
512 518
513uint32_t group_sendmessage(Group_Chat *chat, uint8_t *message, uint32_t length) 519uint32_t group_sendmessage(Group_Chat *chat, uint8_t *message, uint32_t length)
514{ 520{
515 return send_data(chat, message, length, 64); //TODO: better return values? 521 return send_data(chat, message, length, GROUP_CHAT_CHAT_MESSAGE); //TODO: better return values?
516} 522}
517 523
518uint32_t group_newpeer(Group_Chat *chat, uint8_t *client_id) 524uint32_t group_newpeer(Group_Chat *chat, uint8_t *client_id)
519{ 525{
520 addpeer(chat, client_id); 526 addpeer(chat, client_id);
521 return send_data(chat, client_id, crypto_box_PUBLICKEYBYTES, 16); //TODO: better return values? 527 return send_data(chat, client_id, crypto_box_PUBLICKEYBYTES, GROUP_CHAT_NEW_PEER); //TODO: better return values?
522} 528}
523 529
524void callback_groupmessage(Group_Chat *chat, void (*function)(Group_Chat *chat, int, uint8_t *, uint16_t, void *), 530void 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)
561 } 567 }
562} 568}
563 569
570/* Interval in seconds to send ping messages */
571#define GROUP_PING_INTERVAL 30
572
573static void ping_group(Group_Chat *chat)
574{
575 if (is_timeout(chat->last_sent_ping, GROUP_PING_INTERVAL)) {
576 if (send_data(chat, 0, 0, GROUP_CHAT_PING) != 0) /* Ping */
577 chat->last_sent_ping = unix_time();
578 }
579}
580
581static void del_dead_peers(Group_Chat *chat)
582{
583 uint32_t i;
584
585 for (i = 0; i < chat->numpeers; ++i) {
586 if (is_timeout(chat->group[i].last_recv_msgping, GROUP_PING_INTERVAL * 2)) {
587 delpeer(chat, chat->group[i].client_id);
588 }
589 }
590}
591
564void do_groupchat(Group_Chat *chat) 592void do_groupchat(Group_Chat *chat)
565{ 593{
566 unix_time_update(); 594 unix_time_update();
567 ping_close(chat); 595 ping_close(chat);
596 ping_group(chat);
597 /* TODO: Maybe run this less? */
598 del_dead_peers(chat);
568} 599}
569 600
570void kill_groupchat(Group_Chat *chat) 601void kill_groupchat(Group_Chat *chat)
diff --git a/toxcore/group_chats.h b/toxcore/group_chats.h
index 33f0b1e6..b3f2e5a8 100644
--- a/toxcore/group_chats.h
+++ b/toxcore/group_chats.h
@@ -63,9 +63,14 @@ typedef struct Group_Chat {
63 uint32_t message_number; 63 uint32_t message_number;
64 void (*group_message)(struct Group_Chat *m, int, uint8_t *, uint16_t, void *); 64 void (*group_message)(struct Group_Chat *m, int, uint8_t *, uint16_t, void *);
65 void *group_message_userdata; 65 void *group_message_userdata;
66 uint64_t last_sent_ping;
66 67
67} Group_Chat; 68} Group_Chat;
68 69
70#define GROUP_CHAT_PING 0
71#define GROUP_CHAT_NEW_PEER 16
72#define GROUP_CHAT_CHAT_MESSAGE 64
73
69/* Copy the name of peernum to name. 74/* Copy the name of peernum to name.
70 * name must be at least MAX_NICK_BYTES long. 75 * name must be at least MAX_NICK_BYTES long.
71 * 76 *
diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h
index 38400ebc..74c3326a 100644
--- a/toxcore/net_crypto.h
+++ b/toxcore/net_crypto.h
@@ -29,6 +29,9 @@
29#define CRYPTO_PACKET_FRIEND_REQ 32 /* Friend request crypto packet ID. */ 29#define CRYPTO_PACKET_FRIEND_REQ 32 /* Friend request crypto packet ID. */
30#define CRYPTO_PACKET_HARDENING 48 /* Hardening crypto packet ID. */ 30#define CRYPTO_PACKET_HARDENING 48 /* Hardening crypto packet ID. */
31#define CRYPTO_PACKET_NAT_PING 254 /* NAT ping crypto packet ID. */ 31#define CRYPTO_PACKET_NAT_PING 254 /* NAT ping crypto packet ID. */
32#define CRYPTO_PACKET_GROUP_CHAT_GET_NODES 48 /* Group chat get Nodes packet */
33#define CRYPTO_PACKET_GROUP_CHAT_SEND_NODES 49 /* Group chat send Nodes packet */
34#define CRYPTO_PACKET_GROUP_CHAT_BROADCAST 50 /* Group chat broadcast packet */
32#define CRYPTO_HANDSHAKE_TIMEOUT (CONNECTION_TIMEOUT * 2) 35#define CRYPTO_HANDSHAKE_TIMEOUT (CONNECTION_TIMEOUT * 2)
33 36
34#define CRYPTO_CONN_NO_CONNECTION 0 37#define CRYPTO_CONN_NO_CONNECTION 0
diff --git a/toxcore/ping.c b/toxcore/ping.c
index 3f237836..80e85a45 100644
--- a/toxcore/ping.c
+++ b/toxcore/ping.c
@@ -114,28 +114,35 @@ static uint64_t add_ping(PING *ping, IP_Port ipp) // O(n)
114 return ping->pings[p].id; 114 return ping->pings[p].id;
115} 115}
116 116
117static bool is_pinging(PING *ping, IP_Port ipp, uint64_t ping_id) // O(n) TODO: Replace this with something else. 117/* checks if ip/port or ping_id are already in the list to ping
118 * if both are set, both must match, otherwise the set must match
119 *
120 * returns 0 if neither is set or no match was found
121 * returns the (index + 1) of the match if one was found
122 */
123static int is_pinging(PING *ping, IP_Port ipp, uint64_t ping_id)
118{ 124{
125 // O(n) TODO: Replace this with something else.
119 126
120 /* shouldn't that be an OR ? */ 127 /* at least one MUST be set */
121 if (!ip_isset(&ipp.ip) && ping_id == 0) 128 uint8_t ip_valid = ip_isset(&ipp.ip);
122 return false;
123 129
124 size_t i, id; 130 if (!ip_valid && !ping_id)
131 return 0;
132
133 size_t i;
125 134
126 remove_timeouts(ping); 135 remove_timeouts(ping);
127 136
128 for (i = 0; i < ping->num_pings; i++) { 137 for (i = 0; i < ping->num_pings; i++) {
129 id = (ping->pos_pings + i) % PING_NUM_MAX; 138 size_t id = (ping->pos_pings + i) % PING_NUM_MAX;
130 139
131 /* ping_id = 0 means match any id. */ 140 if (!ping_id || (ping->pings[id].id == ping_id))
132 if ((!ip_isset(&ipp.ip) || ipport_equal(&ping->pings[id].ip_port, &ipp)) && 141 if (!ip_valid || ipport_equal(&ping->pings[id].ip_port, &ipp))
133 (ping->pings[id].id == ping_id || ping_id == 0)) { 142 return id + 1;
134 return true;
135 }
136 } 143 }
137 144
138 return false; 145 return 0;
139} 146}
140 147
141#define DHT_PING_SIZE (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(uint64_t) + crypto_box_MACBYTES) 148#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
252 return 1; 259 return 1;
253 260
254 /* Make sure ping_id is correct. */ 261 /* Make sure ping_id is correct. */
255 if (!is_pinging(ping, source, ping_id)) 262 int ping_index = is_pinging(ping, source, ping_id);
263
264 if (!ping_index)
256 return 1; 265 return 1;
257 266
258 // Associate source ip with client_id 267 /* Associate client_id with the ip the request was sent to */
259 addto_lists(dht, source, packet + 1); 268 addto_lists(dht, ping->pings[ping_index - 1].ip_port, packet + 1);
260 return 0; 269 return 0;
261} 270}
262 271
diff --git a/toxcore/tox.h b/toxcore/tox.h
index 5d3916b4..13e9c7a9 100644
--- a/toxcore/tox.h
+++ b/toxcore/tox.h
@@ -521,7 +521,7 @@ uint64_t tox_file_dataremaining(Tox *tox, int friendnumber, uint8_t filenumber,
521void tox_bootstrap_from_ip(Tox *tox, tox_IP_Port ip_port, uint8_t *public_key); 521void tox_bootstrap_from_ip(Tox *tox, tox_IP_Port ip_port, uint8_t *public_key);
522 522
523/* Resolves address into an IP address. If successful, sends a "get nodes" 523/* Resolves address into an IP address. If successful, sends a "get nodes"
524 * request to the given node with ip, port (in network byte order, HINT: use htons()) 524 * request to the given node with ip, port (in network byte order, HINT: use htons())
525 * and public_key to setup connections 525 * and public_key to setup connections
526 * 526 *
527 * address can be a hostname or an IP address (IPv4 or IPv6). 527 * address can be a hostname or an IP address (IPv4 or IPv6).
diff --git a/toxcore/util.c b/toxcore/util.c
index fab9f660..3a43042d 100644
--- a/toxcore/util.c
+++ b/toxcore/util.c
@@ -139,8 +139,10 @@ void loginit(uint16_t port)
139 if (logfile) 139 if (logfile)
140 fclose(logfile); 140 fclose(logfile);
141 141
142 if (!starttime) 142 if (!starttime) {
143 starttime = now(); 143 unix_time_update();
144 starttime = unix_time();
145 }
144 146
145 struct tm *tm = localtime(&starttime); 147 struct tm *tm = localtime(&starttime);
146 148
@@ -164,7 +166,7 @@ void loginit(uint16_t port)
164void loglog(char *text) 166void loglog(char *text)
165{ 167{
166 if (logfile) { 168 if (logfile) {
167 fprintf(logfile, "%4u %s", (uint32_t)(now() - starttime), text); 169 fprintf(logfile, "%4u %s", (uint32_t)(unix_time() - starttime), text);
168 fflush(logfile); 170 fflush(logfile);
169 171
170 return; 172 return;
@@ -175,7 +177,9 @@ void loglog(char *text)
175 size_t len = strlen(text); 177 size_t len = strlen(text);
176 178
177 if (!starttime) { 179 if (!starttime) {
178 starttime = now(); 180 unix_time_update();
181 starttime = unix_time();
182
179 logbufferprelen = 1024 + len - (len % 1024); 183 logbufferprelen = 1024 + len - (len % 1024);
180 logbufferpredata = malloc(logbufferprelen); 184 logbufferpredata = malloc(logbufferprelen);
181 logbufferprehead = logbufferpredata; 185 logbufferprehead = logbufferpredata;
@@ -193,7 +197,7 @@ void loglog(char *text)
193 logbufferprelen = lennew; 197 logbufferprelen = lennew;
194 } 198 }
195 199
196 int written = sprintf(logbufferprehead, "%4u %s", (uint32_t)(now() - starttime), text); 200 int written = sprintf(logbufferprehead, "%4u %s", (uint32_t)(unix_time() - starttime), text);
197 logbufferprehead += written; 201 logbufferprehead += written;
198} 202}
199 203