diff options
-rw-r--r-- | INSTALL.md | 5 | ||||
-rw-r--r-- | auto_tests/Makefile.inc | 50 | ||||
-rw-r--r-- | auto_tests/skeleton_test.c | 53 | ||||
-rw-r--r-- | docs/Hardening.txt | 14 | ||||
-rw-r--r-- | docs/av_api.md | 78 | ||||
-rw-r--r-- | toxcore/DHT.c | 123 | ||||
-rw-r--r-- | toxcore/Lossless_UDP.c | 7 | ||||
-rw-r--r-- | toxcore/Messenger.c | 34 | ||||
-rw-r--r-- | toxcore/Messenger.h | 5 | ||||
-rw-r--r-- | toxcore/group_chats.c | 63 | ||||
-rw-r--r-- | toxcore/group_chats.h | 5 | ||||
-rw-r--r-- | toxcore/net_crypto.h | 3 | ||||
-rw-r--r-- | toxcore/ping.c | 39 | ||||
-rw-r--r-- | toxcore/tox.h | 2 | ||||
-rw-r--r-- | toxcore/util.c | 14 |
15 files changed, 335 insertions, 160 deletions
@@ -54,6 +54,11 @@ make check | |||
54 | sudo make install | 54 | sudo make install |
55 | cd .. | 55 | cd .. |
56 | ``` | 56 | ``` |
57 | 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: | ||
58 | ``` | ||
59 | sudo echo "/usr/local/lib/" >> /etc/ld.so.conf.d/locallib.conf | ||
60 | sudo ldconfig | ||
61 | ``` | ||
57 | 62 | ||
58 | You also need recent [FFmpeg](http://git.videolan.org/?p=ffmpeg.git) libraries: | 63 | You 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 | ||
5 | check_PROGRAMS = messenger_autotest crypto_test network_test | 5 | check_PROGRAMS = messenger_autotest crypto_test network_test |
6 | 6 | ||
7 | messenger_autotest_SOURCES = \ | 7 | AUTOTEST_CFLAGS = \ |
8 | ../auto_tests/messenger_test.c | 8 | $(LIBSODIUM_CFLAGS) \ |
9 | 9 | $(NACL_CFLAGS) \ | |
10 | messenger_autotest_CFLAGS = \ | 10 | $(CHECK_CFLAGS) |
11 | $(LIBSODIUM_CFLAGS) \ | 11 | |
12 | $(NACL_CFLAGS) \ | 12 | AUTOTEST_LDADD = \ |
13 | $(CHECK_CFLAGS) | ||
14 | |||
15 | messenger_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 | ||
20 | messenger_autotest_SOURCES = ../auto_tests/messenger_test.c | ||
21 | |||
22 | messenger_autotest_CFLAGS = $(AUTOTEST_CFLAGS) | ||
23 | |||
24 | messenger_autotest_LDADD = $(AUTOTEST_LDADD) | ||
25 | |||
23 | 26 | ||
24 | crypto_test_SOURCES = ../auto_tests/crypto_test.c | 27 | crypto_test_SOURCES = ../auto_tests/crypto_test.c |
25 | 28 | ||
26 | crypto_test_CFLAGS = $(LIBSODIUM_CFLAGS) \ | 29 | crypto_test_CFLAGS = $(AUTOTEST_CFLAGS) |
27 | $(NACL_CFLAGS) \ | ||
28 | $(CHECK_CFLAGS) | ||
29 | 30 | ||
30 | crypto_test_LDADD = $(LIBSODIUM_LDFLAGS) \ | 31 | crypto_test_LDADD = $(AUTOTEST_LDADD) |
31 | $(NACL_LDFLAGS) \ | ||
32 | libtoxcore.la \ | ||
33 | $(LIBSODIUM_LIBS) \ | ||
34 | $(NACL_LIBS) \ | ||
35 | $(CHECK_LIBS) | ||
36 | 32 | ||
37 | network_test_SOURCES = \ | ||
38 | ../auto_tests/network_test.c | ||
39 | 33 | ||
40 | network_test_CFLAGS = \ | 34 | network_test_SOURCES = ../auto_tests/network_test.c |
41 | $(LIBSODIUM_CFLAGS) \ | 35 | |
42 | $(NACL_CFLAGS) \ | 36 | network_test_CFLAGS = $(AUTOTEST_CFLAGS) |
43 | $(CHECK_CFLAGS) | 37 | |
38 | network_test_LDADD = $(AUTOTEST_LDADD) | ||
44 | 39 | ||
45 | network_test_LDADD = \ | ||
46 | $(LIBSODIUM_LDFLAGS) \ | ||
47 | $(NACL_LDFLAGS) \ | ||
48 | libtoxcore.la \ | ||
49 | $(LIBSODIUM_LIBS) \ | ||
50 | $(NACL_LIBS) \ | ||
51 | $(CHECK_LIBS) | ||
52 | 40 | ||
53 | endif | 41 | endif |
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 | |||
16 | START_TEST(test_creativetestnamegoeshere) | ||
17 | { | ||
18 | uint8_t test = 0; | ||
19 | ck_assert_msg(test == 0, "test: expected result 0, got %u.", test); | ||
20 | } | ||
21 | END_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 | |||
29 | Suite *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 | |||
38 | int 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 | ||
46 | Problems with this: People don't always have at least one online friend. | 46 | Problems with this: People don't always have at least one online friend. |
47 | 47 | ||
48 | 2. ... | 48 | 2. Pick random nodes (add ourselves some random (fake) friends to increase the |
49 | pool of available nodes) and make then send requests to other nodes, the | ||
50 | response is then relayed back to us and compared to how the node should have | ||
51 | behaved. If the node is found to be behaving correctly, it is set as trusted. | ||
52 | Only trusted nodes are sent in send node packets, that is unless the exact node | ||
53 | being queried for in the getnode packet is present, it will be sent in the | ||
54 | sendnode packet even if it is not trusted. | ||
55 | |||
56 | The hypothesis is that if to be part of the network nodes have to behave | ||
57 | correctly 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 @@ | |||
1 | A/V API reference | 1 | #A/V API reference |
2 | 2 | ||
3 | Take toxmsi/phone.c as a reference | 3 | ##Take toxmsi/phone.c as a reference |
4 | 4 | ||
5 | Initialization: | 5 | ###Initialization: |
6 | 6 | ||
7 | ``` | ||
7 | phone_t* initPhone(uint16_t _listen_port, uint16_t _send_port); | 8 | phone_t* initPhone(uint16_t _listen_port, uint16_t _send_port); |
9 | ``` | ||
10 | |||
8 | function initializes sample phone. _listen_port and _send_port are variables only meant | 11 | function initializes sample phone. _listen_port and _send_port are variables only meant |
9 | for local testing. You will not have to do anything regarding to that since | 12 | for local testing. You will not have to do anything regarding to that since |
10 | everything will be started within a mesenger. | 13 | everything will be started within a mesenger. |
@@ -13,17 +16,22 @@ everything will be started within a mesenger. | |||
13 | Phone requires one msi session and two rtp sessions ( one for audio and one for | 16 | Phone requires one msi session and two rtp sessions ( one for audio and one for |
14 | video ). | 17 | video ). |
15 | 18 | ||
19 | ``` | ||
16 | msi_session_t* msi_init_session( void* _core_handler, const uint8_t* _user_agent ); | 20 | msi_session_t* msi_init_session( void* _core_handler, const uint8_t* _user_agent ); |
21 | ``` | ||
17 | 22 | ||
18 | initializes msi session. | 23 | initializes msi session. |
19 | Params: | 24 | Params: |
25 | |||
26 | ``` | ||
20 | void* _core_handler - pointer to an object handling networking, | 27 | void* _core_handler - pointer to an object handling networking, |
21 | const uint8_t* _user_agent - string describing phone client version. | 28 | const uint8_t* _user_agent - string describing phone client version. |
29 | ``` | ||
22 | 30 | ||
23 | Return value: | 31 | Return value: |
24 | msi_session_t* - pointer to a newly created msi session handler. | 32 | msi_session_t* - pointer to a newly created msi session handler. |
25 | 33 | ||
26 | msi_session_t reference: | 34 | ###msi_session_t reference: |
27 | 35 | ||
28 | How to handle msi session: | 36 | How to handle msi session: |
29 | Controling is done via callbacks and action handlers. | 37 | 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 | |||
32 | directly from event loop. You can find examples in phone.c. | 40 | directly from event loop. You can find examples in phone.c. |
33 | 41 | ||
34 | Register callbacks: | 42 | Register callbacks: |
43 | ``` | ||
35 | void msi_register_callback_call_started ( MCALLBACK ); | 44 | void msi_register_callback_call_started ( MCALLBACK ); |
36 | void msi_register_callback_call_canceled ( MCALLBACK ); | 45 | void msi_register_callback_call_canceled ( MCALLBACK ); |
37 | void msi_register_callback_call_rejected ( MCALLBACK ); | 46 | void msi_register_callback_call_rejected ( MCALLBACK ); |
@@ -44,52 +53,72 @@ void msi_register_callback_recv_ending ( MCALLBACK ); | |||
44 | void msi_register_callback_recv_error ( MCALLBACK ); | 53 | void msi_register_callback_recv_error ( MCALLBACK ); |
45 | 54 | ||
46 | void msi_register_callback_requ_timeout ( MCALLBACK ); | 55 | void msi_register_callback_requ_timeout ( MCALLBACK ); |
56 | ``` | ||
47 | 57 | ||
48 | MCALLBACK is defined as: void (*callback) (void* _arg) | 58 | MCALLBACK is defined as: void (*callback) (void* _arg) |
49 | msi_session_t* handler is being thrown as _arg so you can use that and _agent_handler to get to your own phone handler | 59 | msi_session_t* handler is being thrown as \_arg so you can use that and \_agent_handler to get to your own phone handler |
50 | directly from callback. | 60 | directly from callback. |
51 | 61 | ||
52 | 62 | ||
53 | Actions: | 63 | Actions: |
64 | |||
65 | ``` | ||
54 | int msi_invite ( msi_session_t* _session, call_type _call_type, uint32_t _timeoutms ); | 66 | int msi_invite ( msi_session_t* _session, call_type _call_type, uint32_t _timeoutms ); |
67 | ``` | ||
68 | |||
55 | Sends call invite. Before calling/sending invite msi_session_t::_friend_id is needed to be set or else | 69 | Sends call invite. Before calling/sending invite msi_session_t::_friend_id is needed to be set or else |
56 | it will not work. _call_type is type of the call ( Audio/Video ) and _timeoutms is how long | 70 | it will not work. _call_type is type of the call ( Audio/Video ) and _timeoutms is how long |
57 | will poll wait until request is terminated. | 71 | will poll wait until request is terminated. |
58 | 72 | ||
73 | ``` | ||
59 | int msi_hangup ( msi_session_t* _session ); | 74 | int msi_hangup ( msi_session_t* _session ); |
75 | ``` | ||
60 | Hangs up active call | 76 | Hangs up active call |
61 | 77 | ||
78 | ``` | ||
62 | int msi_answer ( msi_session_t* _session, call_type _call_type ); | 79 | int msi_answer ( msi_session_t* _session, call_type _call_type ); |
80 | ``` | ||
63 | Answer incomming call. _call_type set's callee call type. | 81 | Answer incomming call. _call_type set's callee call type. |
64 | 82 | ||
83 | ``` | ||
65 | int msi_cancel ( msi_session_t* _session ); | 84 | int msi_cancel ( msi_session_t* _session ); |
85 | ``` | ||
66 | Cancel current request. | 86 | Cancel current request. |
67 | 87 | ||
88 | ``` | ||
68 | int msi_reject ( msi_session_t* _session ); | 89 | int msi_reject ( msi_session_t* _session ); |
90 | ``` | ||
69 | Reject incomming call. | 91 | Reject incomming call. |
70 | 92 | ||
71 | 93 | ||
94 | ###Now for rtp: | ||
72 | 95 | ||
73 | |||
74 | Now for rtp: | ||
75 | You will need 2 sessions; one for audio one for video. | 96 | You will need 2 sessions; one for audio one for video. |
76 | You start them with: | 97 | You start them with: |
77 | 98 | ``` | |
78 | rtp_session_t* rtp_init_session ( int _max_users, int _multi_session ); | 99 | rtp_session_t* rtp_init_session ( int _max_users, int _multi_session ); |
100 | ``` | ||
79 | 101 | ||
80 | Params: | 102 | Params: |
103 | ``` | ||
81 | int _max_users - max users. -1 if undefined | 104 | int _max_users - max users. -1 if undefined |
82 | int _multi_session - any positive number means uses multi session; -1 if not. | 105 | int _multi_session - any positive number means uses multi session; -1 if not. |
106 | ``` | ||
83 | 107 | ||
84 | Return value: | 108 | Return value: |
109 | ``` | ||
85 | rtp_session_t* - pointer to a newly created rtp session handler. | 110 | rtp_session_t* - pointer to a newly created rtp session handler. |
111 | ``` | ||
86 | 112 | ||
87 | How to handle rtp session: | 113 | ###How to handle rtp session: |
88 | Take a look at | 114 | Take a look at |
115 | ``` | ||
89 | void* phone_handle_media_transport_poll ( void* _hmtc_args_p ) in phone.c | 116 | void* phone_handle_media_transport_poll ( void* _hmtc_args_p ) in phone.c |
117 | ``` | ||
90 | on example. Basically what you do is just receive a message via: | 118 | on example. Basically what you do is just receive a message via: |
91 | 119 | ``` | |
92 | struct rtp_msg_s* rtp_recv_msg ( rtp_session_t* _session ); | 120 | struct rtp_msg_s* rtp_recv_msg ( rtp_session_t* _session ); |
121 | ``` | ||
93 | 122 | ||
94 | and then you use payload within the rtp_msg_s struct. Don't forget to deallocate it with: | 123 | and then you use payload within the rtp_msg_s struct. Don't forget to deallocate it with: |
95 | void rtp_free_msg ( rtp_session_t* _session, struct rtp_msg_s* _msg ); | 124 | 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. | |||
98 | When you capture and encode a payload you want to send it ( obviously ). | 127 | When you capture and encode a payload you want to send it ( obviously ). |
99 | 128 | ||
100 | first create a new message with: | 129 | first create a new message with: |
130 | ``` | ||
101 | struct rtp_msg_s* rtp_msg_new ( rtp_session_t* _session, const uint8_t* _data, uint32_t _length ); | 131 | struct rtp_msg_s* rtp_msg_new ( rtp_session_t* _session, const uint8_t* _data, uint32_t _length ); |
132 | ``` | ||
102 | 133 | ||
103 | and then send it with: | 134 | and then send it with: |
135 | ``` | ||
104 | int rtp_send_msg ( rtp_session_t* _session, struct rtp_msg_s* _msg, void* _core_handler ); | 136 | int 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: | |
110 | A/V initialization: | 143 | ``` |
111 | |||
112 | int init_receive_audio(codec_state *cs); | 144 | int init_receive_audio(codec_state *cs); |
113 | int init_receive_video(codec_state *cs); | 145 | int init_receive_video(codec_state *cs); |
114 | Initialises the A/V decoders. On failure it will print the reason and return 0. On success it will return 1. | 146 | 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); | |||
122 | 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. | 154 | 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. |
123 | In the future, VP8 should be used directly and ffmpeg should be dropped from the dependencies. | 155 | In the future, VP8 should be used directly and ffmpeg should be dropped from the dependencies. |
124 | The variable bps is the required bitrate in bits per second. | 156 | The variable bps is the required bitrate in bits per second. |
157 | ``` | ||
125 | 158 | ||
126 | 159 | ||
127 | 160 | ###A/V encoding/decoding: | |
128 | A/V encoding/decoding: | 161 | ``` |
129 | |||
130 | void *encode_video_thread(void *arg); | 162 | void *encode_video_thread(void *arg); |
163 | ``` | ||
131 | Spawns the video encoding thread. The argument should hold a pointer to a codec_state. | 164 | Spawns the video encoding thread. The argument should hold a pointer to a codec_state. |
132 | This function should only be called if video encoding is supported (when init_send_video returns 1). | 165 | This function should only be called if video encoding is supported (when init_send_video returns 1). |
133 | Each video frame gets encoded into a packet, which is sent via RTP. Every 60 frames a new bidirectional interframe is encoded. | 166 | Each video frame gets encoded into a packet, which is sent via RTP. Every 60 frames a new bidirectional interframe is encoded. |
134 | 167 | ``` | |
135 | void *encode_audio_thread(void *arg); | 168 | void *encode_audio_thread(void *arg); |
169 | ``` | ||
136 | Spawns the audio encoding thread. The argument should hold a pointer to a codec_state. | 170 | Spawns the audio encoding thread. The argument should hold a pointer to a codec_state. |
137 | This function should only be called if audio encoding is supported (when init_send_audio returns 1). | 171 | This function should only be called if audio encoding is supported (when init_send_audio returns 1). |
138 | 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. | 172 | 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. |
139 | 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. | 173 | 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. |
140 | 174 | ``` | |
141 | int video_decoder_refresh(codec_state *cs, int width, int height); | 175 | int video_decoder_refresh(codec_state *cs, int width, int height); |
176 | ``` | ||
142 | 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. | 177 | 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. |
143 | 178 | ||
179 | ``` | ||
144 | void *decode_video_thread(void *arg); | 180 | void *decode_video_thread(void *arg); |
181 | ``` | ||
145 | 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. | 182 | 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. |
146 | 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. | 183 | 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. |
147 | 184 | ``` | |
148 | void *decode_audio_thread(void *arg); | 185 | void *decode_audio_thread(void *arg); |
186 | ``` | ||
149 | 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. | 187 | 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. |
150 | 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. | 188 | 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. |
151 | Audio is played on the default OpenAL output device. | 189 | Audio is played on the default OpenAL output device. |
@@ -153,4 +191,4 @@ Audio is played on the default OpenAL output device. | |||
153 | 191 | ||
154 | If you have any more qustions/bug reports/feature request contact the following users on the irc channel #tox-dev on irc.freenode.net: | 192 | If you have any more qustions/bug reports/feature request contact the following users on the irc channel #tox-dev on irc.freenode.net: |
155 | For RTP and MSI: mannol | 193 | For RTP and MSI: mannol |
156 | For audio and video: Martijnvdc \ No newline at end of file | 194 | For 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. */ |
815 | static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, Node_format *list, uint16_t num_nodes); | 815 | static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, Node_format *list, uint16_t num_nodes); |
816 | 816 | ||
817 | static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length) | 817 | static 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 | |||
861 | static 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 | ||
879 | static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet, uint32_t length) | 898 | static 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 | */ | ||
874 | static 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 | */ |
874 | static uint8_t group_invited(Messenger *m, int friendnumber, int groupnumber) | 885 | static 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. */ |
56 | enum { | 59 | enum { |
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 | ||
153 | typedef struct Messenger { | 158 | typedef 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 | ||
293 | static int send_sendnodes(Group_Chat *chat, IP_Port ip_port, int peernum, uint64_t pingid) | 296 | 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 | |||
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 | ||
314 | static int handle_getnodes(Group_Chat *chat, IP_Port source, int peernum, uint8_t *data, uint32_t len) | 317 | 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) | |||
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 | ||
513 | uint32_t group_sendmessage(Group_Chat *chat, uint8_t *message, uint32_t length) | 519 | uint32_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 | ||
518 | uint32_t group_newpeer(Group_Chat *chat, uint8_t *client_id) | 524 | uint32_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 | ||
524 | void callback_groupmessage(Group_Chat *chat, void (*function)(Group_Chat *chat, int, uint8_t *, uint16_t, void *), | 530 | 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) | |||
561 | } | 567 | } |
562 | } | 568 | } |
563 | 569 | ||
570 | /* Interval in seconds to send ping messages */ | ||
571 | #define GROUP_PING_INTERVAL 30 | ||
572 | |||
573 | static 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 | |||
581 | static 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 | |||
564 | void do_groupchat(Group_Chat *chat) | 592 | void 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 | ||
570 | void kill_groupchat(Group_Chat *chat) | 601 | void 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 | ||
117 | static 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 | */ | ||
123 | static 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, | |||
521 | void tox_bootstrap_from_ip(Tox *tox, tox_IP_Port ip_port, uint8_t *public_key); | 521 | void 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) | |||
164 | void loglog(char *text) | 166 | void 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 | ||