diff options
-rw-r--r-- | auto_tests/Makefile.inc | 52 | ||||
-rw-r--r-- | auto_tests/toxav_basic_test.c | 131 | ||||
-rw-r--r-- | auto_tests/toxav_many.c | 120 | ||||
-rw-r--r-- | configure.ac | 52 | ||||
-rwxr-xr-x | toxav/msi.c | 708 | ||||
-rwxr-xr-x | toxav/msi.h | 66 | ||||
-rwxr-xr-x | toxav/toxav.c | 200 | ||||
-rwxr-xr-x | toxav/toxav.h | 44 | ||||
-rw-r--r-- | toxcore/DHT.c | 67 | ||||
-rw-r--r-- | toxcore/Makefile.inc | 2 | ||||
-rw-r--r-- | toxcore/Messenger.c | 46 | ||||
-rw-r--r-- | toxcore/assoc.c | 89 | ||||
-rw-r--r-- | toxcore/assoc.h | 2 | ||||
-rw-r--r-- | toxcore/logger.c | 159 | ||||
-rw-r--r-- | toxcore/logger.h | 86 | ||||
-rw-r--r-- | toxcore/network.c | 153 | ||||
-rw-r--r-- | toxcore/tox.c | 2 | ||||
-rw-r--r-- | toxcore/util.c | 84 | ||||
-rw-r--r-- | toxcore/util.h | 7 |
19 files changed, 1280 insertions, 790 deletions
diff --git a/auto_tests/Makefile.inc b/auto_tests/Makefile.inc index a8771695..a29c1bec 100644 --- a/auto_tests/Makefile.inc +++ b/auto_tests/Makefile.inc | |||
@@ -1,8 +1,10 @@ | |||
1 | if BUILD_TESTS | 1 | if BUILD_TESTS |
2 | 2 | ||
3 | TESTS = messenger_autotest crypto_test network_test assoc_test onion_test TCP_test tox_test | 3 | #TESTS = messenger_autotest crypto_test network_test assoc_test onion_test TCP_test tox_test |
4 | check_PROGRAMS = messenger_autotest crypto_test network_test assoc_test onion_test TCP_test tox_test | 4 | #check_PROGRAMS = messenger_autotest crypto_test network_test assoc_test onion_test TCP_test tox_test |
5 | 5 | ||
6 | TESTS = toxav_basic_test | ||
7 | check_PROGRAMS = toxav_basic_test | ||
6 | 8 | ||
7 | AUTOTEST_CFLAGS = \ | 9 | AUTOTEST_CFLAGS = \ |
8 | $(LIBSODIUM_CFLAGS) \ | 10 | $(LIBSODIUM_CFLAGS) \ |
@@ -19,58 +21,58 @@ AUTOTEST_LDADD = \ | |||
19 | 21 | ||
20 | 22 | ||
21 | if BUILD_AV | 23 | if BUILD_AV |
22 | TESTS += toxav_basic_test | 24 | #TESTS += toxav_basic_test |
23 | check_PROGRAMS += toxav_basic_test | 25 | #check_PROGRAMS += toxav_basic_test |
24 | AUTOTEST_LDADD += libtoxav.la | 26 | AUTOTEST_LDADD += libtoxav.la |
25 | endif | 27 | endif |
26 | 28 | ||
27 | messenger_autotest_SOURCES = ../auto_tests/messenger_test.c | 29 | #messenger_autotest_SOURCES = ../auto_tests/messenger_test.c |
28 | 30 | ||
29 | messenger_autotest_CFLAGS = $(AUTOTEST_CFLAGS) | 31 | #messenger_autotest_CFLAGS = $(AUTOTEST_CFLAGS) |
30 | 32 | ||
31 | messenger_autotest_LDADD = $(AUTOTEST_LDADD) | 33 | #messenger_autotest_LDADD = $(AUTOTEST_LDADD) |
32 | 34 | ||
33 | 35 | ||
34 | crypto_test_SOURCES = ../auto_tests/crypto_test.c | 36 | #crypto_test_SOURCES = ../auto_tests/crypto_test.c |
35 | 37 | ||
36 | crypto_test_CFLAGS = $(AUTOTEST_CFLAGS) | 38 | #crypto_test_CFLAGS = $(AUTOTEST_CFLAGS) |
37 | 39 | ||
38 | crypto_test_LDADD = $(AUTOTEST_LDADD) | 40 | #crypto_test_LDADD = $(AUTOTEST_LDADD) |
39 | 41 | ||
40 | 42 | ||
41 | network_test_SOURCES = ../auto_tests/network_test.c | 43 | #network_test_SOURCES = ../auto_tests/network_test.c |
42 | 44 | ||
43 | network_test_CFLAGS = $(AUTOTEST_CFLAGS) | 45 | #network_test_CFLAGS = $(AUTOTEST_CFLAGS) |
44 | 46 | ||
45 | network_test_LDADD = $(AUTOTEST_LDADD) | 47 | #network_test_LDADD = $(AUTOTEST_LDADD) |
46 | 48 | ||
47 | 49 | ||
48 | assoc_test_SOURCES = ../auto_tests/assoc_test.c | 50 | #assoc_test_SOURCES = ../auto_tests/assoc_test.c |
49 | 51 | ||
50 | assoc_test_CFLAGS = $(AUTOTEST_CFLAGS) | 52 | #assoc_test_CFLAGS = $(AUTOTEST_CFLAGS) |
51 | 53 | ||
52 | assoc_test_LDADD = $(AUTOTEST_LDADD) | 54 | #assoc_test_LDADD = $(AUTOTEST_LDADD) |
53 | 55 | ||
54 | 56 | ||
55 | onion_test_SOURCES = ../auto_tests/onion_test.c | 57 | #onion_test_SOURCES = ../auto_tests/onion_test.c |
56 | 58 | ||
57 | onion_test_CFLAGS = $(AUTOTEST_CFLAGS) | 59 | #onion_test_CFLAGS = $(AUTOTEST_CFLAGS) |
58 | 60 | ||
59 | onion_test_LDADD = $(AUTOTEST_LDADD) | 61 | #onion_test_LDADD = $(AUTOTEST_LDADD) |
60 | 62 | ||
61 | 63 | ||
62 | TCP_test_SOURCES = ../auto_tests/TCP_test.c | 64 | #TCP_test_SOURCES = ../auto_tests/TCP_test.c |
63 | 65 | ||
64 | TCP_test_CFLAGS = $(AUTOTEST_CFLAGS) | 66 | #TCP_test_CFLAGS = $(AUTOTEST_CFLAGS) |
65 | 67 | ||
66 | TCP_test_LDADD = $(AUTOTEST_LDADD) | 68 | #TCP_test_LDADD = $(AUTOTEST_LDADD) |
67 | 69 | ||
68 | 70 | ||
69 | tox_test_SOURCES = ../auto_tests/tox_test.c | 71 | #tox_test_SOURCES = ../auto_tests/tox_test.c |
70 | 72 | ||
71 | tox_test_CFLAGS = $(AUTOTEST_CFLAGS) | 73 | #tox_test_CFLAGS = $(AUTOTEST_CFLAGS) |
72 | 74 | ||
73 | tox_test_LDADD = $(AUTOTEST_LDADD) | 75 | #tox_test_LDADD = $(AUTOTEST_LDADD) |
74 | 76 | ||
75 | 77 | ||
76 | if BUILD_AV | 78 | if BUILD_AV |
diff --git a/auto_tests/toxav_basic_test.c b/auto_tests/toxav_basic_test.c index f337217c..affe4dd2 100644 --- a/auto_tests/toxav_basic_test.c +++ b/auto_tests/toxav_basic_test.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <assert.h> | 12 | #include <assert.h> |
13 | 13 | ||
14 | #include "../toxcore/tox.h" | 14 | #include "../toxcore/tox.h" |
15 | #include "../toxcore/logger.h" | ||
15 | #include "../toxav/toxav.h" | 16 | #include "../toxav/toxav.h" |
16 | 17 | ||
17 | #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) | 18 | #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) |
@@ -22,6 +23,7 @@ | |||
22 | #endif | 23 | #endif |
23 | 24 | ||
24 | 25 | ||
26 | |||
25 | typedef enum _CallStatus { | 27 | typedef enum _CallStatus { |
26 | none, | 28 | none, |
27 | InCall, | 29 | InCall, |
@@ -36,6 +38,7 @@ typedef struct _Party { | |||
36 | CallStatus status; | 38 | CallStatus status; |
37 | ToxAv *av; | 39 | ToxAv *av; |
38 | time_t *CallStarted; | 40 | time_t *CallStarted; |
41 | int call_index; | ||
39 | } Party; | 42 | } Party; |
40 | 43 | ||
41 | typedef struct _Status { | 44 | typedef struct _Status { |
@@ -45,42 +48,41 @@ typedef struct _Status { | |||
45 | 48 | ||
46 | void accept_friend_request(Tox *m, uint8_t *public_key, uint8_t *data, uint16_t length, void *userdata) | 49 | void accept_friend_request(Tox *m, uint8_t *public_key, uint8_t *data, uint16_t length, void *userdata) |
47 | { | 50 | { |
48 | if (length == 15 && memcmp("ILIKESMALLTITS", data, 15) == 0) { | 51 | if (length == 7 && memcmp("gentoo", data, 7) == 0) { |
49 | tox_add_friend_norequest(m, public_key); | 52 | tox_add_friend_norequest(m, public_key); |
50 | } | 53 | } |
51 | } | 54 | } |
52 | 55 | ||
53 | 56 | ||
54 | /******************************************************************************/ | 57 | /******************************************************************************/ |
55 | void callback_recv_invite ( void *_arg ) | 58 | void callback_recv_invite ( uint32_t call_index, void *_arg ) |
56 | { | 59 | { |
57 | Status *cast = _arg; | 60 | Status *cast = _arg; |
58 | 61 | ||
59 | /* Bob always receives invite */ | 62 | /* Bob always receives invite */ |
60 | cast->Bob.status = Ringing; | 63 | cast->Bob.status = Ringing; |
64 | cast->Bob.call_index = call_index; | ||
61 | } | 65 | } |
62 | void callback_recv_ringing ( void *_arg ) | 66 | void callback_recv_ringing ( uint32_t call_index, void *_arg ) |
63 | { | 67 | { |
64 | Status *cast = _arg; | 68 | Status *cast = _arg; |
65 | 69 | ||
66 | /* Alice always sends invite */ | 70 | /* Alice always sends invite */ |
67 | cast->Alice.status = Ringing; | 71 | cast->Alice.status = Ringing; |
68 | } | 72 | } |
69 | void callback_recv_starting ( void *_arg ) | 73 | void callback_recv_starting ( uint32_t call_index, void *_arg ) |
70 | { | 74 | { |
71 | Status *cast = _arg; | 75 | Status *cast = _arg; |
72 | 76 | ||
73 | /* Alice always sends invite */ | 77 | /* Alice always sends invite */ |
74 | printf("Call started on Alice side...\n"); | 78 | printf("Call started on Alice side...\n"); |
75 | cast->Alice.status = InCall; | 79 | cast->Alice.status = InCall; |
76 | toxav_prepare_transmission(cast->Alice.av, 1); | 80 | toxav_prepare_transmission(cast->Alice.av, call_index, 1); |
77 | } | 81 | } |
78 | void callback_recv_ending ( void *_arg ) | 82 | void callback_recv_ending ( uint32_t call_index, void *_arg ) |
79 | { | 83 | { |
80 | Status *cast = _arg; | 84 | Status *cast = _arg; |
81 | 85 | ||
82 | |||
83 | |||
84 | if ( cast->Alice.status == Rejected) { | 86 | if ( cast->Alice.status == Rejected) { |
85 | printf ( "Call ended for Bob!\n" ); | 87 | printf ( "Call ended for Bob!\n" ); |
86 | cast->Bob.status = Ended; | 88 | cast->Bob.status = Ended; |
@@ -90,28 +92,28 @@ void callback_recv_ending ( void *_arg ) | |||
90 | } | 92 | } |
91 | } | 93 | } |
92 | 94 | ||
93 | void callback_recv_error ( void *_arg ) | 95 | void callback_recv_error ( uint32_t call_index, void *_arg ) |
94 | { | 96 | { |
95 | ck_assert_msg(0, "AV internal error"); | 97 | ck_assert_msg(0, "AV internal error"); |
96 | } | 98 | } |
97 | 99 | ||
98 | void callback_call_started ( void *_arg ) | 100 | void callback_call_started ( uint32_t call_index, void *_arg ) |
99 | { | 101 | { |
100 | Status *cast = _arg; | 102 | Status *cast = _arg; |
101 | 103 | ||
102 | /* Alice always sends invite */ | 104 | /* Alice always sends invite */ |
103 | printf("Call started on Bob side...\n"); | 105 | printf("Call started on Bob side...\n"); |
104 | cast->Bob.status = InCall; | 106 | cast->Bob.status = InCall; |
105 | toxav_prepare_transmission(cast->Bob.av, 1); | 107 | toxav_prepare_transmission(cast->Bob.av, call_index, 1); |
106 | } | 108 | } |
107 | void callback_call_canceled ( void *_arg ) | 109 | void callback_call_canceled ( uint32_t call_index, void *_arg ) |
108 | { | 110 | { |
109 | Status *cast = _arg; | 111 | Status *cast = _arg; |
110 | 112 | ||
111 | printf ( "Call Canceled for Bob!\n" ); | 113 | printf ( "Call Canceled for Bob!\n" ); |
112 | cast->Bob.status = Cancel; | 114 | cast->Bob.status = Cancel; |
113 | } | 115 | } |
114 | void callback_call_rejected ( void *_arg ) | 116 | void callback_call_rejected ( uint32_t call_index, void *_arg ) |
115 | { | 117 | { |
116 | Status *cast = _arg; | 118 | Status *cast = _arg; |
117 | 119 | ||
@@ -120,7 +122,7 @@ void callback_call_rejected ( void *_arg ) | |||
120 | /* If Bob rejects, call is ended for alice and she sends ending */ | 122 | /* If Bob rejects, call is ended for alice and she sends ending */ |
121 | cast->Alice.status = Rejected; | 123 | cast->Alice.status = Rejected; |
122 | } | 124 | } |
123 | void callback_call_ended ( void *_arg ) | 125 | void callback_call_ended ( uint32_t call_index, void *_arg ) |
124 | { | 126 | { |
125 | Status *cast = _arg; | 127 | Status *cast = _arg; |
126 | 128 | ||
@@ -128,7 +130,7 @@ void callback_call_ended ( void *_arg ) | |||
128 | cast->Bob.status = Ended; | 130 | cast->Bob.status = Ended; |
129 | } | 131 | } |
130 | 132 | ||
131 | void callback_requ_timeout ( void *_arg ) | 133 | void callback_requ_timeout ( uint32_t call_index, void *_arg ) |
132 | { | 134 | { |
133 | ck_assert_msg(0, "No answer!"); | 135 | ck_assert_msg(0, "No answer!"); |
134 | } | 136 | } |
@@ -142,9 +144,9 @@ void callback_requ_timeout ( void *_arg ) | |||
142 | tox_do(bootstrap_node); tox_do(Alice); tox_do(Bob); \ | 144 | tox_do(bootstrap_node); tox_do(Alice); tox_do(Bob); \ |
143 | switch ( step ) {\ | 145 | switch ( step ) {\ |
144 | case 0: /* Alice */ printf("Alice is calling...\n");\ | 146 | case 0: /* Alice */ printf("Alice is calling...\n");\ |
145 | toxav_call(status_control.Alice.av, 0, AliceCallType, 10); step++; break;\ | 147 | toxav_call(status_control.Alice.av, &status_control.Alice.call_index, 0, AliceCallType, 10); step++; break;\ |
146 | case 1: /* Bob */ if (status_control.Bob.status == Ringing) { printf("Bob answers...\n");\ | 148 | case 1: /* Bob */ if (status_control.Bob.status == Ringing) { printf("Bob answers...\n");\ |
147 | cur_time = time(NULL); toxav_answer(status_control.Bob.av, BobCallType); step++; } break; \ | 149 | cur_time = time(NULL); toxav_answer(status_control.Bob.av, status_control.Bob.call_index, BobCallType); step++; } break; \ |
148 | case 2: /* Rtp transmission */ \ | 150 | case 2: /* Rtp transmission */ \ |
149 | if (status_control.Bob.status == InCall && status_control.Alice.status == InCall) | 151 | if (status_control.Bob.status == InCall && status_control.Alice.status == InCall) |
150 | 152 | ||
@@ -153,7 +155,7 @@ void callback_requ_timeout ( void *_arg ) | |||
153 | case 3: /* Wait for Both to have status ended */\ | 155 | case 3: /* Wait for Both to have status ended */\ |
154 | if (status_control.Alice.status == Ended && status_control.Bob.status == Ended) running = 0; break; } c_sleep(20); } } printf("\n"); | 156 | if (status_control.Alice.status == Ended && status_control.Bob.status == Ended) running = 0; break; } c_sleep(20); } } printf("\n"); |
155 | 157 | ||
156 | START_TEST(test_AV) | 158 | START_TEST(test_AV_flows) |
157 | { | 159 | { |
158 | long long unsigned int cur_time = time(NULL); | 160 | long long unsigned int cur_time = time(NULL); |
159 | Tox *bootstrap_node = tox_new(0); | 161 | Tox *bootstrap_node = tox_new(0); |
@@ -166,7 +168,7 @@ START_TEST(test_AV) | |||
166 | tox_callback_friend_request(Alice, accept_friend_request, &to_compare); | 168 | tox_callback_friend_request(Alice, accept_friend_request, &to_compare); |
167 | uint8_t address[TOX_FRIEND_ADDRESS_SIZE]; | 169 | uint8_t address[TOX_FRIEND_ADDRESS_SIZE]; |
168 | tox_get_address(Alice, address); | 170 | tox_get_address(Alice, address); |
169 | int test = tox_add_friend(Bob, address, (uint8_t *)"ILIKESMALLTITS", 15); | 171 | int test = tox_add_friend(Bob, address, (uint8_t *)"gentoo", 7); |
170 | 172 | ||
171 | ck_assert_msg(test == 0, "Failed to add friend error code: %i", test); | 173 | ck_assert_msg(test == 0, "Failed to add friend error code: %i", test); |
172 | 174 | ||
@@ -195,8 +197,8 @@ START_TEST(test_AV) | |||
195 | muhcaps.video_height = muhcaps.video_width = 128; | 197 | muhcaps.video_height = muhcaps.video_width = 128; |
196 | 198 | ||
197 | Status status_control = { | 199 | Status status_control = { |
198 | {none, toxav_new(Alice, &muhcaps), NULL}, | 200 | {none, toxav_new(Alice, &muhcaps, 1), NULL}, |
199 | {none, toxav_new(Bob, &muhcaps), NULL}, | 201 | {none, toxav_new(Bob, &muhcaps, 1), NULL}, |
200 | }; | 202 | }; |
201 | 203 | ||
202 | 204 | ||
@@ -235,23 +237,23 @@ START_TEST(test_AV) | |||
235 | */ | 237 | */ |
236 | CALL_AND_START_LOOP(TypeAudio, TypeAudio) { | 238 | CALL_AND_START_LOOP(TypeAudio, TypeAudio) { |
237 | /* Both send */ | 239 | /* Both send */ |
238 | toxav_send_audio(status_control.Alice.av, sample_payload, 10); | 240 | toxav_send_audio(status_control.Alice.av, status_control.Alice.call_index, sample_payload, 10); |
239 | toxav_send_audio(status_control.Bob.av, sample_payload, 10); | 241 | toxav_send_audio(status_control.Bob.av, status_control.Bob.call_index, sample_payload, 10); |
240 | 242 | ||
241 | /* Both receive */ | 243 | /* Both receive */ |
242 | int16_t storage[10]; | 244 | int16_t storage[10]; |
243 | int recved; | 245 | int recved; |
244 | 246 | ||
245 | /* Payload from Alice */ | 247 | /* Payload from Bob */ |
246 | recved = toxav_recv_audio(status_control.Alice.av, 10, storage); | 248 | recved = toxav_recv_audio(status_control.Alice.av, status_control.Alice.call_index, 10, storage); |
247 | 249 | ||
248 | if ( recved ) { | 250 | if ( recved ) { |
249 | /*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Bob is invalid");*/ | 251 | /*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Bob is invalid");*/ |
250 | memset(storage, 0, 10); | 252 | memset(storage, 0, 10); |
251 | } | 253 | } |
252 | 254 | ||
253 | /* Payload from Bob */ | 255 | /* Payload from Alice */ |
254 | recved = toxav_recv_audio(status_control.Bob.av, 10, storage); | 256 | recved = toxav_recv_audio(status_control.Bob.av, status_control.Bob.call_index, 10, storage); |
255 | 257 | ||
256 | if ( recved ) { | 258 | if ( recved ) { |
257 | /*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Alice is invalid");*/ | 259 | /*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Alice is invalid");*/ |
@@ -259,11 +261,11 @@ START_TEST(test_AV) | |||
259 | 261 | ||
260 | if (time(NULL) - cur_time > 10) { /* Transmit for 10 seconds */ | 262 | if (time(NULL) - cur_time > 10) { /* Transmit for 10 seconds */ |
261 | step++; /* This terminates the loop */ | 263 | step++; /* This terminates the loop */ |
262 | toxav_kill_transmission(status_control.Alice.av); | 264 | toxav_kill_transmission(status_control.Alice.av, status_control.Alice.call_index); |
263 | toxav_kill_transmission(status_control.Bob.av); | 265 | toxav_kill_transmission(status_control.Bob.av, status_control.Bob.call_index); |
264 | 266 | ||
265 | /* Call over Alice hangs up */ | 267 | /* Call over Alice hangs up */ |
266 | toxav_hangup(status_control.Alice.av); | 268 | toxav_hangup(status_control.Alice.av, status_control.Alice.call_index); |
267 | } | 269 | } |
268 | } | 270 | } |
269 | TERMINATE_SCOPE() | 271 | TERMINATE_SCOPE() |
@@ -274,10 +276,10 @@ START_TEST(test_AV) | |||
274 | */ | 276 | */ |
275 | CALL_AND_START_LOOP(TypeAudio, TypeVideo) { | 277 | CALL_AND_START_LOOP(TypeAudio, TypeVideo) { |
276 | /* Both send */ | 278 | /* Both send */ |
277 | toxav_send_audio(status_control.Alice.av, sample_payload, 10); | 279 | toxav_send_audio(status_control.Alice.av, status_control.Alice.call_index, sample_payload, 10); |
278 | 280 | ||
279 | toxav_send_audio(status_control.Bob.av, sample_payload, 10); | 281 | toxav_send_audio(status_control.Bob.av, status_control.Bob.call_index, sample_payload, 10); |
280 | toxav_send_video(status_control.Bob.av, sample_image); | 282 | toxav_send_video(status_control.Bob.av, status_control.Bob.call_index, sample_image); |
281 | 283 | ||
282 | /* Both receive */ | 284 | /* Both receive */ |
283 | int16_t storage[10]; | 285 | int16_t storage[10]; |
@@ -285,7 +287,7 @@ START_TEST(test_AV) | |||
285 | int recved; | 287 | int recved; |
286 | 288 | ||
287 | /* Payload from Bob */ | 289 | /* Payload from Bob */ |
288 | recved = toxav_recv_audio(status_control.Alice.av, 10, storage); | 290 | recved = toxav_recv_audio(status_control.Alice.av, status_control.Alice.call_index, 10, storage); |
289 | 291 | ||
290 | if ( recved ) { | 292 | if ( recved ) { |
291 | /*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Bob is invalid");*/ | 293 | /*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Bob is invalid");*/ |
@@ -293,7 +295,7 @@ START_TEST(test_AV) | |||
293 | } | 295 | } |
294 | 296 | ||
295 | /* Video payload */ | 297 | /* Video payload */ |
296 | toxav_recv_video(status_control.Alice.av, &video_storage); | 298 | toxav_recv_video(status_control.Alice.av, status_control.Alice.call_index, &video_storage); |
297 | 299 | ||
298 | if ( video_storage ) { | 300 | if ( video_storage ) { |
299 | /*ck_assert_msg( memcmp(video_storage->planes[VPX_PLANE_Y], sample_payload, 10) == 0 || | 301 | /*ck_assert_msg( memcmp(video_storage->planes[VPX_PLANE_Y], sample_payload, 10) == 0 || |
@@ -305,7 +307,7 @@ START_TEST(test_AV) | |||
305 | 307 | ||
306 | 308 | ||
307 | /* Payload from Alice */ | 309 | /* Payload from Alice */ |
308 | recved = toxav_recv_audio(status_control.Bob.av, 10, storage); | 310 | recved = toxav_recv_audio(status_control.Bob.av, status_control.Bob.call_index, 10, storage); |
309 | 311 | ||
310 | if ( recved ) { | 312 | if ( recved ) { |
311 | /*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Alice is invalid");*/ | 313 | /*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Alice is invalid");*/ |
@@ -313,11 +315,11 @@ START_TEST(test_AV) | |||
313 | 315 | ||
314 | if (time(NULL) - cur_time > 10) { /* Transmit for 10 seconds */ | 316 | if (time(NULL) - cur_time > 10) { /* Transmit for 10 seconds */ |
315 | step++; /* This terminates the loop */ | 317 | step++; /* This terminates the loop */ |
316 | toxav_kill_transmission(status_control.Alice.av); | 318 | toxav_kill_transmission(status_control.Alice.av, status_control.Alice.call_index); |
317 | toxav_kill_transmission(status_control.Bob.av); | 319 | toxav_kill_transmission(status_control.Bob.av, status_control.Bob.call_index); |
318 | 320 | ||
319 | /* Call over Alice hangs up */ | 321 | /* Call over Alice hangs up */ |
320 | toxav_hangup(status_control.Alice.av); | 322 | toxav_hangup(status_control.Alice.av, status_control.Alice.call_index); |
321 | } | 323 | } |
322 | } | 324 | } |
323 | TERMINATE_SCOPE() | 325 | TERMINATE_SCOPE() |
@@ -328,11 +330,11 @@ START_TEST(test_AV) | |||
328 | */ | 330 | */ |
329 | CALL_AND_START_LOOP(TypeVideo, TypeVideo) { | 331 | CALL_AND_START_LOOP(TypeVideo, TypeVideo) { |
330 | /* Both send */ | 332 | /* Both send */ |
331 | toxav_send_audio(status_control.Alice.av, sample_payload, 10); | 333 | toxav_send_audio(status_control.Alice.av, status_control.Alice.call_index, sample_payload, 10); |
332 | toxav_send_video(status_control.Alice.av, sample_image); | 334 | toxav_send_video(status_control.Alice.av, status_control.Alice.call_index, sample_image); |
333 | 335 | ||
334 | toxav_send_audio(status_control.Bob.av, sample_payload, 10); | 336 | toxav_send_audio(status_control.Bob.av, status_control.Bob.call_index, sample_payload, 10); |
335 | toxav_send_video(status_control.Bob.av, sample_image); | 337 | toxav_send_video(status_control.Bob.av, status_control.Bob.call_index, sample_image); |
336 | 338 | ||
337 | /* Both receive */ | 339 | /* Both receive */ |
338 | int16_t storage[10]; | 340 | int16_t storage[10]; |
@@ -340,7 +342,7 @@ START_TEST(test_AV) | |||
340 | int recved; | 342 | int recved; |
341 | 343 | ||
342 | /* Payload from Bob */ | 344 | /* Payload from Bob */ |
343 | recved = toxav_recv_audio(status_control.Alice.av, 10, storage); | 345 | recved = toxav_recv_audio(status_control.Alice.av, status_control.Alice.call_index, 10, storage); |
344 | 346 | ||
345 | if ( recved ) { | 347 | if ( recved ) { |
346 | /*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Bob is invalid");*/ | 348 | /*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Bob is invalid");*/ |
@@ -348,7 +350,7 @@ START_TEST(test_AV) | |||
348 | } | 350 | } |
349 | 351 | ||
350 | /* Video payload */ | 352 | /* Video payload */ |
351 | toxav_recv_video(status_control.Alice.av, &video_storage); | 353 | toxav_recv_video(status_control.Alice.av, status_control.Alice.call_index, &video_storage); |
352 | 354 | ||
353 | if ( video_storage ) { | 355 | if ( video_storage ) { |
354 | /*ck_assert_msg( memcmp(video_storage->planes[VPX_PLANE_Y], sample_payload, 10) == 0 || | 356 | /*ck_assert_msg( memcmp(video_storage->planes[VPX_PLANE_Y], sample_payload, 10) == 0 || |
@@ -360,14 +362,14 @@ START_TEST(test_AV) | |||
360 | 362 | ||
361 | 363 | ||
362 | /* Payload from Alice */ | 364 | /* Payload from Alice */ |
363 | recved = toxav_recv_audio(status_control.Bob.av, 10, storage); | 365 | recved = toxav_recv_audio(status_control.Bob.av, status_control.Bob.call_index, 10, storage); |
364 | 366 | ||
365 | if ( recved ) { | 367 | if ( recved ) { |
366 | /*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Alice is invalid");*/ | 368 | /*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Alice is invalid");*/ |
367 | } | 369 | } |
368 | 370 | ||
369 | /* Video payload */ | 371 | /* Video payload */ |
370 | toxav_recv_video(status_control.Bob.av, &video_storage); | 372 | toxav_recv_video(status_control.Bob.av, status_control.Bob.call_index, &video_storage); |
371 | 373 | ||
372 | if ( video_storage ) { | 374 | if ( video_storage ) { |
373 | /*ck_assert_msg( memcmp(video_storage->planes[VPX_PLANE_Y], sample_payload, 10) == 0 || | 375 | /*ck_assert_msg( memcmp(video_storage->planes[VPX_PLANE_Y], sample_payload, 10) == 0 || |
@@ -378,11 +380,11 @@ START_TEST(test_AV) | |||
378 | 380 | ||
379 | if (time(NULL) - cur_time > 10) { /* Transmit for 10 seconds */ | 381 | if (time(NULL) - cur_time > 10) { /* Transmit for 10 seconds */ |
380 | step++; /* This terminates the loop */ | 382 | step++; /* This terminates the loop */ |
381 | toxav_kill_transmission(status_control.Alice.av); | 383 | toxav_kill_transmission(status_control.Alice.av, status_control.Alice.call_index); |
382 | toxav_kill_transmission(status_control.Bob.av); | 384 | toxav_kill_transmission(status_control.Bob.av, status_control.Bob.call_index); |
383 | 385 | ||
384 | /* Call over Alice hangs up */ | 386 | /* Call over Alice hangs up */ |
385 | toxav_hangup(status_control.Alice.av); | 387 | toxav_hangup(status_control.Alice.av, status_control.Alice.call_index); |
386 | } | 388 | } |
387 | } | 389 | } |
388 | TERMINATE_SCOPE() | 390 | TERMINATE_SCOPE() |
@@ -408,7 +410,7 @@ START_TEST(test_AV) | |||
408 | switch ( step ) { | 410 | switch ( step ) { |
409 | case 0: /* Alice */ | 411 | case 0: /* Alice */ |
410 | printf("Alice is calling...\n"); | 412 | printf("Alice is calling...\n"); |
411 | toxav_call(status_control.Alice.av, 0, TypeAudio, 10); | 413 | toxav_call(status_control.Alice.av, &status_control.Alice.call_index, 0, TypeAudio, 10); |
412 | step++; | 414 | step++; |
413 | break; | 415 | break; |
414 | \ | 416 | \ |
@@ -416,7 +418,7 @@ START_TEST(test_AV) | |||
416 | case 1: /* Bob */ | 418 | case 1: /* Bob */ |
417 | if (status_control.Bob.status == Ringing) { | 419 | if (status_control.Bob.status == Ringing) { |
418 | printf("Bob rejects...\n"); | 420 | printf("Bob rejects...\n"); |
419 | toxav_reject(status_control.Bob.av, "Who likes D's anyway?"); | 421 | toxav_reject(status_control.Bob.av, status_control.Bob.call_index, "Who likes D's anyway?"); |
420 | step++; | 422 | step++; |
421 | } | 423 | } |
422 | 424 | ||
@@ -450,7 +452,7 @@ START_TEST(test_AV) | |||
450 | switch ( step ) { | 452 | switch ( step ) { |
451 | case 0: /* Alice */ | 453 | case 0: /* Alice */ |
452 | printf("Alice is calling...\n"); | 454 | printf("Alice is calling...\n"); |
453 | toxav_call(status_control.Alice.av, 0, TypeAudio, 10); | 455 | toxav_call(status_control.Alice.av, &status_control.Alice.call_index, 0, TypeAudio, 10); |
454 | step++; | 456 | step++; |
455 | break; | 457 | break; |
456 | \ | 458 | \ |
@@ -458,7 +460,7 @@ START_TEST(test_AV) | |||
458 | case 1: /* Alice again */ | 460 | case 1: /* Alice again */ |
459 | if (status_control.Bob.status == Ringing) { | 461 | if (status_control.Bob.status == Ringing) { |
460 | printf("Alice cancels...\n"); | 462 | printf("Alice cancels...\n"); |
461 | toxav_cancel(status_control.Alice.av, 0, "Who likes D's anyway?"); | 463 | toxav_cancel(status_control.Alice.av, status_control.Alice.call_index, 0, "Who likes D's anyway?"); |
462 | step++; | 464 | step++; |
463 | } | 465 | } |
464 | 466 | ||
@@ -484,20 +486,29 @@ END_TEST | |||
484 | /*************************************************************************************************/ | 486 | /*************************************************************************************************/ |
485 | 487 | ||
486 | 488 | ||
489 | /*************************************************************************************************/ | ||
490 | |||
491 | /*************************************************************************************************/ | ||
492 | |||
487 | 493 | ||
488 | Suite *tox_suite(void) | 494 | Suite *tox_suite(void) |
489 | { | 495 | { |
490 | Suite *s = suite_create("ToxAV"); | 496 | Suite *s = suite_create("ToxAV"); |
491 | 497 | ||
492 | TCase *tc_av = tcase_create("A/V"); | 498 | TCase *tc_av_flows = tcase_create("AV_flows"); |
493 | tcase_add_test(tc_av, test_AV); | 499 | tcase_add_test(tc_av_flows, test_AV_flows); |
494 | tcase_set_timeout(tc_av, 100); /* Timeout on 100 too much? */ | 500 | tcase_set_timeout(tc_av_flows, 100); /* Timeout on 100 too much? */ |
495 | suite_add_tcase(s, tc_av); | 501 | suite_add_tcase(s, tc_av_flows); |
502 | |||
503 | TCase *tc_av_three_calls = tcase_create("AV_three_calls"); | ||
504 | tcase_add_test(tc_av_three_calls, test_AV_three_calls); | ||
505 | tcase_set_timeout(tc_av_three_calls, 100); /* Timeout on 100 too much? */ | ||
506 | suite_add_tcase(s, tc_av_three_calls); | ||
496 | 507 | ||
497 | return s; | 508 | return s; |
498 | } | 509 | } |
499 | int main(int argc, char *argv[]) | 510 | int main(int argc, char *argv[]) |
500 | { | 511 | { |
501 | Suite *tox = tox_suite(); | 512 | Suite *tox = tox_suite(); |
502 | SRunner *test_runner = srunner_create(tox); | 513 | SRunner *test_runner = srunner_create(tox); |
503 | 514 | ||
diff --git a/auto_tests/toxav_many.c b/auto_tests/toxav_many.c new file mode 100644 index 00000000..a5a32945 --- /dev/null +++ b/auto_tests/toxav_many.c | |||
@@ -0,0 +1,120 @@ | |||
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 <stdio.h> | ||
9 | #include <check.h> | ||
10 | #include <stdlib.h> | ||
11 | #include <time.h> | ||
12 | #include <assert.h> | ||
13 | |||
14 | #include "../toxcore/tox.h" | ||
15 | #include "../toxcore/logger.h" | ||
16 | #include "../toxav/toxav.h" | ||
17 | |||
18 | #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) | ||
19 | #define c_sleep(x) Sleep(1*x) | ||
20 | #else | ||
21 | #include <unistd.h> | ||
22 | #define c_sleep(x) usleep(1000*x) | ||
23 | #endif | ||
24 | |||
25 | |||
26 | |||
27 | typedef enum _CallStatus { | ||
28 | none, | ||
29 | InCall, | ||
30 | Ringing, | ||
31 | Ended, | ||
32 | Rejected, | ||
33 | Cancel | ||
34 | |||
35 | } CallStatus; | ||
36 | |||
37 | typedef struct _Party { | ||
38 | CallStatus status; | ||
39 | ToxAv *av; | ||
40 | time_t *CallStarted; | ||
41 | int call_index; | ||
42 | } Party; | ||
43 | |||
44 | typedef struct _Status { | ||
45 | Party Alice; | ||
46 | Party Bob; | ||
47 | } Status; | ||
48 | |||
49 | void accept_friend_request(Tox *m, uint8_t *public_key, uint8_t *data, uint16_t length, void *userdata) | ||
50 | { | ||
51 | if (length == 7 && memcmp("gentoo", data, 7) == 0) { | ||
52 | tox_add_friend_norequest(m, public_key); | ||
53 | } | ||
54 | } | ||
55 | |||
56 | |||
57 | /******************************************************************************/ | ||
58 | void callback_recv_invite ( uint32_t call_index, void *_arg ) | ||
59 | { | ||
60 | Party *cast = _arg; | ||
61 | |||
62 | cast->status = Ringing; | ||
63 | cast->call_index = call_index; | ||
64 | } | ||
65 | void callback_recv_ringing ( uint32_t call_index, void *_arg ) | ||
66 | { | ||
67 | Party *cast = _arg; | ||
68 | |||
69 | cast->status = Ringing; | ||
70 | } | ||
71 | void callback_recv_starting ( uint32_t call_index, void *_arg ) | ||
72 | { | ||
73 | Party *cast = _arg; | ||
74 | |||
75 | cast->status = InCall; | ||
76 | toxav_prepare_transmission(cast->av, call_index, 1); | ||
77 | } | ||
78 | void callback_recv_ending ( uint32_t call_index, void *_arg ) | ||
79 | { | ||
80 | Party *cast = _arg; | ||
81 | |||
82 | cast->status = Ended; | ||
83 | } | ||
84 | |||
85 | void callback_recv_error ( uint32_t call_index, void *_arg ) | ||
86 | { | ||
87 | ck_assert_msg(0, "AV internal error"); | ||
88 | } | ||
89 | |||
90 | void callback_call_started ( uint32_t call_index, void *_arg ) | ||
91 | { | ||
92 | Party *cast = _arg; | ||
93 | |||
94 | cast->status = InCall; | ||
95 | toxav_prepare_transmission(cast->av, call_index, 1); | ||
96 | } | ||
97 | void callback_call_canceled ( uint32_t call_index, void *_arg ) | ||
98 | { | ||
99 | Party *cast = _arg; | ||
100 | |||
101 | cast->status = Cancel; | ||
102 | } | ||
103 | void callback_call_rejected ( uint32_t call_index, void *_arg ) | ||
104 | { | ||
105 | Party *cast = _arg; | ||
106 | |||
107 | cast->status = Rejected; | ||
108 | } | ||
109 | void callback_call_ended ( uint32_t call_index, void *_arg ) | ||
110 | { | ||
111 | Party *cast = _arg; | ||
112 | |||
113 | cast->status = Ended; | ||
114 | } | ||
115 | |||
116 | void callback_requ_timeout ( uint32_t call_index, void *_arg ) | ||
117 | { | ||
118 | ck_assert_msg(0, "No answer!"); | ||
119 | } | ||
120 | /*************************************************************************************************/ | ||
diff --git a/configure.ac b/configure.ac index 34038517..f82f0a19 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -34,6 +34,9 @@ BUILD_AV="yes" | |||
34 | BUILD_PHONE="no" | 34 | BUILD_PHONE="no" |
35 | BUILD_TESTING="yes" | 35 | BUILD_TESTING="yes" |
36 | 36 | ||
37 | LOGGING="no" | ||
38 | LOGGING_OUTNAM="libtoxcore.log" | ||
39 | |||
37 | NCURSES_FOUND="no" | 40 | NCURSES_FOUND="no" |
38 | LIBCONFIG_FOUND="no" | 41 | LIBCONFIG_FOUND="no" |
39 | LIBCHECK_FOUND="no" | 42 | LIBCHECK_FOUND="no" |
@@ -80,6 +83,55 @@ AC_ARG_ENABLE([randombytes-stir], | |||
80 | ] | 83 | ] |
81 | ) | 84 | ) |
82 | 85 | ||
86 | AC_ARG_ENABLE([logging], | ||
87 | [AC_HELP_STRING([--enable-logging], [enable logging (default: auto)]) ], | ||
88 | [ | ||
89 | if test "x$enableval" = "xyes"; then | ||
90 | LOGGING="yes" | ||
91 | |||
92 | AC_DEFINE([LOGGING], [], [If logging enabled]) | ||
93 | AC_DEFINE([LOGGER_LEVEL], [DEBUG], [LoggerLevel value]) | ||
94 | AC_DEFINE_UNQUOTED([LOGGER_OUTPUT_FILE], ["$LOGGING_OUTNAM"], [Output of logger]) | ||
95 | fi | ||
96 | ] | ||
97 | ) | ||
98 | |||
99 | AC_ARG_WITH(logger-level, | ||
100 | AC_HELP_STRING([--with-logger-level=LEVEL], | ||
101 | [Logger levels: INFO; DEBUG; WARNING; ERROR ]), | ||
102 | [ | ||
103 | if test "x$LOGGING" = "xno"; then | ||
104 | AC_MSG_WARN([Logging disabled!]) | ||
105 | else | ||
106 | if test "x$withval" = "xINFO"; then | ||
107 | AC_DEFINE([LOGGER_LEVEL], [INFO], [LoggerLevel value]) | ||
108 | |||
109 | elif test "x$withval" = "xDEBUG"; then | ||
110 | AC_DEFINE([LOGGER_LEVEL], [DEBUG], [LoggerLevel value]) | ||
111 | |||
112 | elif test "x$withval" = "xWARNING"; then | ||
113 | AC_DEFINE([LOGGER_LEVEL], [WARNING], [LoggerLevel value]) | ||
114 | |||
115 | elif test "x$withval" = "xERROR"; then | ||
116 | AC_DEFINE([LOGGER_LEVEL], [ERROR], [LoggerLevel value]) | ||
117 | else | ||
118 | AC_MSG_WARN([Invalid logger level: $withval. Using default 'DEBUG']) | ||
119 | fi | ||
120 | fi | ||
121 | ] | ||
122 | ) | ||
123 | |||
124 | AC_ARG_WITH(logger-path, | ||
125 | AC_HELP_STRING([--with-logger-path=DIR], | ||
126 | [Path of logger output]), | ||
127 | [ | ||
128 | if test "x$LOGGING" = "xno"; then | ||
129 | AC_MSG_WARN([Logging disabled!]) | ||
130 | else | ||
131 | AC_DEFINE_UNQUOTED([LOGGER_OUTPUT_FILE], ["$withval""/""$LOGGING_OUTNAM"], [Output of logger]) | ||
132 | fi | ||
133 | ] | ||
134 | ) | ||
83 | 135 | ||
84 | PKG_PROG_PKG_CONFIG | 136 | PKG_PROG_PKG_CONFIG |
85 | 137 | ||
diff --git a/toxav/msi.c b/toxav/msi.c index 26e301d3..ae6fcf84 100755 --- a/toxav/msi.c +++ b/toxav/msi.c | |||
@@ -26,7 +26,9 @@ | |||
26 | #include "config.h" | 26 | #include "config.h" |
27 | #endif /* HAVE_CONFIG_H */ | 27 | #endif /* HAVE_CONFIG_H */ |
28 | 28 | ||
29 | #define _BSD_SOURCE | 29 | #include "../toxcore/logger.h" |
30 | |||
31 | /*#define _BSD_SOURCE*/ | ||
30 | 32 | ||
31 | #include "msi.h" | 33 | #include "msi.h" |
32 | #include "event.h" | 34 | #include "event.h" |
@@ -120,10 +122,13 @@ static struct _Callbacks { | |||
120 | void* data; | 122 | void* data; |
121 | } callbacks[11] = {0}; | 123 | } callbacks[11] = {0}; |
122 | 124 | ||
123 | inline__ void invoke_callback(MSICallbackID id) | 125 | inline__ void invoke_callback(uint32_t call_index, MSICallbackID id) |
124 | { | 126 | { |
125 | /*if ( callbacks[id].function ) event.rise ( callbacks[id].function, callbacks[id].data );*/ | 127 | /*if ( callbacks[id].function ) event.rise ( callbacks[id].function, callbacks[id].data );*/ |
126 | if ( callbacks[id].function ) callbacks[id].function ( callbacks[id].data ); | 128 | if ( callbacks[id].function ) { |
129 | LOGGER_DEBUG("Invoking callback function: %d", id); | ||
130 | callbacks[id].function ( call_index, callbacks[id].data ); | ||
131 | } | ||
127 | } | 132 | } |
128 | 133 | ||
129 | /*static MSICallback callbacks[10] = {0};*/ | 134 | /*static MSICallback callbacks[10] = {0};*/ |
@@ -230,7 +235,9 @@ static inline__ const uint8_t *stringify_response ( MSIResponse response ) | |||
230 | */ | 235 | */ |
231 | int parse_raw_data ( MSIMessage *msg, const uint8_t *data, uint16_t length ) | 236 | int parse_raw_data ( MSIMessage *msg, const uint8_t *data, uint16_t length ) |
232 | { | 237 | { |
233 | assert ( msg ); | 238 | if ( msg == NULL ) { |
239 | LOGGER_ERROR("Could not parse message: no storage!"); | ||
240 | } | ||
234 | 241 | ||
235 | if ( data[length - 1] ) /* End byte must have value 0 */ | 242 | if ( data[length - 1] ) /* End byte must have value 0 */ |
236 | return -1; | 243 | return -1; |
@@ -271,7 +278,7 @@ int parse_raw_data ( MSIMessage *msg, const uint8_t *data, uint16_t length ) | |||
271 | if ON_HEADER ( _it, msg->version, VERSION_FIELD, 7 ) | 278 | if ON_HEADER ( _it, msg->version, VERSION_FIELD, 7 ) |
272 | else if ON_HEADER ( _it, msg->request, REQUEST_FIELD, 7 ) | 279 | else if ON_HEADER ( _it, msg->request, REQUEST_FIELD, 7 ) |
273 | else if ON_HEADER ( _it, msg->callid, CALLID_FIELD, 7 ) | 280 | else if ON_HEADER ( _it, msg->callid, CALLID_FIELD, 7 ) |
274 | } | 281 | } |
275 | break; | 282 | break; |
276 | 283 | ||
277 | case 8: { /* Response header */ | 284 | case 8: { /* Response header */ |
@@ -290,9 +297,13 @@ int parse_raw_data ( MSIMessage *msg, const uint8_t *data, uint16_t length ) | |||
290 | break; | 297 | break; |
291 | 298 | ||
292 | default: | 299 | default: |
300 | LOGGER_ERROR("Unkown field value"); | ||
293 | return -1; | 301 | return -1; |
294 | } | 302 | } |
295 | } else return -1; | 303 | } else { |
304 | LOGGER_ERROR("Invalid field byte or field size too large"); | ||
305 | return -1; | ||
306 | } | ||
296 | 307 | ||
297 | /* If it's anything else return failure as the message is invalid */ | 308 | /* If it's anything else return failure as the message is invalid */ |
298 | 309 | ||
@@ -304,8 +315,9 @@ int parse_raw_data ( MSIMessage *msg, const uint8_t *data, uint16_t length ) | |||
304 | 315 | ||
305 | #define ALLOCATE_HEADER( var, mheader_value, t_size) \ | 316 | #define ALLOCATE_HEADER( var, mheader_value, t_size) \ |
306 | var.header_value = calloc(sizeof *mheader_value, t_size); \ | 317 | var.header_value = calloc(sizeof *mheader_value, t_size); \ |
307 | memcpy(var.header_value, mheader_value, t_size); \ | 318 | if (var.header_value == NULL) { LOGGER_WARNING("Header allocation failed!"); } \ |
308 | var.size = t_size; | 319 | else { memcpy(var.header_value, mheader_value, t_size); \ |
320 | var.size = t_size; } | ||
309 | 321 | ||
310 | 322 | ||
311 | /** | 323 | /** |
@@ -316,7 +328,9 @@ var.size = t_size; | |||
316 | */ | 328 | */ |
317 | void free_message ( MSIMessage *msg ) | 329 | void free_message ( MSIMessage *msg ) |
318 | { | 330 | { |
319 | assert ( msg ); | 331 | if ( msg == NULL ) { |
332 | LOGGER_ERROR("Tried to free empty message"); | ||
333 | } | ||
320 | 334 | ||
321 | free ( msg->calltype.header_value ); | 335 | free ( msg->calltype.header_value ); |
322 | free ( msg->request.header_value ); | 336 | free ( msg->request.header_value ); |
@@ -343,7 +357,11 @@ void free_message ( MSIMessage *msg ) | |||
343 | MSIMessage *msi_new_message ( uint8_t type, const uint8_t *type_id ) | 357 | MSIMessage *msi_new_message ( uint8_t type, const uint8_t *type_id ) |
344 | { | 358 | { |
345 | MSIMessage *_retu = calloc ( sizeof ( MSIMessage ), 1 ); | 359 | MSIMessage *_retu = calloc ( sizeof ( MSIMessage ), 1 ); |
346 | assert ( _retu ); | 360 | |
361 | if ( _retu == NULL ) { | ||
362 | LOGGER_WARNING("Allocation failed!"); | ||
363 | return NULL; | ||
364 | } | ||
347 | 365 | ||
348 | if ( type == TYPE_REQUEST ) { | 366 | if ( type == TYPE_REQUEST ) { |
349 | ALLOCATE_HEADER ( _retu->request, type_id, strlen ( (const char *)type_id ) ) | 367 | ALLOCATE_HEADER ( _retu->request, type_id, strlen ( (const char *)type_id ) ) |
@@ -371,10 +389,17 @@ MSIMessage *msi_new_message ( uint8_t type, const uint8_t *type_id ) | |||
371 | */ | 389 | */ |
372 | MSIMessage *parse_message ( const uint8_t *data, uint16_t length ) | 390 | MSIMessage *parse_message ( const uint8_t *data, uint16_t length ) |
373 | { | 391 | { |
374 | assert ( data ); | 392 | if ( data == NULL ) { |
393 | LOGGER_WARNING("Tried to parse empty message!"); | ||
394 | return NULL; | ||
395 | } | ||
375 | 396 | ||
376 | MSIMessage *_retu = calloc ( sizeof ( MSIMessage ), 1 ); | 397 | MSIMessage *_retu = calloc ( sizeof ( MSIMessage ), 1 ); |
377 | assert ( _retu ); | 398 | |
399 | if ( _retu == NULL ) { | ||
400 | LOGGER_WARNING("Allocation failed!"); | ||
401 | return NULL; | ||
402 | } | ||
378 | 403 | ||
379 | memset ( _retu, 0, sizeof ( MSIMessage ) ); | 404 | memset ( _retu, 0, sizeof ( MSIMessage ) ); |
380 | 405 | ||
@@ -397,6 +422,42 @@ MSIMessage *parse_message ( const uint8_t *data, uint16_t length ) | |||
397 | 422 | ||
398 | 423 | ||
399 | /** | 424 | /** |
425 | * @brief Makes clear message presentation | ||
426 | * | ||
427 | * @param msg Message | ||
428 | * @param dest Dest string | ||
429 | * @return int | ||
430 | */ | ||
431 | int stringify_message(MSIMessage* msg, char* dest) | ||
432 | { | ||
433 | #define HDR_TO_STR(__dest, __hdr) if (__hdr.header_value) {\ | ||
434 | char nltstr[MSI_MAXMSG_SIZE]; memset(nltstr, '\0', MSI_MAXMSG_SIZE); int i = 0; \ | ||
435 | for ( ; i < __hdr.size; i ++) nltstr[i] = (char)__hdr.header_value[i]; \ | ||
436 | } | ||
437 | |||
438 | if ( !msg || !dest ) | ||
439 | return -1; | ||
440 | |||
441 | HDR_TO_STR(dest, msg->version); | ||
442 | HDR_TO_STR(dest, msg->request); | ||
443 | HDR_TO_STR(dest, msg->response); | ||
444 | HDR_TO_STR(dest, msg->reason); | ||
445 | HDR_TO_STR(dest, msg->callid); | ||
446 | HDR_TO_STR(dest, msg->calltype); | ||
447 | HDR_TO_STR(dest, msg->cryptokey); | ||
448 | HDR_TO_STR(dest, msg->nonce); | ||
449 | |||
450 | // if (msg->version.header_value) { | ||
451 | // U8_TO_NLTCHAR(msg->version.header_value, msg->version.size, nltstr, MSI_MAXMSG_SIZE); | ||
452 | // sprintf(dest, "Version: %s\n", nltstr); | ||
453 | // } | ||
454 | |||
455 | return 0; | ||
456 | } | ||
457 | |||
458 | |||
459 | |||
460 | /** | ||
400 | * @brief Speaks for it self. | 461 | * @brief Speaks for it self. |
401 | * | 462 | * |
402 | * @param dest Container. | 463 | * @param dest Container. |
@@ -413,10 +474,20 @@ uint8_t *append_header_to_string ( | |||
413 | uint16_t value_len, | 474 | uint16_t value_len, |
414 | uint16_t *length ) | 475 | uint16_t *length ) |
415 | { | 476 | { |
416 | assert ( dest ); | 477 | if ( dest == NULL ) { |
417 | assert ( header_value ); | 478 | LOGGER_ERROR("No destination space!"); |
418 | assert ( header_field ); | 479 | assert(dest); |
419 | 480 | } | |
481 | if (header_value == NULL) { | ||
482 | LOGGER_ERROR("Empty header value"); | ||
483 | return NULL; | ||
484 | } | ||
485 | if ( header_field == NULL ) { | ||
486 | LOGGER_ERROR("Empty header field"); | ||
487 | return NULL; | ||
488 | } | ||
489 | |||
490 | |||
420 | const uint8_t *_hvit = header_value; | 491 | const uint8_t *_hvit = header_value; |
421 | uint16_t _total = 6 + value_len; /* 6 is known plus header value len + field len*/ | 492 | uint16_t _total = 6 + value_len; /* 6 is known plus header value len + field len*/ |
422 | 493 | ||
@@ -477,10 +548,16 @@ if ( header.header_value ) { var = append_header_to_string(var, (const uint8_t*) | |||
477 | * @param dest Destination. | 548 | * @param dest Destination. |
478 | * @return uint16_t It's final size. | 549 | * @return uint16_t It's final size. |
479 | */ | 550 | */ |
480 | uint16_t message_to_string ( MSIMessage *msg, uint8_t *dest ) | 551 | uint16_t message_to_send ( MSIMessage *msg, uint8_t *dest ) |
481 | { | 552 | { |
482 | assert ( msg ); | 553 | if (msg == NULL) { |
483 | assert ( dest ); | 554 | LOGGER_ERROR("Empty message!"); |
555 | return 0; | ||
556 | } | ||
557 | if (dest == NULL ) { | ||
558 | LOGGER_ERROR("Empty destination!"); | ||
559 | return 0; | ||
560 | } | ||
484 | 561 | ||
485 | uint8_t *_iterated = dest; | 562 | uint8_t *_iterated = dest; |
486 | uint16_t _size = 0; | 563 | uint16_t _size = 0; |
@@ -525,7 +602,10 @@ GENERIC_SETTER_DEFINITION ( nonce ) | |||
525 | */ | 602 | */ |
526 | void t_randomstr ( uint8_t *str, size_t size ) | 603 | void t_randomstr ( uint8_t *str, size_t size ) |
527 | { | 604 | { |
528 | assert ( str ); | 605 | if (str == NULL) { |
606 | LOGGER_DEBUG("Empty destination!"); | ||
607 | return; | ||
608 | } | ||
529 | 609 | ||
530 | static const uint8_t _bytes[] = | 610 | static const uint8_t _bytes[] = |
531 | "0123456789" | 611 | "0123456789" |
@@ -607,14 +687,32 @@ static inline__ const uint8_t *stringify_error_code ( MSICallError error_code ) | |||
607 | * @retval -1 Error occured. | 687 | * @retval -1 Error occured. |
608 | * @retval 0 Success. | 688 | * @retval 0 Success. |
609 | */ | 689 | */ |
610 | int send_message ( MSISession *session, MSIMessage *msg, uint32_t to ) | 690 | int send_message ( MSISession *session, MSICall* call, MSIMessage *msg, uint32_t to ) |
611 | { | 691 | { |
612 | msi_msg_set_callid ( msg, session->call->id, CALL_ID_LEN ); | 692 | msi_msg_set_callid ( msg, call->id, CALL_ID_LEN ); |
613 | 693 | ||
614 | uint8_t _msg_string_final [MSI_MAXMSG_SIZE]; | 694 | uint8_t _msg_string_final [MSI_MAXMSG_SIZE]; |
615 | uint16_t _length = message_to_string ( msg, _msg_string_final ); | 695 | uint16_t _length = message_to_send ( msg, _msg_string_final ); |
616 | 696 | ||
617 | return m_msi_packet(session->messenger_handle, to, _msg_string_final, _length) ? 0 : -1; | 697 | if (!_length) { |
698 | LOGGER_WARNING("Parsing message failed; nothing sent!"); | ||
699 | return -1; | ||
700 | } | ||
701 | |||
702 | /* | ||
703 | LOGGER_SCOPE( | ||
704 | char cast[MSI_MAXMSG_SIZE]; | ||
705 | stringify_message(msg, cast); | ||
706 | LOGGER_DEBUG("[Call: %s] [to: %u] Sending message: len: %d\n%s", call->id, to, _length, cast); | ||
707 | );*/ | ||
708 | |||
709 | |||
710 | if ( m_msi_packet(session->messenger_handle, to, _msg_string_final, _length) ) { | ||
711 | LOGGER_DEBUG("Sent message"); | ||
712 | return 0; | ||
713 | } | ||
714 | |||
715 | return -1; | ||
618 | } | 716 | } |
619 | 717 | ||
620 | 718 | ||
@@ -646,7 +744,7 @@ int call_id_bigger( const uint8_t* first, const uint8_t* second) | |||
646 | * @param peer_id The peer. | 744 | * @param peer_id The peer. |
647 | * @return void | 745 | * @return void |
648 | */ | 746 | */ |
649 | void flush_peer_type ( MSISession *session, MSIMessage *msg, int peer_id ) | 747 | void flush_peer_type ( MSICall *call, MSIMessage *msg, int peer_id ) |
650 | { | 748 | { |
651 | if ( msg->calltype.header_value ) { | 749 | if ( msg->calltype.header_value ) { |
652 | uint8_t hdrval [MSI_MAXMSG_SIZE]; /* Make sure no overflow */ | 750 | uint8_t hdrval [MSI_MAXMSG_SIZE]; /* Make sure no overflow */ |
@@ -655,10 +753,10 @@ void flush_peer_type ( MSISession *session, MSIMessage *msg, int peer_id ) | |||
655 | hdrval[msg->calltype.size] = '\0'; | 753 | hdrval[msg->calltype.size] = '\0'; |
656 | 754 | ||
657 | if ( strcmp ( ( const char * ) hdrval, CT_AUDIO_HEADER_VALUE ) == 0 ) { | 755 | if ( strcmp ( ( const char * ) hdrval, CT_AUDIO_HEADER_VALUE ) == 0 ) { |
658 | session->call->type_peer[peer_id] = type_audio; | 756 | call->type_peer[peer_id] = type_audio; |
659 | 757 | ||
660 | } else if ( strcmp ( ( const char * ) hdrval, CT_VIDEO_HEADER_VALUE ) == 0 ) { | 758 | } else if ( strcmp ( ( const char * ) hdrval, CT_VIDEO_HEADER_VALUE ) == 0 ) { |
661 | session->call->type_peer[peer_id] = type_video; | 759 | call->type_peer[peer_id] = type_video; |
662 | } else {} /* Error */ | 760 | } else {} /* Error */ |
663 | } else {} /* Error */ | 761 | } else {} /* Error */ |
664 | } | 762 | } |
@@ -669,13 +767,17 @@ void handle_remote_connection_change(Messenger *messenger, int friend_num, uint8 | |||
669 | 767 | ||
670 | switch ( status ) { | 768 | switch ( status ) { |
671 | case 0: { /* Went offline */ | 769 | case 0: { /* Went offline */ |
672 | if ( session->call ) { | 770 | uint32_t j =0; |
771 | for ( ; j < session->max_calls; j ++ ) { | ||
772 | |||
773 | if ( !session->calls[j] ) continue; | ||
774 | |||
673 | int i = 0; | 775 | int i = 0; |
674 | 776 | for ( ; i < session->calls[j]->peer_count; i ++ ) | |
675 | for ( ; i < session->call->peer_count; i ++ ) | 777 | if ( session->calls[j]->peers[i] == friend_num ) { |
676 | if ( session->call->peers[i] == friend_num ) { | 778 | invoke_callback(j, MSI_OnPeerTimeout); |
677 | invoke_callback(MSI_OnPeerTimeout); | 779 | LOGGER_DEBUG("Remote: %d timed out!", friend_num); |
678 | return; | 780 | return; /* TODO: On group calls change behaviour */ |
679 | } | 781 | } |
680 | } | 782 | } |
681 | } | 783 | } |
@@ -686,6 +788,18 @@ void handle_remote_connection_change(Messenger *messenger, int friend_num, uint8 | |||
686 | } | 788 | } |
687 | } | 789 | } |
688 | 790 | ||
791 | MSICall* find_call ( MSISession* session, uint8_t* call_id ) | ||
792 | { | ||
793 | if ( call_id == NULL ) return NULL; | ||
794 | |||
795 | uint32_t i = 0; | ||
796 | for (; i < session->max_calls; i ++ ) | ||
797 | if ( session->calls[i] && memcmp(session->calls[i]->id, call_id, CALL_ID_LEN) == 0 ) | ||
798 | return session->calls[i]; | ||
799 | |||
800 | return NULL; | ||
801 | } | ||
802 | |||
689 | /** | 803 | /** |
690 | * @brief Sends error response to peer. | 804 | * @brief Sends error response to peer. |
691 | * | 805 | * |
@@ -695,20 +809,22 @@ void handle_remote_connection_change(Messenger *messenger, int friend_num, uint8 | |||
695 | * @return int | 809 | * @return int |
696 | * @retval 0 It's always success. | 810 | * @retval 0 It's always success. |
697 | */ | 811 | */ |
698 | int handle_error ( MSISession *session, MSICallError errid, uint32_t to ) | 812 | int handle_error ( MSISession *session, MSICall* call, MSICallError errid, uint32_t to ) |
699 | { | 813 | { |
814 | LOGGER_DEBUG("Sending error: %d on call: %s", errid, call->id); | ||
815 | |||
700 | MSIMessage *_msg_error = msi_new_message ( TYPE_RESPONSE, stringify_response ( error ) ); | 816 | MSIMessage *_msg_error = msi_new_message ( TYPE_RESPONSE, stringify_response ( error ) ); |
701 | 817 | ||
702 | const uint8_t *_error_code_str = stringify_error_code ( errid ); | 818 | const uint8_t *_error_code_str = stringify_error_code ( errid ); |
703 | 819 | ||
704 | msi_msg_set_reason ( _msg_error, _error_code_str, strlen ( ( const char * ) _error_code_str ) ); | 820 | msi_msg_set_reason ( _msg_error, _error_code_str, strlen ( ( const char * ) _error_code_str ) ); |
705 | send_message ( session, _msg_error, to ); | 821 | send_message ( session, call, _msg_error, to ); |
706 | free_message ( _msg_error ); | 822 | free_message ( _msg_error ); |
707 | 823 | ||
708 | session->last_error_id = errid; | 824 | session->last_error_id = errid; |
709 | session->last_error_str = stringify_error ( errid ); | 825 | session->last_error_str = stringify_error ( errid ); |
710 | 826 | ||
711 | invoke_callback(MSI_OnError); | 827 | invoke_callback(call->call_idx, MSI_OnError); |
712 | 828 | ||
713 | return 0; | 829 | return 0; |
714 | } | 830 | } |
@@ -723,16 +839,16 @@ int handle_error ( MSISession *session, MSICallError errid, uint32_t to ) | |||
723 | * @retval -1 No error. | 839 | * @retval -1 No error. |
724 | * @retval 0 Error occured and response sent. | 840 | * @retval 0 Error occured and response sent. |
725 | */ | 841 | */ |
726 | int has_call_error ( MSISession *session, MSIMessage *msg ) | 842 | int has_call_error ( MSISession *session, MSICall* call, MSIMessage *msg ) |
727 | { | 843 | { |
728 | if ( !msg->callid.header_value ) { | 844 | if ( !msg->callid.header_value ) { |
729 | return handle_error ( session, error_no_callid, msg->friend_id ); | 845 | return handle_error ( session, call, error_no_callid, msg->friend_id ); |
730 | 846 | ||
731 | } else if ( !session->call ) { | 847 | } else if ( !call ) { |
732 | return handle_error ( session, error_no_call, msg->friend_id ); | 848 | return handle_error ( session, call, error_no_call, msg->friend_id ); |
733 | 849 | ||
734 | } else if ( memcmp ( session->call->id, msg->callid.header_value, CALL_ID_LEN ) != 0 ) { | 850 | } else if ( memcmp ( call->id, msg->callid.header_value, CALL_ID_LEN ) != 0 ) { |
735 | return handle_error ( session, error_id_mismatch, msg->friend_id ); | 851 | return handle_error ( session, call, error_id_mismatch, msg->friend_id ); |
736 | 852 | ||
737 | } | 853 | } |
738 | 854 | ||
@@ -741,7 +857,7 @@ int has_call_error ( MSISession *session, MSIMessage *msg ) | |||
741 | 857 | ||
742 | 858 | ||
743 | /** | 859 | /** |
744 | * @brief Function called at request timeout. | 860 | * @brief Function called at request timeout. If not called in thread it might cause trouble |
745 | * | 861 | * |
746 | * @param arg Control session | 862 | * @param arg Control session |
747 | * @return void* | 863 | * @return void* |
@@ -752,16 +868,18 @@ void *handle_timeout ( void *arg ) | |||
752 | * timers on these cancels and terminate call on | 868 | * timers on these cancels and terminate call on |
753 | * their timeout | 869 | * their timeout |
754 | */ | 870 | */ |
755 | MSISession *_session = arg; | 871 | MSICall *_call = arg; |
756 | 872 | ||
757 | invoke_callback(MSI_OnRequestTimeout); | 873 | LOGGER_DEBUG("[Call: %s] Request timed out!", _call->id); |
874 | |||
875 | invoke_callback(_call->call_idx, MSI_OnRequestTimeout); | ||
758 | 876 | ||
759 | if ( _session && _session->call ) { | 877 | if ( _call && _call->session ) { |
760 | 878 | ||
761 | /* TODO: Cancel all? */ | 879 | /* TODO: Cancel all? */ |
762 | /* uint16_t _it = 0; | 880 | /* uint16_t _it = 0; |
763 | for ( ; _it < _session->call->peer_count; _it++ ) */ | 881 | for ( ; _it < _session->call->peer_count; _it++ ) */ |
764 | msi_cancel ( _session, _session->call->peers [0], "Request timedout" ); | 882 | msi_cancel ( _call->session, _call->call_idx, _call->peers [0], "Request timed out" ); |
765 | } | 883 | } |
766 | 884 | ||
767 | pthread_exit(NULL); | 885 | pthread_exit(NULL); |
@@ -798,14 +916,41 @@ void add_peer( MSICall *call, int peer_id ) | |||
798 | */ | 916 | */ |
799 | MSICall *init_call ( MSISession *session, int peers, int ringing_timeout ) | 917 | MSICall *init_call ( MSISession *session, int peers, int ringing_timeout ) |
800 | { | 918 | { |
801 | assert ( session ); | 919 | |
802 | assert ( peers ); | 920 | if (peers == 0) { |
921 | LOGGER_ERROR("No peers!"); | ||
922 | return NULL; | ||
923 | } | ||
924 | |||
925 | uint32_t _call_idx = 0; | ||
926 | for (; _call_idx < session->max_calls; _call_idx ++) { | ||
927 | if ( !session->calls[_call_idx] ) { | ||
928 | session->calls[_call_idx] = calloc ( sizeof ( MSICall ), 1 ); | ||
929 | break; | ||
930 | } | ||
931 | } | ||
932 | |||
933 | if ( _call_idx == session->max_calls ) { | ||
934 | LOGGER_WARNING("Reached maximum amount of calls!"); | ||
935 | } | ||
936 | |||
803 | 937 | ||
804 | MSICall *_call = calloc ( sizeof ( MSICall ), 1 ); | 938 | MSICall *_call = session->calls[_call_idx]; |
939 | _call->call_idx = _call_idx; | ||
940 | |||
941 | if ( _call == NULL ) { | ||
942 | LOGGER_WARNING("Allocation failed!"); | ||
943 | return NULL; | ||
944 | } | ||
945 | |||
805 | _call->type_peer = calloc ( sizeof ( MSICallType ), peers ); | 946 | _call->type_peer = calloc ( sizeof ( MSICallType ), peers ); |
806 | 947 | ||
807 | assert ( _call ); | 948 | if ( _call->type_peer == NULL ) { |
808 | assert ( _call->type_peer ); | 949 | LOGGER_WARNING("Allocation failed!"); |
950 | return NULL; | ||
951 | } | ||
952 | |||
953 | _call->session = session; | ||
809 | 954 | ||
810 | /*_call->_participant_count = _peers;*/ | 955 | /*_call->_participant_count = _peers;*/ |
811 | 956 | ||
@@ -821,6 +966,7 @@ MSICall *init_call ( MSISession *session, int peers, int ringing_timeout ) | |||
821 | 966 | ||
822 | pthread_mutex_init ( &_call->mutex, NULL ); | 967 | pthread_mutex_init ( &_call->mutex, NULL ); |
823 | 968 | ||
969 | LOGGER_DEBUG("Started new call with index: %u", _call_idx); | ||
824 | return _call; | 970 | return _call; |
825 | } | 971 | } |
826 | 972 | ||
@@ -833,51 +979,48 @@ MSICall *init_call ( MSISession *session, int peers, int ringing_timeout ) | |||
833 | * @retval -1 Error occured. | 979 | * @retval -1 Error occured. |
834 | * @retval 0 Success. | 980 | * @retval 0 Success. |
835 | */ | 981 | */ |
836 | int terminate_call ( MSISession *session ) | 982 | int terminate_call ( MSISession *session, MSICall *call ) |
837 | { | 983 | { |
838 | assert ( session ); | 984 | if ( !call ) { |
839 | 985 | LOGGER_WARNING("Tried to terminate non-existing call!"); | |
840 | if ( !session->call ) | ||
841 | return -1; | 986 | return -1; |
842 | 987 | } | |
843 | 988 | ||
844 | /* Check event loop and cancel timed events if there are any | 989 | /* Check event loop and cancel timed events if there are any |
845 | * NOTE: This has to be done before possibly | 990 | * NOTE: This has to be done before possibly |
846 | * locking the mutex the second time | 991 | * locking the mutex the second time |
847 | */ | 992 | */ |
848 | event.timer_release ( session->call->request_timer_id ); | 993 | event.timer_release ( call->request_timer_id ); |
849 | event.timer_release ( session->call->ringing_timer_id ); | 994 | event.timer_release ( call->ringing_timer_id ); |
850 | 995 | ||
851 | /* Get a handle */ | 996 | /* Get a handle */ |
852 | pthread_mutex_lock ( &session->call->mutex ); | 997 | pthread_mutex_lock ( &call->mutex ); |
853 | 998 | ||
854 | MSICall *_call = session->call; | 999 | session->calls[call->call_idx]= NULL; |
855 | session->call = NULL; | ||
856 | 1000 | ||
857 | free ( _call->type_peer ); | 1001 | free ( call->type_peer ); |
858 | free ( _call->key_local ); | 1002 | free ( call->key_local ); |
859 | free ( _call->key_peer ); | 1003 | free ( call->key_peer ); |
860 | free ( _call->peers); | 1004 | free ( call->peers); |
861 | 1005 | ||
862 | /* Release handle */ | 1006 | /* Release handle */ |
863 | pthread_mutex_unlock ( &_call->mutex ); | 1007 | pthread_mutex_unlock ( &call->mutex ); |
864 | 1008 | ||
865 | pthread_mutex_destroy ( &_call->mutex ); | 1009 | pthread_mutex_destroy ( &call->mutex ); |
866 | 1010 | ||
867 | free ( _call ); | 1011 | free ( call ); |
868 | 1012 | ||
869 | return 0; | 1013 | return 0; |
870 | } | 1014 | } |
871 | 1015 | ||
872 | 1016 | ||
873 | /********** Request handlers **********/ | 1017 | /********** Request handlers **********/ |
874 | int handle_recv_invite ( MSISession *session, MSIMessage *msg ) | 1018 | int handle_recv_invite ( MSISession *session, MSICall* call, MSIMessage *msg ) |
875 | { | 1019 | { |
876 | assert ( session ); | 1020 | LOGGER_DEBUG("Handling 'invite' on call: %s", call? (char*)call->id : "making new"); |
877 | |||
878 | 1021 | ||
879 | if ( session->call ) { | 1022 | if ( call ) { |
880 | if ( session->call->peers[0] == msg->friend_id ) { | 1023 | if ( call->peers[0] == msg->friend_id ) { |
881 | /* The glare case. A calls B when at the same time | 1024 | /* The glare case. A calls B when at the same time |
882 | * B calls A. Who has advantage is set bey calculating | 1025 | * B calls A. Who has advantage is set bey calculating |
883 | * 'bigger' Call id and then that call id is being used in | 1026 | * 'bigger' Call id and then that call id is being used in |
@@ -885,8 +1028,8 @@ int handle_recv_invite ( MSISession *session, MSIMessage *msg ) | |||
885 | * as in he will wait the reponse from the other. | 1028 | * as in he will wait the reponse from the other. |
886 | */ | 1029 | */ |
887 | 1030 | ||
888 | if ( call_id_bigger (session->call->id, msg->callid.header_value) == 1 ) { /* Peer has advantage */ | 1031 | if ( call_id_bigger (call->id, msg->callid.header_value) == 1 ) { /* Peer has advantage */ |
889 | terminate_call(session); | 1032 | terminate_call(session, call); |
890 | } | 1033 | } |
891 | else { | 1034 | else { |
892 | return 0; /* Wait for ringing from peer */ | 1035 | return 0; /* Wait for ringing from peer */ |
@@ -894,202 +1037,213 @@ int handle_recv_invite ( MSISession *session, MSIMessage *msg ) | |||
894 | 1037 | ||
895 | } | 1038 | } |
896 | else { | 1039 | else { |
897 | handle_error ( session, error_busy, msg->friend_id ); | 1040 | handle_error ( session, call, error_busy, msg->friend_id ); /* TODO: Ugh*/ |
898 | return 0; | 1041 | return 0; |
899 | } | 1042 | } |
900 | } | 1043 | } |
901 | 1044 | ||
902 | if ( !msg->callid.header_value ) { | 1045 | if ( !msg->callid.header_value ) { |
903 | handle_error ( session, error_no_callid, msg->friend_id ); | 1046 | handle_error ( session, call, error_no_callid, msg->friend_id ); |
904 | return 0; | 1047 | return 0; |
905 | } | 1048 | } |
906 | 1049 | ||
907 | session->call = init_call ( session, 1, 0 ); | 1050 | MSICall* new_call = init_call ( session, 1, 0 ); |
908 | memcpy ( session->call->id, msg->callid.header_value, CALL_ID_LEN ); | 1051 | |
909 | session->call->state = call_starting; | 1052 | if ( !new_call ) { |
1053 | handle_error ( session, call, error_busy, msg->friend_id ); | ||
1054 | return 0; | ||
1055 | } | ||
1056 | |||
1057 | memcpy ( new_call->id, msg->callid.header_value, CALL_ID_LEN ); | ||
1058 | new_call->state = call_starting; | ||
910 | 1059 | ||
911 | add_peer( session->call, msg->friend_id); | 1060 | add_peer( new_call, msg->friend_id); |
912 | 1061 | ||
913 | flush_peer_type ( session, msg, 0 ); | 1062 | flush_peer_type ( new_call, msg, 0 ); |
914 | 1063 | ||
915 | MSIMessage *_msg_ringing = msi_new_message ( TYPE_RESPONSE, stringify_response ( ringing ) ); | 1064 | MSIMessage *_msg_ringing = msi_new_message ( TYPE_RESPONSE, stringify_response ( ringing ) ); |
916 | send_message ( session, _msg_ringing, msg->friend_id ); | 1065 | send_message ( session, new_call, _msg_ringing, msg->friend_id ); |
917 | free_message ( _msg_ringing ); | 1066 | free_message ( _msg_ringing ); |
918 | 1067 | ||
919 | invoke_callback(MSI_OnInvite); | 1068 | invoke_callback(new_call->call_idx, MSI_OnInvite); |
920 | 1069 | ||
921 | return 1; | 1070 | return 1; |
922 | } | 1071 | } |
923 | int handle_recv_start ( MSISession *session, MSIMessage *msg ) | 1072 | int handle_recv_start ( MSISession *session, MSICall* call, MSIMessage *msg ) |
924 | { | 1073 | { |
925 | assert ( session ); | 1074 | LOGGER_DEBUG("Handling 'start' on call: %s", call->id ); |
926 | 1075 | ||
927 | if ( has_call_error ( session, msg ) == 0 ) | 1076 | if ( has_call_error ( session, call, msg ) == 0 ) |
928 | return 0; | 1077 | return -1; |
929 | 1078 | ||
930 | if ( !msg->cryptokey.header_value ) | 1079 | if ( !msg->cryptokey.header_value ) |
931 | return handle_error ( session, error_no_crypto_key, msg->friend_id ); | 1080 | return handle_error ( session, call, error_no_crypto_key, msg->friend_id ); |
932 | 1081 | ||
933 | session->call->state = call_active; | 1082 | call->state = call_active; |
934 | 1083 | ||
935 | session->call->key_peer = calloc ( sizeof ( uint8_t ), crypto_secretbox_KEYBYTES ); | 1084 | call->key_peer = calloc ( sizeof ( uint8_t ), crypto_secretbox_KEYBYTES ); |
936 | memcpy ( session->call->key_peer, msg->cryptokey.header_value, crypto_secretbox_KEYBYTES ); | 1085 | memcpy ( call->key_peer, msg->cryptokey.header_value, crypto_secretbox_KEYBYTES ); |
937 | 1086 | ||
938 | session->call->nonce_peer = calloc ( sizeof ( uint8_t ), crypto_secretbox_NONCEBYTES ); | 1087 | call->nonce_peer = calloc ( sizeof ( uint8_t ), crypto_secretbox_NONCEBYTES ); |
939 | memcpy ( session->call->nonce_peer, msg->nonce.header_value, crypto_secretbox_NONCEBYTES ); | 1088 | memcpy ( call->nonce_peer, msg->nonce.header_value, crypto_secretbox_NONCEBYTES ); |
940 | 1089 | ||
941 | flush_peer_type ( session, msg, 0 ); | 1090 | flush_peer_type ( call, msg, 0 ); |
942 | 1091 | ||
943 | invoke_callback(MSI_OnStart); | 1092 | invoke_callback(call->call_idx, MSI_OnStart); |
944 | 1093 | ||
945 | return 1; | 1094 | return 1; |
946 | } | 1095 | } |
947 | int handle_recv_reject ( MSISession *session, MSIMessage *msg ) | 1096 | int handle_recv_reject ( MSISession *session, MSICall* call, MSIMessage *msg ) |
948 | { | 1097 | { |
949 | assert ( session ); | 1098 | LOGGER_DEBUG("Handling 'reject' on call: %s", call->id ); |
950 | 1099 | ||
951 | if ( has_call_error ( session, msg ) == 0 ) | 1100 | if ( has_call_error ( session, call, msg ) == 0 ) |
952 | return 0; | 1101 | return 0; |
953 | 1102 | ||
954 | 1103 | ||
955 | MSIMessage *_msg_ending = msi_new_message ( TYPE_RESPONSE, stringify_response ( ending ) ); | 1104 | MSIMessage *_msg_ending = msi_new_message ( TYPE_RESPONSE, stringify_response ( ending ) ); |
956 | send_message ( session, _msg_ending, msg->friend_id ); | 1105 | send_message ( session, call, _msg_ending, msg->friend_id ); |
957 | free_message ( _msg_ending ); | 1106 | free_message ( _msg_ending ); |
958 | 1107 | ||
959 | 1108 | ||
960 | invoke_callback(MSI_OnReject); | 1109 | invoke_callback(call->call_idx, MSI_OnReject); |
961 | /* | 1110 | /* |
962 | event.timer_release ( session->call->request_timer_id ); | 1111 | event.timer_release ( session->call->request_timer_id ); |
963 | session->call->request_timer_id = event.timer_alloc ( handle_timeout, session, m_deftout ); | 1112 | session->call->request_timer_id = event.timer_alloc ( handle_timeout, session, m_deftout ); |
964 | */ | 1113 | */ |
965 | 1114 | ||
966 | terminate_call(session); | 1115 | terminate_call(session, call); |
967 | 1116 | ||
968 | return 1; | 1117 | return 1; |
969 | } | 1118 | } |
970 | int handle_recv_cancel ( MSISession *session, MSIMessage *msg ) | 1119 | int handle_recv_cancel ( MSISession *session, MSICall* call, MSIMessage *msg ) |
971 | { | 1120 | { |
972 | assert ( session ); | 1121 | LOGGER_DEBUG("Handling 'cancel' on call: %s", call->id ); |
973 | 1122 | ||
974 | if ( has_call_error ( session, msg ) == 0 ) | 1123 | if ( has_call_error ( session, call, msg ) == 0 ) |
975 | return 0; | 1124 | return 0; |
976 | 1125 | ||
977 | /* Act as end message */ | 1126 | /* Act as end message */ |
978 | 1127 | ||
979 | MSIMessage *_msg_ending = msi_new_message ( TYPE_RESPONSE, stringify_response ( ending ) ); | 1128 | MSIMessage *_msg_ending = msi_new_message ( TYPE_RESPONSE, stringify_response ( ending ) ); |
980 | send_message ( session, _msg_ending, msg->friend_id ); | 1129 | send_message ( session, call, _msg_ending, msg->friend_id ); |
981 | free_message ( _msg_ending ); | 1130 | free_message ( _msg_ending ); |
982 | 1131 | ||
983 | invoke_callback(MSI_OnCancel); | 1132 | invoke_callback(call->call_idx, MSI_OnCancel); |
984 | 1133 | ||
985 | terminate_call ( session ); | 1134 | terminate_call ( session, call ); |
986 | 1135 | ||
987 | return 1; | 1136 | return 1; |
988 | } | 1137 | } |
989 | int handle_recv_end ( MSISession *session, MSIMessage *msg ) | 1138 | int handle_recv_end ( MSISession *session, MSICall* call, MSIMessage *msg ) |
990 | { | 1139 | { |
991 | assert ( session ); | 1140 | LOGGER_DEBUG("Handling 'end' on call: %s", call->id ); |
992 | 1141 | ||
993 | if ( has_call_error ( session, msg ) == 0 ) | 1142 | if ( has_call_error ( session, call, msg ) == 0 ) |
994 | return 0; | 1143 | return 0; |
995 | 1144 | ||
996 | 1145 | ||
997 | MSIMessage *_msg_ending = msi_new_message ( TYPE_RESPONSE, stringify_response ( ending ) ); | 1146 | MSIMessage *_msg_ending = msi_new_message ( TYPE_RESPONSE, stringify_response ( ending ) ); |
998 | send_message ( session, _msg_ending, msg->friend_id ); | 1147 | send_message ( session, call, _msg_ending, msg->friend_id ); |
999 | free_message ( _msg_ending ); | 1148 | free_message ( _msg_ending ); |
1000 | 1149 | ||
1001 | invoke_callback(MSI_OnEnd); | 1150 | invoke_callback(call->call_idx, MSI_OnEnd); |
1002 | 1151 | ||
1003 | terminate_call ( session ); | 1152 | terminate_call ( session, call ); |
1004 | return 1; | 1153 | return 1; |
1005 | } | 1154 | } |
1006 | 1155 | ||
1007 | /********** Response handlers **********/ | 1156 | /********** Response handlers **********/ |
1008 | int handle_recv_ringing ( MSISession *session, MSIMessage *msg ) | 1157 | int handle_recv_ringing ( MSISession *session, MSICall* call, MSIMessage *msg ) |
1009 | { | 1158 | { |
1010 | assert ( session ); | 1159 | LOGGER_DEBUG("Handling 'ringing' on call: %s", call->id ); |
1011 | 1160 | ||
1012 | if ( has_call_error ( session, msg ) == 0 ) | 1161 | if ( has_call_error ( session, call, msg ) == 0 ) |
1013 | return 0; | 1162 | return 0; |
1014 | 1163 | ||
1015 | session->call->ringing_timer_id = event.timer_alloc ( handle_timeout, session, session->call->ringing_tout_ms ); | 1164 | call->ringing_timer_id = event.timer_alloc ( handle_timeout, call, call->ringing_tout_ms ); |
1016 | 1165 | ||
1017 | invoke_callback(MSI_OnRinging); | 1166 | invoke_callback(call->call_idx, MSI_OnRinging); |
1018 | 1167 | ||
1019 | return 1; | 1168 | return 1; |
1020 | } | 1169 | } |
1021 | int handle_recv_starting ( MSISession *session, MSIMessage *msg ) | 1170 | int handle_recv_starting ( MSISession *session, MSICall* call, MSIMessage *msg ) |
1022 | { | 1171 | { |
1023 | assert ( session ); | 1172 | LOGGER_DEBUG("Handling 'starting' on call: %s", call->id ); |
1024 | 1173 | ||
1025 | if ( has_call_error ( session, msg ) == 0 ) | 1174 | if ( has_call_error ( session, call, msg ) == 0 ) |
1026 | return 0; | 1175 | return 0; |
1027 | 1176 | ||
1028 | if ( !msg->cryptokey.header_value ) { | 1177 | if ( !msg->cryptokey.header_value ) { |
1029 | return handle_error ( session, error_no_crypto_key, msg->friend_id ); | 1178 | return handle_error ( session, call, error_no_crypto_key, msg->friend_id ); |
1030 | } | 1179 | } |
1031 | 1180 | ||
1032 | /* Generate local key/nonce to send */ | 1181 | /* Generate local key/nonce to send */ |
1033 | session->call->key_local = calloc ( sizeof ( uint8_t ), crypto_secretbox_KEYBYTES ); | 1182 | call->key_local = calloc ( sizeof ( uint8_t ), crypto_secretbox_KEYBYTES ); |
1034 | new_symmetric_key ( session->call->key_local ); | 1183 | new_symmetric_key ( call->key_local ); |
1035 | 1184 | ||
1036 | session->call->nonce_local = calloc ( sizeof ( uint8_t ), crypto_secretbox_NONCEBYTES ); | 1185 | call->nonce_local = calloc ( sizeof ( uint8_t ), crypto_secretbox_NONCEBYTES ); |
1037 | new_nonce ( session->call->nonce_local ); | 1186 | new_nonce ( call->nonce_local ); |
1038 | 1187 | ||
1039 | /* Save peer key/nonce */ | 1188 | /* Save peer key/nonce */ |
1040 | session->call->key_peer = calloc ( sizeof ( uint8_t ), crypto_secretbox_KEYBYTES ); | 1189 | call->key_peer = calloc ( sizeof ( uint8_t ), crypto_secretbox_KEYBYTES ); |
1041 | memcpy ( session->call->key_peer, msg->cryptokey.header_value, crypto_secretbox_KEYBYTES ); | 1190 | memcpy ( call->key_peer, msg->cryptokey.header_value, crypto_secretbox_KEYBYTES ); |
1042 | 1191 | ||
1043 | session->call->nonce_peer = calloc ( sizeof ( uint8_t ), crypto_secretbox_NONCEBYTES ); | 1192 | call->nonce_peer = calloc ( sizeof ( uint8_t ), crypto_secretbox_NONCEBYTES ); |
1044 | memcpy ( session->call->nonce_peer, msg->nonce.header_value, crypto_secretbox_NONCEBYTES ); | 1193 | memcpy ( call->nonce_peer, msg->nonce.header_value, crypto_secretbox_NONCEBYTES ); |
1045 | 1194 | ||
1046 | session->call->state = call_active; | 1195 | call->state = call_active; |
1047 | 1196 | ||
1048 | MSIMessage *_msg_start = msi_new_message ( TYPE_REQUEST, stringify_request ( start ) ); | 1197 | MSIMessage *_msg_start = msi_new_message ( TYPE_REQUEST, stringify_request ( start ) ); |
1049 | msi_msg_set_cryptokey ( _msg_start, session->call->key_local, crypto_secretbox_KEYBYTES ); | 1198 | msi_msg_set_cryptokey ( _msg_start, call->key_local, crypto_secretbox_KEYBYTES ); |
1050 | msi_msg_set_nonce ( _msg_start, session->call->nonce_local, crypto_secretbox_NONCEBYTES ); | 1199 | msi_msg_set_nonce ( _msg_start, call->nonce_local, crypto_secretbox_NONCEBYTES ); |
1051 | send_message ( session, _msg_start, msg->friend_id ); | 1200 | send_message ( session, call, _msg_start, msg->friend_id ); |
1052 | free_message ( _msg_start ); | 1201 | free_message ( _msg_start ); |
1053 | 1202 | ||
1054 | flush_peer_type ( session, msg, 0 ); | 1203 | flush_peer_type ( call, msg, 0 ); |
1055 | 1204 | ||
1056 | invoke_callback(MSI_OnStarting); | 1205 | invoke_callback(call->call_idx, MSI_OnStarting); |
1057 | 1206 | ||
1058 | event.timer_release ( session->call->ringing_timer_id ); | 1207 | event.timer_release ( call->ringing_timer_id ); |
1059 | 1208 | ||
1060 | return 1; | 1209 | return 1; |
1061 | } | 1210 | } |
1062 | int handle_recv_ending ( MSISession *session, MSIMessage *msg ) | 1211 | int handle_recv_ending ( MSISession *session, MSICall* call, MSIMessage *msg ) |
1063 | { | 1212 | { |
1064 | assert ( session ); | 1213 | LOGGER_DEBUG("Handling 'ending' on call: %s", call->id ); |
1065 | 1214 | ||
1066 | if ( has_call_error ( session, msg ) == 0 ) | 1215 | if ( has_call_error ( session, call, msg ) == 0 ) |
1067 | return 0; | 1216 | return 0; |
1068 | 1217 | ||
1069 | /* Stop timer */ | 1218 | /* Stop timer */ |
1070 | event.timer_release ( session->call->request_timer_id ); | 1219 | event.timer_release ( call->request_timer_id ); |
1071 | 1220 | ||
1072 | invoke_callback(MSI_OnEnding); | 1221 | invoke_callback(call->call_idx, MSI_OnEnding); |
1073 | 1222 | ||
1074 | /* Terminate call */ | 1223 | /* Terminate call */ |
1075 | terminate_call ( session ); | 1224 | terminate_call ( session, call ); |
1076 | 1225 | ||
1077 | return 1; | 1226 | return 1; |
1078 | } | 1227 | } |
1079 | int handle_recv_error ( MSISession *session, MSIMessage *msg ) | 1228 | int handle_recv_error ( MSISession *session, MSICall* call, MSIMessage *msg ) |
1080 | { | 1229 | { |
1081 | assert ( session ); | 1230 | if ( !call ) { |
1082 | assert ( session->call ); | 1231 | LOGGER_WARNING("Handling 'error' on non-existing call!"); |
1232 | return -1; | ||
1233 | } | ||
1234 | |||
1235 | LOGGER_DEBUG("Handling 'error' on call: %s", call->id ); | ||
1083 | 1236 | ||
1084 | /* Handle error accordingly */ | 1237 | /* Handle error accordingly */ |
1085 | if ( msg->reason.header_value ) { | 1238 | if ( msg->reason.header_value ) { |
1086 | session->last_error_id = atoi ( ( const char * ) msg->reason.header_value ); | 1239 | session->last_error_id = atoi ( ( const char * ) msg->reason.header_value ); |
1087 | session->last_error_str = stringify_error ( session->last_error_id ); | 1240 | session->last_error_str = stringify_error ( session->last_error_id ); |
1241 | LOGGER_DEBUG("Error reason: %s", session->last_error_str); | ||
1088 | } | 1242 | } |
1089 | 1243 | ||
1090 | invoke_callback(MSI_OnEnding); | 1244 | invoke_callback(call->call_idx, MSI_OnEnding); |
1091 | 1245 | ||
1092 | terminate_call ( session ); | 1246 | terminate_call ( session, call ); |
1093 | return 1; | 1247 | return 1; |
1094 | } | 1248 | } |
1095 | 1249 | ||
@@ -1128,26 +1282,40 @@ int handle_recv_error ( MSISession *session, MSIMessage *msg ) | |||
1128 | */ | 1282 | */ |
1129 | void msi_handle_packet ( Messenger *messenger, int source, uint8_t *data, uint16_t length, void *object ) | 1283 | void msi_handle_packet ( Messenger *messenger, int source, uint8_t *data, uint16_t length, void *object ) |
1130 | { | 1284 | { |
1285 | LOGGER_DEBUG("Got msi message"); | ||
1131 | /* Unused */ | 1286 | /* Unused */ |
1132 | (void)messenger; | 1287 | (void)messenger; |
1133 | 1288 | ||
1134 | MSISession *_session = object; | 1289 | MSISession *_session = object; |
1135 | MSIMessage *_msg; | 1290 | MSIMessage *_msg; |
1136 | 1291 | ||
1137 | if ( !length ) return; | 1292 | if ( !length ) { |
1293 | LOGGER_WARNING("Lenght param negative"); | ||
1294 | return; | ||
1295 | } | ||
1138 | 1296 | ||
1139 | _msg = parse_message ( data, length ); | 1297 | _msg = parse_message ( data, length ); |
1140 | 1298 | ||
1141 | if ( !_msg ) return; | 1299 | if ( !_msg ) { |
1300 | LOGGER_WARNING("Error parsing message"); | ||
1301 | return; | ||
1302 | } else { | ||
1303 | LOGGER_DEBUG("Successfully parsed message"); | ||
1304 | } | ||
1142 | 1305 | ||
1143 | _msg->friend_id = source; | 1306 | _msg->friend_id = source; |
1144 | 1307 | ||
1145 | 1308 | /* Find what call */ | |
1309 | MSICall* _call = _msg->callid.header_value ? find_call(_session, _msg->callid.header_value ) : NULL; | ||
1310 | |||
1146 | /* Now handle message */ | 1311 | /* Now handle message */ |
1147 | 1312 | ||
1148 | if ( _msg->request.header_value ) { /* Handle request */ | 1313 | if ( _msg->request.header_value ) { /* Handle request */ |
1149 | 1314 | ||
1150 | if ( _msg->response.size > 32 ) goto free_end; | 1315 | if ( _msg->response.size > 32 ) { |
1316 | LOGGER_WARNING("Header size too big"); | ||
1317 | goto free_end; | ||
1318 | } | ||
1151 | 1319 | ||
1152 | uint8_t _request_value[32]; | 1320 | uint8_t _request_value[32]; |
1153 | 1321 | ||
@@ -1155,26 +1323,30 @@ void msi_handle_packet ( Messenger *messenger, int source, uint8_t *data, uint16 | |||
1155 | _request_value[_msg->request.size] = '\0'; | 1323 | _request_value[_msg->request.size] = '\0'; |
1156 | 1324 | ||
1157 | if ( same ( _request_value, stringify_request ( invite ) ) ) { | 1325 | if ( same ( _request_value, stringify_request ( invite ) ) ) { |
1158 | handle_recv_invite ( _session, _msg ); | 1326 | handle_recv_invite ( _session, _call, _msg ); |
1159 | 1327 | ||
1160 | } else if ( same ( _request_value, stringify_request ( start ) ) ) { | 1328 | } else if ( same ( _request_value, stringify_request ( start ) ) ) { |
1161 | handle_recv_start ( _session, _msg ); | 1329 | handle_recv_start ( _session, _call, _msg ); |
1162 | 1330 | ||
1163 | } else if ( same ( _request_value, stringify_request ( cancel ) ) ) { | 1331 | } else if ( same ( _request_value, stringify_request ( cancel ) ) ) { |
1164 | handle_recv_cancel ( _session, _msg ); | 1332 | handle_recv_cancel ( _session, _call, _msg ); |
1165 | 1333 | ||
1166 | } else if ( same ( _request_value, stringify_request ( reject ) ) ) { | 1334 | } else if ( same ( _request_value, stringify_request ( reject ) ) ) { |
1167 | handle_recv_reject ( _session, _msg ); | 1335 | handle_recv_reject ( _session, _call, _msg ); |
1168 | 1336 | ||
1169 | } else if ( same ( _request_value, stringify_request ( end ) ) ) { | 1337 | } else if ( same ( _request_value, stringify_request ( end ) ) ) { |
1170 | handle_recv_end ( _session, _msg ); | 1338 | handle_recv_end ( _session, _call, _msg ); |
1339 | } else { | ||
1340 | LOGGER_WARNING("Uknown request"); | ||
1341 | goto free_end; | ||
1171 | } | 1342 | } |
1172 | 1343 | ||
1173 | else goto free_end; | ||
1174 | |||
1175 | } else if ( _msg->response.header_value ) { /* Handle response */ | 1344 | } else if ( _msg->response.header_value ) { /* Handle response */ |
1176 | 1345 | ||
1177 | if ( _msg->response.size > 32 ) goto free_end; | 1346 | if ( _msg->response.size > 32 ) { |
1347 | LOGGER_WARNING("Header size too big"); | ||
1348 | goto free_end; | ||
1349 | } | ||
1178 | 1350 | ||
1179 | uint8_t _response_value[32]; | 1351 | uint8_t _response_value[32]; |
1180 | 1352 | ||
@@ -1182,23 +1354,28 @@ void msi_handle_packet ( Messenger *messenger, int source, uint8_t *data, uint16 | |||
1182 | _response_value[_msg->response.size] = '\0'; | 1354 | _response_value[_msg->response.size] = '\0'; |
1183 | 1355 | ||
1184 | if ( same ( _response_value, stringify_response ( ringing ) ) ) { | 1356 | if ( same ( _response_value, stringify_response ( ringing ) ) ) { |
1185 | handle_recv_ringing ( _session, _msg ); | 1357 | handle_recv_ringing ( _session, _call, _msg ); |
1186 | 1358 | ||
1187 | } else if ( same ( _response_value, stringify_response ( starting ) ) ) { | 1359 | } else if ( same ( _response_value, stringify_response ( starting ) ) ) { |
1188 | handle_recv_starting ( _session, _msg ); | 1360 | handle_recv_starting ( _session, _call, _msg ); |
1189 | 1361 | ||
1190 | } else if ( same ( _response_value, stringify_response ( ending ) ) ) { | 1362 | } else if ( same ( _response_value, stringify_response ( ending ) ) ) { |
1191 | handle_recv_ending ( _session, _msg ); | 1363 | handle_recv_ending ( _session, _call, _msg ); |
1192 | 1364 | ||
1193 | } else if ( same ( _response_value, stringify_response ( error ) ) ) { | 1365 | } else if ( same ( _response_value, stringify_response ( error ) ) ) { |
1194 | handle_recv_error ( _session, _msg ); | 1366 | handle_recv_error ( _session, _call, _msg ); |
1195 | 1367 | ||
1196 | } else goto free_end; | 1368 | } else { |
1369 | LOGGER_WARNING("Uknown response"); | ||
1370 | goto free_end; | ||
1371 | } | ||
1197 | 1372 | ||
1198 | /* Got response so cancel timer */ | 1373 | /* Got response so cancel timer */ |
1199 | if ( _session->call ) | 1374 | if ( _call ) |
1200 | event.timer_release ( _session->call->request_timer_id ); | 1375 | event.timer_release ( _call->request_timer_id ); |
1201 | 1376 | ||
1377 | } else { | ||
1378 | LOGGER_WARNING("Invalid message: no resp nor requ headers"); | ||
1202 | } | 1379 | } |
1203 | 1380 | ||
1204 | free_end:free_message ( _msg ); | 1381 | free_end:free_message ( _msg ); |
@@ -1248,21 +1425,31 @@ void msi_register_callback ( MSICallback callback, MSICallbackID id, void* userd | |||
1248 | * @brief Start the control session. | 1425 | * @brief Start the control session. |
1249 | * | 1426 | * |
1250 | * @param messenger Tox* object. | 1427 | * @param messenger Tox* object. |
1251 | * @param user_agent User agent, i.e. 'Venom'; 'QT-gui' | 1428 | * @param max_calls Amount of calls possible |
1252 | * @return MSISession* The created session. | 1429 | * @return MSISession* The created session. |
1253 | * @retval NULL Error occured. | 1430 | * @retval NULL Error occured. |
1254 | */ | 1431 | */ |
1255 | MSISession *msi_init_session ( Messenger* messenger ) | 1432 | MSISession *msi_init_session ( Messenger* messenger, uint32_t max_calls ) |
1256 | { | 1433 | { |
1257 | assert ( messenger ); | 1434 | if (messenger == NULL) { |
1435 | LOGGER_ERROR("Could not init session on empty messenger!"); | ||
1436 | return NULL; | ||
1437 | } | ||
1258 | 1438 | ||
1439 | if ( !max_calls) return NULL; | ||
1440 | |||
1259 | MSISession *_retu = calloc ( sizeof ( MSISession ), 1 ); | 1441 | MSISession *_retu = calloc ( sizeof ( MSISession ), 1 ); |
1260 | assert ( _retu ); | 1442 | |
1443 | if (_retu == NULL) { | ||
1444 | LOGGER_ERROR("Allocation failed!"); | ||
1445 | return NULL; | ||
1446 | } | ||
1261 | 1447 | ||
1262 | _retu->messenger_handle = messenger; | 1448 | _retu->messenger_handle = messenger; |
1263 | _retu->agent_handler = NULL; | 1449 | _retu->agent_handler = NULL; |
1264 | 1450 | ||
1265 | _retu->call = NULL; | 1451 | _retu->calls = calloc( sizeof (MSICall*), max_calls ); |
1452 | _retu->max_calls = max_calls; | ||
1266 | 1453 | ||
1267 | _retu->frequ = 10000; /* default value? */ | 1454 | _retu->frequ = 10000; /* default value? */ |
1268 | _retu->call_timeout = 30000; /* default value? */ | 1455 | _retu->call_timeout = 30000; /* default value? */ |
@@ -1272,7 +1459,8 @@ MSISession *msi_init_session ( Messenger* messenger ) | |||
1272 | 1459 | ||
1273 | /* This is called when remote terminates session */ | 1460 | /* This is called when remote terminates session */ |
1274 | m_callback_connectionstatus_internal_av(messenger, handle_remote_connection_change, _retu); | 1461 | m_callback_connectionstatus_internal_av(messenger, handle_remote_connection_change, _retu); |
1275 | 1462 | ||
1463 | LOGGER_DEBUG("New msi session: %p max calls: %u", _retu, max_calls); | ||
1276 | return _retu; | 1464 | return _retu; |
1277 | } | 1465 | } |
1278 | 1466 | ||
@@ -1285,16 +1473,20 @@ MSISession *msi_init_session ( Messenger* messenger ) | |||
1285 | */ | 1473 | */ |
1286 | int msi_terminate_session ( MSISession *session ) | 1474 | int msi_terminate_session ( MSISession *session ) |
1287 | { | 1475 | { |
1288 | assert ( session ); | 1476 | if (session == NULL) { |
1477 | LOGGER_ERROR("Tried to terminate non-existing session"); | ||
1478 | return -1; | ||
1479 | } | ||
1289 | 1480 | ||
1290 | int _status = 0; | 1481 | int _status = 0; |
1291 | 1482 | ||
1292 | /* If have call, cancel it */ | 1483 | /* If have calls, cancel them */ |
1293 | if ( session->call ) { | 1484 | uint32_t idx = 0; |
1485 | for (; idx < session->max_calls; idx ++) if ( session->calls[idx] ) { | ||
1294 | /* Cancel all? */ | 1486 | /* Cancel all? */ |
1295 | uint16_t _it = 0; | 1487 | uint16_t _it = 0; |
1296 | for ( ; _it < session->call->peer_count; _it++ ) | 1488 | for ( ; _it < session->calls[idx]->peer_count; _it++ ) |
1297 | msi_cancel ( session, session->call->peers [_it], "MSI session terminated!" ); | 1489 | msi_cancel ( session, idx, session->calls[idx]->peers [_it], "MSI session terminated!" ); |
1298 | } | 1490 | } |
1299 | 1491 | ||
1300 | m_callback_msi_packet((struct Messenger *) session->messenger_handle, NULL, NULL); | 1492 | m_callback_msi_packet((struct Messenger *) session->messenger_handle, NULL, NULL); |
@@ -1313,35 +1505,39 @@ int msi_terminate_session ( MSISession *session ) | |||
1313 | * @param friend_id The friend. | 1505 | * @param friend_id The friend. |
1314 | * @return int | 1506 | * @return int |
1315 | */ | 1507 | */ |
1316 | int msi_invite ( MSISession *session, MSICallType call_type, uint32_t rngsec, uint32_t friend_id ) | 1508 | int msi_invite ( MSISession* session, uint32_t* call_index, MSICallType call_type, uint32_t rngsec, uint32_t friend_id ) |
1317 | { | 1509 | { |
1318 | assert ( session ); | 1510 | LOGGER_DEBUG("Inviting friend: %u", friend_id); |
1319 | 1511 | ||
1320 | MSIMessage *_msg_invite = msi_new_message ( TYPE_REQUEST, stringify_request ( invite ) ); | 1512 | MSIMessage *_msg_invite = msi_new_message ( TYPE_REQUEST, stringify_request ( invite ) ); |
1513 | |||
1514 | MSICall* _call = init_call ( session, 1, rngsec ); /* Just one for now */ | ||
1515 | if ( !_call ) return -1; /* Cannot handle more calls */ | ||
1516 | |||
1517 | *call_index = _call->call_idx; | ||
1518 | |||
1519 | t_randomstr ( _call->id, CALL_ID_LEN ); | ||
1321 | 1520 | ||
1322 | session->call = init_call ( session, 1, rngsec ); /* Just one for now */ | 1521 | add_peer(_call, friend_id ); |
1323 | t_randomstr ( session->call->id, CALL_ID_LEN ); | ||
1324 | |||
1325 | add_peer(session->call, friend_id ); | ||
1326 | 1522 | ||
1327 | session->call->type_local = call_type; | 1523 | _call->type_local = call_type; |
1524 | |||
1328 | /* Do whatever with message */ | 1525 | /* Do whatever with message */ |
1329 | |||
1330 | if ( call_type == type_audio ) { | 1526 | if ( call_type == type_audio ) { |
1331 | msi_msg_set_calltype | 1527 | msi_msg_set_calltype ( _msg_invite, ( const uint8_t * ) CT_AUDIO_HEADER_VALUE, strlen ( CT_AUDIO_HEADER_VALUE ) ); |
1332 | ( _msg_invite, ( const uint8_t * ) CT_AUDIO_HEADER_VALUE, strlen ( CT_AUDIO_HEADER_VALUE ) ); | ||
1333 | } else { | 1528 | } else { |
1334 | msi_msg_set_calltype | 1529 | msi_msg_set_calltype ( _msg_invite, ( const uint8_t * ) CT_VIDEO_HEADER_VALUE, strlen ( CT_VIDEO_HEADER_VALUE ) ); |
1335 | ( _msg_invite, ( const uint8_t * ) CT_VIDEO_HEADER_VALUE, strlen ( CT_VIDEO_HEADER_VALUE ) ); | ||
1336 | } | 1530 | } |
1337 | 1531 | ||
1338 | send_message ( session, _msg_invite, friend_id ); | 1532 | send_message ( session, _call, _msg_invite, friend_id ); |
1339 | free_message ( _msg_invite ); | 1533 | free_message ( _msg_invite ); |
1340 | 1534 | ||
1341 | session->call->state = call_inviting; | 1535 | _call->state = call_inviting; |
1342 | |||
1343 | session->call->request_timer_id = event.timer_alloc ( handle_timeout, session, m_deftout ); | ||
1344 | 1536 | ||
1537 | _call->request_timer_id = event.timer_alloc ( handle_timeout, _call, m_deftout ); | ||
1538 | |||
1539 | LOGGER_DEBUG("Invite sent"); | ||
1540 | |||
1345 | return 0; | 1541 | return 0; |
1346 | } | 1542 | } |
1347 | 1543 | ||
@@ -1350,29 +1546,37 @@ int msi_invite ( MSISession *session, MSICallType call_type, uint32_t rngsec, ui | |||
1350 | * @brief Hangup active call. | 1546 | * @brief Hangup active call. |
1351 | * | 1547 | * |
1352 | * @param session Control session. | 1548 | * @param session Control session. |
1549 | * @param call_id To which call is this action handled. | ||
1353 | * @return int | 1550 | * @return int |
1354 | * @retval -1 Error occured. | 1551 | * @retval -1 Error occured. |
1355 | * @retval 0 Success. | 1552 | * @retval 0 Success. |
1356 | */ | 1553 | */ |
1357 | int msi_hangup ( MSISession *session ) | 1554 | int msi_hangup ( MSISession* session, uint32_t call_index ) |
1358 | { | 1555 | { |
1359 | assert ( session ); | 1556 | LOGGER_DEBUG("Hanging up call: %u", call_index); |
1360 | 1557 | ||
1361 | if ( !session->call || session->call->state != call_active ) | 1558 | if ( call_index >= session->max_calls || !session->calls[call_index] ) { |
1559 | LOGGER_ERROR("Invalid call index!"); | ||
1560 | return -1; | ||
1561 | } | ||
1562 | |||
1563 | if ( !session->calls[call_index] || session->calls[call_index]->state != call_active ) { | ||
1564 | LOGGER_ERROR("No call with such index or call is not active!"); | ||
1362 | return -1; | 1565 | return -1; |
1566 | } | ||
1363 | 1567 | ||
1364 | MSIMessage *_msg_end = msi_new_message ( TYPE_REQUEST, stringify_request ( end ) ); | 1568 | MSIMessage *_msg_end = msi_new_message ( TYPE_REQUEST, stringify_request ( end ) ); |
1365 | 1569 | ||
1366 | /* hangup for each peer */ | 1570 | /* hangup for each peer */ |
1367 | int _it = 0; | 1571 | int _it = 0; |
1368 | 1572 | ||
1369 | for ( ; _it < session->call->peer_count; _it ++ ) | 1573 | for ( ; _it < session->calls[call_index]->peer_count; _it ++ ) |
1370 | send_message ( session, _msg_end, session->call->peers[_it] ); | 1574 | send_message ( session, session->calls[call_index], _msg_end, session->calls[call_index]->peers[_it] ); |
1371 | 1575 | ||
1372 | 1576 | ||
1373 | free_message ( _msg_end ); | 1577 | free_message ( _msg_end ); |
1374 | 1578 | ||
1375 | session->call->request_timer_id = event.timer_alloc ( handle_timeout, session, m_deftout ); | 1579 | session->calls[call_index]->request_timer_id = event.timer_alloc ( handle_timeout, session->calls[call_index], m_deftout ); |
1376 | 1580 | ||
1377 | return 0; | 1581 | return 0; |
1378 | } | 1582 | } |
@@ -1382,15 +1586,22 @@ int msi_hangup ( MSISession *session ) | |||
1382 | * @brief Answer active call request. | 1586 | * @brief Answer active call request. |
1383 | * | 1587 | * |
1384 | * @param session Control session. | 1588 | * @param session Control session. |
1589 | * @param call_id To which call is this action handled. | ||
1385 | * @param call_type Answer with Audio or Video(both). | 1590 | * @param call_type Answer with Audio or Video(both). |
1386 | * @return int | 1591 | * @return int |
1387 | */ | 1592 | */ |
1388 | int msi_answer ( MSISession *session, MSICallType call_type ) | 1593 | int msi_answer ( MSISession* session, uint32_t call_index, MSICallType call_type ) |
1389 | { | 1594 | { |
1390 | assert ( session ); | 1595 | LOGGER_DEBUG("Answering call: %u", call_index); |
1391 | 1596 | ||
1597 | if ( call_index >= session->max_calls || !session->calls[call_index] ){ | ||
1598 | LOGGER_ERROR("Invalid call index!"); | ||
1599 | return -1; | ||
1600 | } | ||
1601 | |||
1392 | MSIMessage *_msg_starting = msi_new_message ( TYPE_RESPONSE, stringify_response ( starting ) ); | 1602 | MSIMessage *_msg_starting = msi_new_message ( TYPE_RESPONSE, stringify_response ( starting ) ); |
1393 | session->call->type_local = call_type; | 1603 | |
1604 | session->calls[call_index]->type_local = call_type; | ||
1394 | 1605 | ||
1395 | if ( call_type == type_audio ) { | 1606 | if ( call_type == type_audio ) { |
1396 | msi_msg_set_calltype | 1607 | msi_msg_set_calltype |
@@ -1402,19 +1613,19 @@ int msi_answer ( MSISession *session, MSICallType call_type ) | |||
1402 | 1613 | ||
1403 | /* Now set the local encryption key and pass it with STARTING message */ | 1614 | /* Now set the local encryption key and pass it with STARTING message */ |
1404 | 1615 | ||
1405 | session->call->key_local = calloc ( sizeof ( uint8_t ), crypto_secretbox_KEYBYTES ); | 1616 | session->calls[call_index]->key_local = calloc ( sizeof ( uint8_t ), crypto_secretbox_KEYBYTES ); |
1406 | new_symmetric_key ( session->call->key_local ); | 1617 | new_symmetric_key ( session->calls[call_index]->key_local ); |
1407 | 1618 | ||
1408 | session->call->nonce_local = calloc ( sizeof ( uint8_t ), crypto_secretbox_NONCEBYTES ); | 1619 | session->calls[call_index]->nonce_local = calloc ( sizeof ( uint8_t ), crypto_secretbox_NONCEBYTES ); |
1409 | new_nonce ( session->call->nonce_local ); | 1620 | new_nonce ( session->calls[call_index]->nonce_local ); |
1410 | 1621 | ||
1411 | msi_msg_set_cryptokey ( _msg_starting, session->call->key_local, crypto_secretbox_KEYBYTES ); | 1622 | msi_msg_set_cryptokey ( _msg_starting, session->calls[call_index]->key_local, crypto_secretbox_KEYBYTES ); |
1412 | msi_msg_set_nonce ( _msg_starting, session->call->nonce_local, crypto_secretbox_NONCEBYTES ); | 1623 | msi_msg_set_nonce ( _msg_starting, session->calls[call_index]->nonce_local, crypto_secretbox_NONCEBYTES ); |
1413 | 1624 | ||
1414 | send_message ( session, _msg_starting, session->call->peers[session->call->peer_count - 1] ); | 1625 | send_message ( session, session->calls[call_index], _msg_starting, session->calls[call_index]->peers[session->calls[call_index]->peer_count - 1] ); |
1415 | free_message ( _msg_starting ); | 1626 | free_message ( _msg_starting ); |
1416 | 1627 | ||
1417 | session->call->state = call_active; | 1628 | session->calls[call_index]->state = call_active; |
1418 | 1629 | ||
1419 | return 0; | 1630 | return 0; |
1420 | } | 1631 | } |
@@ -1424,21 +1635,27 @@ int msi_answer ( MSISession *session, MSICallType call_type ) | |||
1424 | * @brief Cancel request. | 1635 | * @brief Cancel request. |
1425 | * | 1636 | * |
1426 | * @param session Control session. | 1637 | * @param session Control session. |
1638 | * @param call_id To which call is this action handled. | ||
1427 | * @param reason Set optional reason header. Pass NULL if none. | 1639 | * @param reason Set optional reason header. Pass NULL if none. |
1428 | * @return int | 1640 | * @return int |
1429 | */ | 1641 | */ |
1430 | int msi_cancel ( MSISession *session, uint32_t peer, const char *reason ) | 1642 | int msi_cancel ( MSISession *session, uint32_t call_index, uint32_t peer, const char *reason ) |
1431 | { | 1643 | { |
1432 | assert ( session ); | 1644 | LOGGER_DEBUG("Canceling call: %u; reason:", call_index, reason? reason : "Unknown"); |
1433 | 1645 | ||
1646 | if ( call_index >= session->max_calls || !session->calls[call_index] ){ | ||
1647 | LOGGER_ERROR("Invalid call index!"); | ||
1648 | return -1; | ||
1649 | } | ||
1650 | |||
1434 | MSIMessage *_msg_cancel = msi_new_message ( TYPE_REQUEST, stringify_request ( cancel ) ); | 1651 | MSIMessage *_msg_cancel = msi_new_message ( TYPE_REQUEST, stringify_request ( cancel ) ); |
1435 | 1652 | ||
1436 | if ( reason ) msi_msg_set_reason(_msg_cancel, (const uint8_t*)reason, strlen(reason)); | 1653 | if ( reason ) msi_msg_set_reason(_msg_cancel, (const uint8_t*)reason, strlen(reason)); |
1437 | 1654 | ||
1438 | send_message ( session, _msg_cancel, peer ); | 1655 | send_message ( session, session->calls[call_index], _msg_cancel, peer ); |
1439 | free_message ( _msg_cancel ); | 1656 | free_message ( _msg_cancel ); |
1440 | 1657 | ||
1441 | session->call->request_timer_id = event.timer_alloc ( handle_timeout, session, m_deftout ); | 1658 | session->calls[call_index]->request_timer_id = event.timer_alloc ( handle_timeout, session->calls[call_index], m_deftout ); |
1442 | 1659 | ||
1443 | return 0; | 1660 | return 0; |
1444 | } | 1661 | } |
@@ -1448,20 +1665,26 @@ int msi_cancel ( MSISession *session, uint32_t peer, const char *reason ) | |||
1448 | * @brief Reject request. | 1665 | * @brief Reject request. |
1449 | * | 1666 | * |
1450 | * @param session Control session. | 1667 | * @param session Control session. |
1668 | * @param call_id To which call is this action handled. | ||
1451 | * @return int | 1669 | * @return int |
1452 | */ | 1670 | */ |
1453 | int msi_reject ( MSISession *session, const uint8_t *reason ) | 1671 | int msi_reject ( MSISession *session, uint32_t call_index, const uint8_t *reason ) |
1454 | { | 1672 | { |
1455 | assert ( session ); | 1673 | LOGGER_DEBUG("Rejecting call: %u; reason:", call_index, reason? (char*)reason : "Unknown"); |
1456 | 1674 | ||
1675 | if ( call_index >= session->max_calls || !session->calls[call_index] ){ | ||
1676 | LOGGER_ERROR("Invalid call index!"); | ||
1677 | return -1; | ||
1678 | } | ||
1679 | |||
1457 | MSIMessage *_msg_reject = msi_new_message ( TYPE_REQUEST, stringify_request ( reject ) ); | 1680 | MSIMessage *_msg_reject = msi_new_message ( TYPE_REQUEST, stringify_request ( reject ) ); |
1458 | 1681 | ||
1459 | if ( reason ) msi_msg_set_reason(_msg_reject, reason, strlen((const char *)reason) + 1); | 1682 | if ( reason ) msi_msg_set_reason(_msg_reject, reason, strlen((const char *)reason) + 1); |
1460 | 1683 | ||
1461 | send_message ( session, _msg_reject, session->call->peers[session->call->peer_count - 1] ); | 1684 | send_message ( session, session->calls[call_index], _msg_reject, session->calls[call_index]->peers[session->calls[call_index]->peer_count - 1] ); |
1462 | free_message ( _msg_reject ); | 1685 | free_message ( _msg_reject ); |
1463 | 1686 | ||
1464 | session->call->request_timer_id = event.timer_alloc ( handle_timeout, session, m_deftout ); | 1687 | session->calls[call_index]->request_timer_id = event.timer_alloc ( handle_timeout, session->calls[call_index], m_deftout ); |
1465 | 1688 | ||
1466 | return 0; | 1689 | return 0; |
1467 | } | 1690 | } |
@@ -1471,18 +1694,19 @@ int msi_reject ( MSISession *session, const uint8_t *reason ) | |||
1471 | * @brief Terminate the current call. | 1694 | * @brief Terminate the current call. |
1472 | * | 1695 | * |
1473 | * @param session Control session. | 1696 | * @param session Control session. |
1697 | * @param call_id To which call is this action handled. | ||
1474 | * @return int | 1698 | * @return int |
1475 | */ | 1699 | */ |
1476 | int msi_stopcall ( MSISession *session ) | 1700 | int msi_stopcall ( MSISession *session, uint32_t call_index ) |
1477 | { | 1701 | { |
1478 | assert ( session ); | 1702 | LOGGER_DEBUG("Stopping call index: %u", call_index); |
1479 | 1703 | ||
1480 | if ( !session->call ) | 1704 | if ( call_index >= session->max_calls || !session->calls[call_index] ) |
1481 | return -1; | 1705 | return -1; |
1482 | 1706 | ||
1483 | /* just terminate it */ | 1707 | /* just terminate it */ |
1484 | 1708 | ||
1485 | terminate_call ( session ); | 1709 | terminate_call ( session, session->calls[call_index] ); |
1486 | 1710 | ||
1487 | return 0; | 1711 | return 0; |
1488 | } \ No newline at end of file | 1712 | } \ No newline at end of file |
diff --git a/toxav/msi.h b/toxav/msi.h index 37fc07a3..c74f9f11 100755 --- a/toxav/msi.h +++ b/toxav/msi.h | |||
@@ -33,7 +33,7 @@ | |||
33 | #define CALL_ID_LEN 12 | 33 | #define CALL_ID_LEN 12 |
34 | 34 | ||
35 | 35 | ||
36 | typedef void ( *MSICallback ) ( void *arg ); | 36 | typedef void ( *MSICallback ) ( uint32_t, void *arg ); |
37 | 37 | ||
38 | 38 | ||
39 | /** | 39 | /** |
@@ -62,32 +62,34 @@ typedef enum { | |||
62 | * @brief The call struct. | 62 | * @brief The call struct. |
63 | * | 63 | * |
64 | */ | 64 | */ |
65 | typedef struct _MSICall { /* Call info structure */ | 65 | typedef struct _MSICall { /* Call info structure */ |
66 | MSICallState state; | 66 | struct _MSISession* session; /* Session pointer */ |
67 | |||
68 | MSICallState state; | ||
67 | 69 | ||
68 | MSICallType type_local; /* Type of payload user is ending */ | 70 | MSICallType type_local; /* Type of payload user is ending */ |
69 | MSICallType *type_peer; /* Type of payload others are sending */ | 71 | MSICallType *type_peer; /* Type of payload others are sending */ |
70 | 72 | ||
71 | uint8_t id[CALL_ID_LEN]; /* Random value identifying the call */ | 73 | uint8_t id[CALL_ID_LEN]; /* Random value identifying the call */ |
72 | 74 | ||
73 | uint8_t *key_local; /* The key for encryption */ | 75 | uint8_t *key_local; /* The key for encryption */ |
74 | uint8_t *key_peer; /* The key for decryption */ | 76 | uint8_t *key_peer; /* The key for decryption */ |
75 | 77 | ||
76 | uint8_t *nonce_local; /* Local nonce */ | 78 | uint8_t *nonce_local; /* Local nonce */ |
77 | uint8_t *nonce_peer; /* Peer nonce */ | 79 | uint8_t *nonce_peer; /* Peer nonce */ |
78 | 80 | ||
79 | int ringing_tout_ms; /* Ringing timeout in ms */ | 81 | int ringing_tout_ms; /* Ringing timeout in ms */ |
80 | 82 | ||
81 | int request_timer_id; /* Timer id for outgoing request/action */ | 83 | int request_timer_id; /* Timer id for outgoing request/action */ |
82 | int ringing_timer_id; /* Timer id for ringing timeout */ | 84 | int ringing_timer_id; /* Timer id for ringing timeout */ |
83 | |||
84 | pthread_mutex_t mutex; /* It's to be assumed that call will have | ||
85 | * seperate thread so add mutex | ||
86 | */ | ||
87 | uint32_t *peers; | ||
88 | uint16_t peer_count; | ||
89 | 85 | ||
86 | pthread_mutex_t mutex; /* It's to be assumed that call will have | ||
87 | * seperate thread so add mutex | ||
88 | */ | ||
89 | uint32_t *peers; | ||
90 | uint16_t peer_count; | ||
90 | 91 | ||
92 | uint32_t call_idx; /* Index of this call in MSISession */ | ||
91 | } MSICall; | 93 | } MSICall; |
92 | 94 | ||
93 | 95 | ||
@@ -97,8 +99,9 @@ typedef struct _MSICall { /* Call info structure */ | |||
97 | */ | 99 | */ |
98 | typedef struct _MSISession { | 100 | typedef struct _MSISession { |
99 | 101 | ||
100 | /* Call handler */ | 102 | /* Call handlers */ |
101 | struct _MSICall *call; | 103 | struct _MSICall **calls; |
104 | uint32_t max_calls; | ||
102 | 105 | ||
103 | int last_error_id; /* Determine the last error */ | 106 | int last_error_id; /* Determine the last error */ |
104 | const uint8_t *last_error_str; | 107 | const uint8_t *last_error_str; |
@@ -151,10 +154,11 @@ void msi_register_callback(MSICallback callback, MSICallbackID id, void* userdat | |||
151 | * @brief Start the control session. | 154 | * @brief Start the control session. |
152 | * | 155 | * |
153 | * @param messenger Tox* object. | 156 | * @param messenger Tox* object. |
157 | * @param max_calls Amount of calls possible | ||
154 | * @return MSISession* The created session. | 158 | * @return MSISession* The created session. |
155 | * @retval NULL Error occured. | 159 | * @retval NULL Error occured. |
156 | */ | 160 | */ |
157 | MSISession *msi_init_session ( Messenger *messenger ); | 161 | MSISession *msi_init_session ( Messenger *messenger, uint32_t max_calls ); |
158 | 162 | ||
159 | 163 | ||
160 | /** | 164 | /** |
@@ -170,62 +174,68 @@ int msi_terminate_session ( MSISession *session ); | |||
170 | * @brief Send invite request to friend_id. | 174 | * @brief Send invite request to friend_id. |
171 | * | 175 | * |
172 | * @param session Control session. | 176 | * @param session Control session. |
177 | * @param call_index Set to new call index. | ||
173 | * @param call_type Type of the call. Audio or Video(both audio and video) | 178 | * @param call_type Type of the call. Audio or Video(both audio and video) |
174 | * @param rngsec Ringing timeout. | 179 | * @param rngsec Ringing timeout. |
175 | * @param friend_id The friend. | 180 | * @param friend_id The friend. |
176 | * @return int | 181 | * @return int |
177 | */ | 182 | */ |
178 | int msi_invite ( MSISession *session, MSICallType call_type, uint32_t rngsec, uint32_t friend_id ); | 183 | int msi_invite ( MSISession *session, uint32_t* call_index, MSICallType call_type, uint32_t rngsec, uint32_t friend_id ); |
179 | 184 | ||
180 | 185 | ||
181 | /** | 186 | /** |
182 | * @brief Hangup active call. | 187 | * @brief Hangup active call. |
183 | * | 188 | * |
184 | * @param session Control session. | 189 | * @param session Control session. |
190 | * @param call_index To which call is this action handled. | ||
185 | * @return int | 191 | * @return int |
186 | * @retval -1 Error occured. | 192 | * @retval -1 Error occured. |
187 | * @retval 0 Success. | 193 | * @retval 0 Success. |
188 | */ | 194 | */ |
189 | int msi_hangup ( MSISession *session ); | 195 | int msi_hangup ( MSISession *session, uint32_t call_index ); |
190 | 196 | ||
191 | 197 | ||
192 | /** | 198 | /** |
193 | * @brief Answer active call request. | 199 | * @brief Answer active call request. |
194 | * | 200 | * |
195 | * @param session Control session. | 201 | * @param session Control session. |
202 | * @param call_index To which call is this action handled. | ||
196 | * @param call_type Answer with Audio or Video(both). | 203 | * @param call_type Answer with Audio or Video(both). |
197 | * @return int | 204 | * @return int |
198 | */ | 205 | */ |
199 | int msi_answer ( MSISession *session, MSICallType call_type ); | 206 | int msi_answer ( MSISession *session, uint32_t call_index, MSICallType call_type ); |
200 | 207 | ||
201 | 208 | ||
202 | /** | 209 | /** |
203 | * @brief Cancel request. | 210 | * @brief Cancel request. |
204 | * | 211 | * |
205 | * @param session Control session. | 212 | * @param session Control session. |
213 | * @param call_index To which call is this action handled. | ||
206 | * @param peer To which peer. | 214 | * @param peer To which peer. |
207 | * @param reason Set optional reason header. Pass NULL if none. | 215 | * @param reason Set optional reason header. Pass NULL if none. |
208 | * @return int | 216 | * @return int |
209 | */ | 217 | */ |
210 | int msi_cancel ( MSISession* session, uint32_t peer, const char* reason ); | 218 | int msi_cancel ( MSISession* session, uint32_t call_index, uint32_t peer, const char* reason ); |
211 | 219 | ||
212 | 220 | ||
213 | /** | 221 | /** |
214 | * @brief Reject request. | 222 | * @brief Reject request. |
215 | * | 223 | * |
216 | * @param session Control session. | 224 | * @param session Control session. |
225 | * @param call_index To which call is this action handled. | ||
217 | * @param reason Set optional reason header. Pass NULL if none. | 226 | * @param reason Set optional reason header. Pass NULL if none. |
218 | * @return int | 227 | * @return int |
219 | */ | 228 | */ |
220 | int msi_reject ( MSISession *session, const uint8_t *reason ); | 229 | int msi_reject ( MSISession *session, uint32_t call_index, const uint8_t *reason ); |
221 | 230 | ||
222 | 231 | ||
223 | /** | 232 | /** |
224 | * @brief Terminate the current call. | 233 | * @brief Terminate the current call. |
225 | * | 234 | * |
226 | * @param session Control session. | 235 | * @param session Control session. |
236 | * @param call_index To which call is this action handled. | ||
227 | * @return int | 237 | * @return int |
228 | */ | 238 | */ |
229 | int msi_stopcall ( MSISession *session ); | 239 | int msi_stopcall ( MSISession *session, uint32_t call_index ); |
230 | 240 | ||
231 | #endif /* __TOXMSI */ | 241 | #endif /* __TOXMSI */ |
diff --git a/toxav/toxav.c b/toxav/toxav.c index 4cdc38ba..f1ff2312 100755 --- a/toxav/toxav.c +++ b/toxav/toxav.c | |||
@@ -29,6 +29,8 @@ | |||
29 | #include "media.h" | 29 | #include "media.h" |
30 | #include "msi.h" | 30 | #include "msi.h" |
31 | 31 | ||
32 | #include "../toxcore/logger.h" | ||
33 | |||
32 | #include <stdlib.h> | 34 | #include <stdlib.h> |
33 | #include <string.h> | 35 | #include <string.h> |
34 | #include <assert.h> | 36 | #include <assert.h> |
@@ -43,6 +45,9 @@ | |||
43 | 45 | ||
44 | static const uint8_t audio_index = 0, video_index = 1; | 46 | static const uint8_t audio_index = 0, video_index = 1; |
45 | 47 | ||
48 | typedef struct _CallRTPSessions { | ||
49 | RTPSession *crtps[2]; /* Audio is first and video is second */ | ||
50 | } CallRTPSessions; | ||
46 | 51 | ||
47 | typedef enum { | 52 | typedef enum { |
48 | ts_closing, | 53 | ts_closing, |
@@ -56,13 +61,27 @@ struct _ToxAv { | |||
56 | 61 | ||
57 | MSISession *msi_session; /** Main msi session */ | 62 | MSISession *msi_session; /** Main msi session */ |
58 | 63 | ||
59 | RTPSession *rtp_sessions[2]; /* Audio is first and video is second */ | 64 | CallRTPSessions* rtp_sessions; |
60 | 65 | ||
61 | struct jitter_buffer *j_buf; | 66 | struct jitter_buffer *j_buf; |
62 | CodecState *cs; | 67 | CodecState *cs; |
63 | 68 | ||
69 | uint32_t max_calls; | ||
70 | }; | ||
71 | |||
72 | const ToxAvCodecSettings av_DefaultSettings = { | ||
73 | 1000000, | ||
74 | 800, | ||
75 | 600, | ||
76 | |||
77 | 64000, | ||
78 | 20, | ||
79 | 48000, | ||
80 | 1, | ||
81 | 20 | ||
64 | }; | 82 | }; |
65 | 83 | ||
84 | |||
66 | /** | 85 | /** |
67 | * @brief Start new A/V session. There can only be one session at the time. If you register more | 86 | * @brief Start new A/V session. There can only be one session at the time. If you register more |
68 | * it will result in undefined behaviour. | 87 | * it will result in undefined behaviour. |
@@ -74,7 +93,7 @@ struct _ToxAv { | |||
74 | * @return ToxAv* | 93 | * @return ToxAv* |
75 | * @retval NULL On error. | 94 | * @retval NULL On error. |
76 | */ | 95 | */ |
77 | ToxAv *toxav_new( Tox* messenger, ToxAvCodecSettings* codec_settings) | 96 | ToxAv *toxav_new( Tox* messenger, ToxAvCodecSettings* codec_settings, uint32_t max_calls) |
78 | { | 97 | { |
79 | ToxAv *av = calloc ( sizeof(ToxAv), 1); | 98 | ToxAv *av = calloc ( sizeof(ToxAv), 1); |
80 | 99 | ||
@@ -83,12 +102,12 @@ ToxAv *toxav_new( Tox* messenger, ToxAvCodecSettings* codec_settings) | |||
83 | 102 | ||
84 | av->messenger = (Messenger *)messenger; | 103 | av->messenger = (Messenger *)messenger; |
85 | 104 | ||
86 | av->msi_session = msi_init_session(av->messenger); | 105 | av->msi_session = msi_init_session(av->messenger, max_calls); |
87 | av->msi_session->agent_handler = av; | 106 | av->msi_session->agent_handler = av; |
88 | 107 | ||
89 | av->rtp_sessions[0] = av->rtp_sessions [1] = NULL; | 108 | av->rtp_sessions = calloc(sizeof(RTPSession), max_calls); |
90 | 109 | av->max_calls = max_calls; | |
91 | /* NOTE: This should be user defined or? */ | 110 | |
92 | av->j_buf = create_queue(codec_settings->jbuf_capacity); | 111 | av->j_buf = create_queue(codec_settings->jbuf_capacity); |
93 | 112 | ||
94 | av->cs = codec_init_session(codec_settings->audio_bitrate, | 113 | av->cs = codec_init_session(codec_settings->audio_bitrate, |
@@ -98,7 +117,7 @@ ToxAv *toxav_new( Tox* messenger, ToxAvCodecSettings* codec_settings) | |||
98 | codec_settings->video_width, | 117 | codec_settings->video_width, |
99 | codec_settings->video_height, | 118 | codec_settings->video_height, |
100 | codec_settings->video_bitrate); | 119 | codec_settings->video_bitrate); |
101 | 120 | ||
102 | return av; | 121 | return av; |
103 | } | 122 | } |
104 | 123 | ||
@@ -111,14 +130,19 @@ ToxAv *toxav_new( Tox* messenger, ToxAvCodecSettings* codec_settings) | |||
111 | void toxav_kill ( ToxAv *av ) | 130 | void toxav_kill ( ToxAv *av ) |
112 | { | 131 | { |
113 | msi_terminate_session(av->msi_session); | 132 | msi_terminate_session(av->msi_session); |
114 | 133 | ||
115 | if ( av->rtp_sessions[audio_index] ) { | 134 | int i = 0; |
116 | rtp_terminate_session(av->rtp_sessions[audio_index], av->msi_session->messenger_handle); | 135 | for (; i < av->max_calls; i ++) { |
117 | } | 136 | if ( av->rtp_sessions[i].crtps[audio_index] ) { |
118 | 137 | rtp_terminate_session(av->rtp_sessions[i].crtps[audio_index], av->msi_session->messenger_handle); | |
119 | if ( av->rtp_sessions[video_index] ) { | 138 | } |
120 | rtp_terminate_session(av->rtp_sessions[video_index], av->msi_session->messenger_handle); | 139 | |
140 | if ( av->rtp_sessions[i].crtps[video_index] ) { | ||
141 | rtp_terminate_session(av->rtp_sessions[i].crtps[video_index], av->msi_session->messenger_handle); | ||
142 | } | ||
121 | } | 143 | } |
144 | |||
145 | free(av->rtp_sessions); | ||
122 | 146 | ||
123 | codec_terminate_session(av->cs); | 147 | codec_terminate_session(av->cs); |
124 | 148 | ||
@@ -148,13 +172,9 @@ void toxav_register_callstate_callback ( ToxAVCallback callback, ToxAvCallbackID | |||
148 | * @retval 0 Success. | 172 | * @retval 0 Success. |
149 | * @retval ToxAvError On error. | 173 | * @retval ToxAvError On error. |
150 | */ | 174 | */ |
151 | int toxav_call (ToxAv *av, int user, ToxAvCallType call_type, int ringing_seconds ) | 175 | int toxav_call (ToxAv* av, uint32_t* call_index, int user, ToxAvCallType call_type, int ringing_seconds ) |
152 | { | 176 | { |
153 | if ( av->msi_session->call ) { | 177 | return msi_invite(av->msi_session, call_index, call_type, ringing_seconds * 1000, user); |
154 | return ErrorAlreadyInCall; | ||
155 | } | ||
156 | |||
157 | return msi_invite(av->msi_session, call_type, ringing_seconds * 1000, user); | ||
158 | } | 178 | } |
159 | 179 | ||
160 | /** | 180 | /** |
@@ -165,17 +185,17 @@ int toxav_call (ToxAv *av, int user, ToxAvCallType call_type, int ringing_second | |||
165 | * @retval 0 Success. | 185 | * @retval 0 Success. |
166 | * @retval ToxAvError On error. | 186 | * @retval ToxAvError On error. |
167 | */ | 187 | */ |
168 | int toxav_hangup ( ToxAv *av ) | 188 | int toxav_hangup ( ToxAv* av, uint32_t call_index ) |
169 | { | 189 | { |
170 | if ( !av->msi_session->call ) { | 190 | if ( !av->msi_session->calls[call_index] ) { |
171 | return ErrorNoCall; | 191 | return ErrorNoCall; |
172 | } | 192 | } |
173 | 193 | ||
174 | if ( av->msi_session->call->state != call_active ) { | 194 | if ( av->msi_session->calls[call_index]->state != call_active ) { |
175 | return ErrorInvalidState; | 195 | return ErrorInvalidState; |
176 | } | 196 | } |
177 | 197 | ||
178 | return msi_hangup(av->msi_session); | 198 | return msi_hangup(av->msi_session, call_index); |
179 | } | 199 | } |
180 | 200 | ||
181 | /** | 201 | /** |
@@ -187,17 +207,17 @@ int toxav_hangup ( ToxAv *av ) | |||
187 | * @retval 0 Success. | 207 | * @retval 0 Success. |
188 | * @retval ToxAvError On error. | 208 | * @retval ToxAvError On error. |
189 | */ | 209 | */ |
190 | int toxav_answer ( ToxAv *av, ToxAvCallType call_type ) | 210 | int toxav_answer ( ToxAv* av, uint32_t call_index, ToxAvCallType call_type ) |
191 | { | 211 | { |
192 | if ( !av->msi_session->call ) { | 212 | if ( !av->msi_session->calls[call_index] ) { |
193 | return ErrorNoCall; | 213 | return ErrorNoCall; |
194 | } | 214 | } |
195 | 215 | ||
196 | if ( av->msi_session->call->state != call_starting ) { | 216 | if ( av->msi_session->calls[call_index]->state != call_starting ) { |
197 | return ErrorInvalidState; | 217 | return ErrorInvalidState; |
198 | } | 218 | } |
199 | 219 | ||
200 | return msi_answer(av->msi_session, call_type); | 220 | return msi_answer(av->msi_session, call_index, call_type); |
201 | } | 221 | } |
202 | 222 | ||
203 | /** | 223 | /** |
@@ -209,17 +229,17 @@ int toxav_answer ( ToxAv *av, ToxAvCallType call_type ) | |||
209 | * @retval 0 Success. | 229 | * @retval 0 Success. |
210 | * @retval ToxAvError On error. | 230 | * @retval ToxAvError On error. |
211 | */ | 231 | */ |
212 | int toxav_reject ( ToxAv *av, const char *reason ) | 232 | int toxav_reject ( ToxAv* av, uint32_t call_index, const char* reason ) |
213 | { | 233 | { |
214 | if ( !av->msi_session->call ) { | 234 | if ( !av->msi_session->calls[call_index] ) { |
215 | return ErrorNoCall; | 235 | return ErrorNoCall; |
216 | } | 236 | } |
217 | 237 | ||
218 | if ( av->msi_session->call->state != call_starting ) { | 238 | if ( av->msi_session->calls[call_index]->state != call_starting ) { |
219 | return ErrorInvalidState; | 239 | return ErrorInvalidState; |
220 | } | 240 | } |
221 | 241 | ||
222 | return msi_reject(av->msi_session, (const uint8_t *) reason); | 242 | return msi_reject(av->msi_session, call_index, (const uint8_t *) reason); |
223 | } | 243 | } |
224 | 244 | ||
225 | /** | 245 | /** |
@@ -232,13 +252,13 @@ int toxav_reject ( ToxAv *av, const char *reason ) | |||
232 | * @retval 0 Success. | 252 | * @retval 0 Success. |
233 | * @retval ToxAvError On error. | 253 | * @retval ToxAvError On error. |
234 | */ | 254 | */ |
235 | int toxav_cancel ( ToxAv *av, int peer_id, const char *reason ) | 255 | int toxav_cancel ( ToxAv* av, uint32_t call_index, int peer_id, const char* reason ) |
236 | { | 256 | { |
237 | if ( !av->msi_session->call ) { | 257 | if ( !av->msi_session->calls[call_index] ) { |
238 | return ErrorNoCall; | 258 | return ErrorNoCall; |
239 | } | 259 | } |
240 | 260 | ||
241 | return msi_cancel(av->msi_session, peer_id, reason); | 261 | return msi_cancel(av->msi_session, call_index, peer_id, reason); |
242 | } | 262 | } |
243 | 263 | ||
244 | /** | 264 | /** |
@@ -249,13 +269,13 @@ int toxav_cancel ( ToxAv *av, int peer_id, const char *reason ) | |||
249 | * @retval 0 Success. | 269 | * @retval 0 Success. |
250 | * @retval ToxAvError On error. | 270 | * @retval ToxAvError On error. |
251 | */ | 271 | */ |
252 | int toxav_stop_call ( ToxAv *av ) | 272 | int toxav_stop_call ( ToxAv* av, uint32_t call_index ) |
253 | { | 273 | { |
254 | if ( !av->msi_session->call ) { | 274 | if ( !av->msi_session->calls[call_index] ) { |
255 | return ErrorNoCall; | 275 | return ErrorNoCall; |
256 | } | 276 | } |
257 | 277 | ||
258 | return msi_stopcall(av->msi_session); | 278 | return msi_stopcall(av->msi_session, call_index); |
259 | } | 279 | } |
260 | 280 | ||
261 | /** | 281 | /** |
@@ -266,43 +286,43 @@ int toxav_stop_call ( ToxAv *av ) | |||
266 | * @retval 0 Success. | 286 | * @retval 0 Success. |
267 | * @retval ToxAvError On error. | 287 | * @retval ToxAvError On error. |
268 | */ | 288 | */ |
269 | int toxav_prepare_transmission ( ToxAv* av, int support_video ) | 289 | int toxav_prepare_transmission ( ToxAv* av, uint32_t call_index, int support_video ) |
270 | { | 290 | { |
271 | assert(av->msi_session); | 291 | if ( !av->msi_session || !av->msi_session->calls[call_index] ) { |
272 | |||
273 | if ( !av->msi_session || !av->msi_session->call ) { | ||
274 | return ErrorNoCall; | 292 | return ErrorNoCall; |
275 | } | 293 | } |
276 | 294 | ||
277 | av->rtp_sessions[audio_index] = rtp_init_session( | 295 | av->rtp_sessions[call_index].crtps[audio_index] = |
278 | type_audio, | 296 | rtp_init_session( |
279 | av->messenger, | 297 | type_audio, |
280 | av->msi_session->call->peers[0], | 298 | av->messenger, |
281 | av->msi_session->call->key_peer, | 299 | av->msi_session->calls[call_index]->peers[0], |
282 | av->msi_session->call->key_local, | 300 | av->msi_session->calls[call_index]->key_peer, |
283 | av->msi_session->call->nonce_peer, | 301 | av->msi_session->calls[call_index]->key_local, |
284 | av->msi_session->call->nonce_local | 302 | av->msi_session->calls[call_index]->nonce_peer, |
285 | ); | 303 | av->msi_session->calls[call_index]->nonce_local |
304 | ); | ||
286 | 305 | ||
287 | 306 | ||
288 | if ( !av->rtp_sessions[audio_index] ) { | 307 | if ( !av->rtp_sessions[call_index].crtps[audio_index] ) { |
289 | fprintf(stderr, "Error while starting audio RTP session!\n"); | 308 | fprintf(stderr, "Error while starting audio RTP session!\n"); |
290 | return ErrorStartingAudioRtp; | 309 | return ErrorStartingAudioRtp; |
291 | } | 310 | } |
292 | 311 | ||
293 | if ( support_video ) { | 312 | if ( support_video ) { |
294 | av->rtp_sessions[video_index] = rtp_init_session ( | 313 | av->rtp_sessions[call_index].crtps[video_index] = |
295 | type_video, | 314 | rtp_init_session ( |
296 | av->messenger, | 315 | type_video, |
297 | av->msi_session->call->peers[0], | 316 | av->messenger, |
298 | av->msi_session->call->key_peer, | 317 | av->msi_session->calls[call_index]->peers[0], |
299 | av->msi_session->call->key_local, | 318 | av->msi_session->calls[call_index]->key_peer, |
300 | av->msi_session->call->nonce_peer, | 319 | av->msi_session->calls[call_index]->key_local, |
301 | av->msi_session->call->nonce_local | 320 | av->msi_session->calls[call_index]->nonce_peer, |
302 | ); | 321 | av->msi_session->calls[call_index]->nonce_local |
303 | 322 | ); | |
304 | 323 | ||
305 | if ( !av->rtp_sessions[video_index] ) { | 324 | |
325 | if ( !av->rtp_sessions[call_index].crtps[video_index] ) { | ||
306 | fprintf(stderr, "Error while starting video RTP session!\n"); | 326 | fprintf(stderr, "Error while starting video RTP session!\n"); |
307 | return ErrorStartingVideoRtp; | 327 | return ErrorStartingVideoRtp; |
308 | } | 328 | } |
@@ -318,20 +338,20 @@ int toxav_prepare_transmission ( ToxAv* av, int support_video ) | |||
318 | * @retval 0 Success. | 338 | * @retval 0 Success. |
319 | * @retval ToxAvError On error. | 339 | * @retval ToxAvError On error. |
320 | */ | 340 | */ |
321 | int toxav_kill_transmission ( ToxAv *av ) | 341 | int toxav_kill_transmission ( ToxAv *av, uint32_t call_index ) |
322 | { | 342 | { |
323 | if ( av->rtp_sessions[audio_index] && -1 == rtp_terminate_session(av->rtp_sessions[audio_index], av->messenger) ) { | 343 | if ( av->rtp_sessions[call_index].crtps[audio_index] && -1 == rtp_terminate_session(av->rtp_sessions[call_index].crtps[audio_index], av->messenger) ) { |
324 | fprintf(stderr, "Error while terminating audio RTP session!\n"); | 344 | fprintf(stderr, "Error while terminating audio RTP session!\n"); |
325 | return ErrorTerminatingAudioRtp; | 345 | return ErrorTerminatingAudioRtp; |
326 | } | 346 | } |
327 | 347 | ||
328 | if ( av->rtp_sessions[video_index] && -1 == rtp_terminate_session(av->rtp_sessions[video_index], av->messenger) ) { | 348 | if ( av->rtp_sessions[call_index].crtps[video_index] && -1 == rtp_terminate_session(av->rtp_sessions[call_index].crtps[video_index], av->messenger) ) { |
329 | fprintf(stderr, "Error while terminating video RTP session!\n"); | 349 | fprintf(stderr, "Error while terminating video RTP session!\n"); |
330 | return ErrorTerminatingVideoRtp; | 350 | return ErrorTerminatingVideoRtp; |
331 | } | 351 | } |
332 | 352 | ||
333 | av->rtp_sessions[audio_index] = NULL; | 353 | av->rtp_sessions[call_index].crtps[audio_index] = NULL; |
334 | av->rtp_sessions[video_index] = NULL; | 354 | av->rtp_sessions[call_index].crtps[video_index] = NULL; |
335 | 355 | ||
336 | 356 | ||
337 | return ErrorNone; | 357 | return ErrorNone; |
@@ -349,10 +369,10 @@ int toxav_kill_transmission ( ToxAv *av ) | |||
349 | * @retval 0 Success. | 369 | * @retval 0 Success. |
350 | * @retval -1 Failure. | 370 | * @retval -1 Failure. |
351 | */ | 371 | */ |
352 | inline__ int toxav_send_rtp_payload ( ToxAv *av, ToxAvCallType type, const uint8_t *payload, uint16_t length ) | 372 | inline__ int toxav_send_rtp_payload ( ToxAv *av, uint32_t call_index, ToxAvCallType type, const uint8_t *payload, uint16_t length ) |
353 | { | 373 | { |
354 | if ( av->rtp_sessions[type - TypeAudio] ) | 374 | if ( av->rtp_sessions[call_index].crtps[type - TypeAudio] ) |
355 | return rtp_send_msg ( av->rtp_sessions[type - TypeAudio], av->msi_session->messenger_handle, payload, length ); | 375 | return rtp_send_msg ( av->rtp_sessions[call_index].crtps[type - TypeAudio], av->msi_session->messenger_handle, payload, length ); |
356 | else return -1; | 376 | else return -1; |
357 | } | 377 | } |
358 | 378 | ||
@@ -366,18 +386,18 @@ inline__ int toxav_send_rtp_payload ( ToxAv *av, ToxAvCallType type, const uint8 | |||
366 | * @retval ToxAvError On Error. | 386 | * @retval ToxAvError On Error. |
367 | * @retval >=0 Size of received payload. | 387 | * @retval >=0 Size of received payload. |
368 | */ | 388 | */ |
369 | inline__ int toxav_recv_rtp_payload ( ToxAv *av, ToxAvCallType type, uint8_t *dest ) | 389 | inline__ int toxav_recv_rtp_payload ( ToxAv *av, uint32_t call_index, ToxAvCallType type, uint8_t *dest ) |
370 | { | 390 | { |
371 | if ( !dest ) return ErrorInternal; | 391 | if ( !dest ) return ErrorInternal; |
372 | 392 | ||
373 | if ( !av->rtp_sessions[type - TypeAudio] ) return ErrorNoRtpSession; | 393 | if ( !av->rtp_sessions[call_index].crtps[type - TypeAudio] ) return ErrorNoRtpSession; |
374 | 394 | ||
375 | RTPMessage *message; | 395 | RTPMessage *message; |
376 | 396 | ||
377 | if ( type == TypeAudio ) { | 397 | if ( type == TypeAudio ) { |
378 | 398 | ||
379 | do { | 399 | do { |
380 | message = rtp_recv_msg(av->rtp_sessions[audio_index]); | 400 | message = rtp_recv_msg(av->rtp_sessions[call_index].crtps[audio_index]); |
381 | 401 | ||
382 | if (message) { | 402 | if (message) { |
383 | /* push the packet into the queue */ | 403 | /* push the packet into the queue */ |
@@ -390,7 +410,7 @@ inline__ int toxav_recv_rtp_payload ( ToxAv *av, ToxAvCallType type, uint8_t *de | |||
390 | 410 | ||
391 | if ( success == 2) return ErrorAudioPacketLost; | 411 | if ( success == 2) return ErrorAudioPacketLost; |
392 | } else { | 412 | } else { |
393 | message = rtp_recv_msg(av->rtp_sessions[video_index]); | 413 | message = rtp_recv_msg(av->rtp_sessions[call_index].crtps[video_index]); |
394 | } | 414 | } |
395 | 415 | ||
396 | if ( message ) { | 416 | if ( message ) { |
@@ -415,7 +435,7 @@ inline__ int toxav_recv_rtp_payload ( ToxAv *av, ToxAvCallType type, uint8_t *de | |||
415 | * @retval 0 Success. | 435 | * @retval 0 Success. |
416 | * @retval ToxAvError On Error. | 436 | * @retval ToxAvError On Error. |
417 | */ | 437 | */ |
418 | inline__ int toxav_recv_video ( ToxAv *av, vpx_image_t **output) | 438 | inline__ int toxav_recv_video ( ToxAv *av, uint32_t call_index, vpx_image_t **output) |
419 | { | 439 | { |
420 | if ( !output ) return ErrorInternal; | 440 | if ( !output ) return ErrorInternal; |
421 | 441 | ||
@@ -424,7 +444,7 @@ inline__ int toxav_recv_video ( ToxAv *av, vpx_image_t **output) | |||
424 | int error; | 444 | int error; |
425 | 445 | ||
426 | do { | 446 | do { |
427 | recved_size = toxav_recv_rtp_payload(av, TypeVideo, packet); | 447 | recved_size = toxav_recv_rtp_payload(av, call_index, TypeVideo, packet); |
428 | 448 | ||
429 | if (recved_size > 0 && ( error = vpx_codec_decode(&av->cs->v_decoder, packet, recved_size, NULL, 0) ) != VPX_CODEC_OK) | 449 | if (recved_size > 0 && ( error = vpx_codec_decode(&av->cs->v_decoder, packet, recved_size, NULL, 0) ) != VPX_CODEC_OK) |
430 | fprintf(stderr, "Error decoding: %s\n", vpx_codec_err_to_string(error)); | 450 | fprintf(stderr, "Error decoding: %s\n", vpx_codec_err_to_string(error)); |
@@ -450,7 +470,7 @@ inline__ int toxav_recv_video ( ToxAv *av, vpx_image_t **output) | |||
450 | * @retval 0 Success. | 470 | * @retval 0 Success. |
451 | * @retval ToxAvError On error. | 471 | * @retval ToxAvError On error. |
452 | */ | 472 | */ |
453 | inline__ int toxav_send_video ( ToxAv *av, vpx_image_t *input) | 473 | inline__ int toxav_send_video ( ToxAv *av, uint32_t call_index, vpx_image_t *input) |
454 | { | 474 | { |
455 | if (vpx_codec_encode(&av->cs->v_encoder, input, av->cs->frame_counter, 1, 0, MAX_ENCODE_TIME_US) != VPX_CODEC_OK) { | 475 | if (vpx_codec_encode(&av->cs->v_encoder, input, av->cs->frame_counter, 1, 0, MAX_ENCODE_TIME_US) != VPX_CODEC_OK) { |
456 | fprintf(stderr, "Could not encode video frame\n"); | 476 | fprintf(stderr, "Could not encode video frame\n"); |
@@ -465,7 +485,7 @@ inline__ int toxav_send_video ( ToxAv *av, vpx_image_t *input) | |||
465 | 485 | ||
466 | while ( (pkt = vpx_codec_get_cx_data(&av->cs->v_encoder, &iter)) ) { | 486 | while ( (pkt = vpx_codec_get_cx_data(&av->cs->v_encoder, &iter)) ) { |
467 | if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) { | 487 | if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) { |
468 | if (toxav_send_rtp_payload(av, TypeVideo, pkt->data.frame.buf, pkt->data.frame.sz) != -1) | 488 | if (toxav_send_rtp_payload(av, call_index, TypeVideo, pkt->data.frame.buf, pkt->data.frame.sz) != -1) |
469 | ++sent; | 489 | ++sent; |
470 | } | 490 | } |
471 | } | 491 | } |
@@ -488,13 +508,13 @@ inline__ int toxav_send_video ( ToxAv *av, vpx_image_t *input) | |||
488 | * @retval >=0 Size of received data in frames/samples. | 508 | * @retval >=0 Size of received data in frames/samples. |
489 | * @retval ToxAvError On error. | 509 | * @retval ToxAvError On error. |
490 | */ | 510 | */ |
491 | inline__ int toxav_recv_audio ( ToxAv *av, int frame_size, int16_t *dest ) | 511 | inline__ int toxav_recv_audio ( ToxAv *av, uint32_t call_index, int frame_size, int16_t *dest ) |
492 | { | 512 | { |
493 | if ( !dest ) return ErrorInternal; | 513 | if ( !dest ) return ErrorInternal; |
494 | 514 | ||
495 | uint8_t packet [RTP_PAYLOAD_SIZE]; | 515 | uint8_t packet [RTP_PAYLOAD_SIZE]; |
496 | 516 | ||
497 | int recved_size = toxav_recv_rtp_payload(av, TypeAudio, packet); | 517 | int recved_size = toxav_recv_rtp_payload(av, call_index, TypeAudio, packet); |
498 | 518 | ||
499 | if ( recved_size == ErrorAudioPacketLost ) { | 519 | if ( recved_size == ErrorAudioPacketLost ) { |
500 | return opus_decode(av->cs->audio_decoder, NULL, 0, dest, frame_size, 1); | 520 | return opus_decode(av->cs->audio_decoder, NULL, 0, dest, frame_size, 1); |
@@ -516,7 +536,7 @@ inline__ int toxav_recv_audio ( ToxAv *av, int frame_size, int16_t *dest ) | |||
516 | * @retval 0 Success. | 536 | * @retval 0 Success. |
517 | * @retval ToxAvError On error. | 537 | * @retval ToxAvError On error. |
518 | */ | 538 | */ |
519 | inline__ int toxav_send_audio ( ToxAv *av, const int16_t *frame, int frame_size) | 539 | inline__ int toxav_send_audio ( ToxAv *av, uint32_t call_index, const int16_t *frame, int frame_size) |
520 | { | 540 | { |
521 | uint8_t temp_data[RTP_PAYLOAD_SIZE]; | 541 | uint8_t temp_data[RTP_PAYLOAD_SIZE]; |
522 | int32_t ret = opus_encode(av->cs->audio_encoder, frame, frame_size, temp_data, sizeof(temp_data)); | 542 | int32_t ret = opus_encode(av->cs->audio_encoder, frame, frame_size, temp_data, sizeof(temp_data)); |
@@ -524,7 +544,7 @@ inline__ int toxav_send_audio ( ToxAv *av, const int16_t *frame, int frame_size) | |||
524 | if (ret <= 0) | 544 | if (ret <= 0) |
525 | return ErrorInternal; | 545 | return ErrorInternal; |
526 | 546 | ||
527 | return toxav_send_rtp_payload(av, TypeAudio, temp_data, ret); | 547 | return toxav_send_rtp_payload(av, call_index, TypeAudio, temp_data, ret); |
528 | } | 548 | } |
529 | 549 | ||
530 | /** | 550 | /** |
@@ -536,14 +556,14 @@ inline__ int toxav_send_audio ( ToxAv *av, const int16_t *frame, int frame_size) | |||
536 | * @retval ToxAvCallType On success. | 556 | * @retval ToxAvCallType On success. |
537 | * @retval ToxAvError On error. | 557 | * @retval ToxAvError On error. |
538 | */ | 558 | */ |
539 | int toxav_get_peer_transmission_type ( ToxAv *av, int peer ) | 559 | int toxav_get_peer_transmission_type ( ToxAv *av, uint32_t call_index, int peer ) |
540 | { | 560 | { |
541 | assert(av->msi_session); | 561 | assert(av->msi_session); |
542 | 562 | ||
543 | if ( peer < 0 || !av->msi_session->call || av->msi_session->call->peer_count <= peer ) | 563 | if ( peer < 0 || !av->msi_session->calls[call_index] || av->msi_session->calls[call_index]->peer_count <= peer ) |
544 | return ErrorInternal; | 564 | return ErrorInternal; |
545 | 565 | ||
546 | return av->msi_session->call->type_peer[peer]; | 566 | return av->msi_session->calls[call_index]->type_peer[peer]; |
547 | } | 567 | } |
548 | 568 | ||
549 | /** | 569 | /** |
@@ -554,14 +574,14 @@ int toxav_get_peer_transmission_type ( ToxAv *av, int peer ) | |||
554 | * @return int | 574 | * @return int |
555 | * @retval ToxAvError No peer id | 575 | * @retval ToxAvError No peer id |
556 | */ | 576 | */ |
557 | int toxav_get_peer_id ( ToxAv* av, int peer ) | 577 | int toxav_get_peer_id ( ToxAv* av, uint32_t call_index, int peer ) |
558 | { | 578 | { |
559 | assert(av->msi_session); | 579 | assert(av->msi_session); |
560 | 580 | ||
561 | if ( peer < 0 || !av->msi_session->call || av->msi_session->call->peer_count <= peer ) | 581 | if ( peer < 0 || !av->msi_session->calls[call_index] || av->msi_session->calls[call_index]->peer_count <= peer ) |
562 | return ErrorInternal; | 582 | return ErrorInternal; |
563 | 583 | ||
564 | return av->msi_session->call->peers[peer]; | 584 | return av->msi_session->calls[call_index]->peers[peer]; |
565 | } | 585 | } |
566 | 586 | ||
567 | /** | 587 | /** |
diff --git a/toxav/toxav.h b/toxav/toxav.h index 349e9498..89addb2b 100755 --- a/toxav/toxav.h +++ b/toxav/toxav.h | |||
@@ -29,7 +29,7 @@ | |||
29 | /* vpx_image_t */ | 29 | /* vpx_image_t */ |
30 | #include <vpx/vpx_image.h> | 30 | #include <vpx/vpx_image.h> |
31 | 31 | ||
32 | typedef void ( *ToxAVCallback ) ( void *arg ); | 32 | typedef void ( *ToxAVCallback ) ( uint32_t, void *arg ); |
33 | typedef struct _ToxAv ToxAv; | 33 | typedef struct _ToxAv ToxAv; |
34 | 34 | ||
35 | #ifndef __TOX_DEFINED__ | 35 | #ifndef __TOX_DEFINED__ |
@@ -119,17 +119,7 @@ typedef struct _ToxAvCodecSettings { | |||
119 | uint32_t jbuf_capacity; /* Size of jitter buffer */ | 119 | uint32_t jbuf_capacity; /* Size of jitter buffer */ |
120 | } ToxAvCodecSettings; | 120 | } ToxAvCodecSettings; |
121 | 121 | ||
122 | static const ToxAvCodecSettings av_DefaultSettings = { | 122 | extern const ToxAvCodecSettings av_DefaultSettings; |
123 | 1000000, | ||
124 | 800, | ||
125 | 600, | ||
126 | |||
127 | 64000, | ||
128 | 20, | ||
129 | 48000, | ||
130 | 1, | ||
131 | 20 | ||
132 | }; | ||
133 | 123 | ||
134 | /** | 124 | /** |
135 | * @brief Start new A/V session. There can only be one session at the time. If you register more | 125 | * @brief Start new A/V session. There can only be one session at the time. If you register more |
@@ -142,7 +132,7 @@ static const ToxAvCodecSettings av_DefaultSettings = { | |||
142 | * @return ToxAv* | 132 | * @return ToxAv* |
143 | * @retval NULL On error. | 133 | * @retval NULL On error. |
144 | */ | 134 | */ |
145 | ToxAv *toxav_new(Tox *messenger, ToxAvCodecSettings* codec_settings); | 135 | ToxAv *toxav_new(Tox *messenger, ToxAvCodecSettings* codec_settings, uint32_t max_calls); |
146 | 136 | ||
147 | /** | 137 | /** |
148 | * @brief Remove A/V session. | 138 | * @brief Remove A/V session. |
@@ -172,7 +162,7 @@ void toxav_register_callstate_callback (ToxAVCallback callback, ToxAvCallbackID | |||
172 | * @retval 0 Success. | 162 | * @retval 0 Success. |
173 | * @retval ToxAvError On error. | 163 | * @retval ToxAvError On error. |
174 | */ | 164 | */ |
175 | int toxav_call(ToxAv *av, int user, ToxAvCallType call_type, int ringing_seconds); | 165 | int toxav_call(ToxAv *av, uint32_t* call_index, int user, ToxAvCallType call_type, int ringing_seconds); |
176 | 166 | ||
177 | /** | 167 | /** |
178 | * @brief Hangup active call. | 168 | * @brief Hangup active call. |
@@ -182,7 +172,7 @@ int toxav_call(ToxAv *av, int user, ToxAvCallType call_type, int ringing_seconds | |||
182 | * @retval 0 Success. | 172 | * @retval 0 Success. |
183 | * @retval ToxAvError On error. | 173 | * @retval ToxAvError On error. |
184 | */ | 174 | */ |
185 | int toxav_hangup(ToxAv *av); | 175 | int toxav_hangup(ToxAv *av, uint32_t call_index); |
186 | 176 | ||
187 | /** | 177 | /** |
188 | * @brief Answer incomming call. | 178 | * @brief Answer incomming call. |
@@ -193,7 +183,7 @@ int toxav_hangup(ToxAv *av); | |||
193 | * @retval 0 Success. | 183 | * @retval 0 Success. |
194 | * @retval ToxAvError On error. | 184 | * @retval ToxAvError On error. |
195 | */ | 185 | */ |
196 | int toxav_answer(ToxAv *av, ToxAvCallType call_type ); | 186 | int toxav_answer(ToxAv *av, uint32_t call_index, ToxAvCallType call_type ); |
197 | 187 | ||
198 | /** | 188 | /** |
199 | * @brief Reject incomming call. | 189 | * @brief Reject incomming call. |
@@ -204,7 +194,7 @@ int toxav_answer(ToxAv *av, ToxAvCallType call_type ); | |||
204 | * @retval 0 Success. | 194 | * @retval 0 Success. |
205 | * @retval ToxAvError On error. | 195 | * @retval ToxAvError On error. |
206 | */ | 196 | */ |
207 | int toxav_reject(ToxAv *av, const char *reason); | 197 | int toxav_reject(ToxAv *av, uint32_t call_index, const char *reason); |
208 | 198 | ||
209 | /** | 199 | /** |
210 | * @brief Cancel outgoing request. | 200 | * @brief Cancel outgoing request. |
@@ -216,7 +206,7 @@ int toxav_reject(ToxAv *av, const char *reason); | |||
216 | * @retval 0 Success. | 206 | * @retval 0 Success. |
217 | * @retval ToxAvError On error. | 207 | * @retval ToxAvError On error. |
218 | */ | 208 | */ |
219 | int toxav_cancel(ToxAv* av, int peer_id, const char* reason); | 209 | int toxav_cancel(ToxAv* av, uint32_t call_index, int peer_id, const char* reason); |
220 | 210 | ||
221 | /** | 211 | /** |
222 | * @brief Terminate transmission. Note that transmission will be terminated without informing remote peer. | 212 | * @brief Terminate transmission. Note that transmission will be terminated without informing remote peer. |
@@ -226,7 +216,7 @@ int toxav_cancel(ToxAv* av, int peer_id, const char* reason); | |||
226 | * @retval 0 Success. | 216 | * @retval 0 Success. |
227 | * @retval ToxAvError On error. | 217 | * @retval ToxAvError On error. |
228 | */ | 218 | */ |
229 | int toxav_stop_call(ToxAv *av); | 219 | int toxav_stop_call(ToxAv *av, uint32_t call_index); |
230 | 220 | ||
231 | /** | 221 | /** |
232 | * @brief Must be call before any RTP transmission occurs. | 222 | * @brief Must be call before any RTP transmission occurs. |
@@ -237,7 +227,7 @@ int toxav_stop_call(ToxAv *av); | |||
237 | * @retval 0 Success. | 227 | * @retval 0 Success. |
238 | * @retval ToxAvError On error. | 228 | * @retval ToxAvError On error. |
239 | */ | 229 | */ |
240 | int toxav_prepare_transmission(ToxAv *av, int support_video); | 230 | int toxav_prepare_transmission(ToxAv* av, uint32_t call_index, int support_video); |
241 | 231 | ||
242 | /** | 232 | /** |
243 | * @brief Call this at the end of the transmission. | 233 | * @brief Call this at the end of the transmission. |
@@ -247,7 +237,7 @@ int toxav_prepare_transmission(ToxAv *av, int support_video); | |||
247 | * @retval 0 Success. | 237 | * @retval 0 Success. |
248 | * @retval ToxAvError On error. | 238 | * @retval ToxAvError On error. |
249 | */ | 239 | */ |
250 | int toxav_kill_transmission(ToxAv *av); | 240 | int toxav_kill_transmission(ToxAv *av, uint32_t call_index); |
251 | 241 | ||
252 | /** | 242 | /** |
253 | * @brief Receive decoded video packet. | 243 | * @brief Receive decoded video packet. |
@@ -258,7 +248,7 @@ int toxav_kill_transmission(ToxAv *av); | |||
258 | * @retval 0 Success. | 248 | * @retval 0 Success. |
259 | * @retval ToxAvError On Error. | 249 | * @retval ToxAvError On Error. |
260 | */ | 250 | */ |
261 | int toxav_recv_video ( ToxAv *av, vpx_image_t **output); | 251 | int toxav_recv_video ( ToxAv* av, uint32_t call_index, vpx_image_t** output); |
262 | 252 | ||
263 | /** | 253 | /** |
264 | * @brief Receive decoded audio frame. | 254 | * @brief Receive decoded audio frame. |
@@ -272,7 +262,7 @@ int toxav_recv_video ( ToxAv *av, vpx_image_t **output); | |||
272 | * @retval >=0 Size of received data in frames/samples. | 262 | * @retval >=0 Size of received data in frames/samples. |
273 | * @retval ToxAvError On error. | 263 | * @retval ToxAvError On error. |
274 | */ | 264 | */ |
275 | int toxav_recv_audio( ToxAv *av, int frame_size, int16_t *dest ); | 265 | int toxav_recv_audio( ToxAv* av, uint32_t call_index, int frame_size, int16_t* dest ); |
276 | 266 | ||
277 | /** | 267 | /** |
278 | * @brief Encode and send video packet. | 268 | * @brief Encode and send video packet. |
@@ -283,7 +273,7 @@ int toxav_recv_audio( ToxAv *av, int frame_size, int16_t *dest ); | |||
283 | * @retval 0 Success. | 273 | * @retval 0 Success. |
284 | * @retval ToxAvError On error. | 274 | * @retval ToxAvError On error. |
285 | */ | 275 | */ |
286 | int toxav_send_video ( ToxAv *av, vpx_image_t *input); | 276 | int toxav_send_video ( ToxAv* av, uint32_t call_index, vpx_image_t* input); |
287 | 277 | ||
288 | /** | 278 | /** |
289 | * @brief Encode and send audio frame. | 279 | * @brief Encode and send audio frame. |
@@ -296,7 +286,7 @@ int toxav_send_video ( ToxAv *av, vpx_image_t *input); | |||
296 | * @retval 0 Success. | 286 | * @retval 0 Success. |
297 | * @retval ToxAvError On error. | 287 | * @retval ToxAvError On error. |
298 | */ | 288 | */ |
299 | int toxav_send_audio ( ToxAv *av, const int16_t *frame, int frame_size); | 289 | int toxav_send_audio ( ToxAv* av, uint32_t call_index, const int16_t* frame, int frame_size); |
300 | 290 | ||
301 | /** | 291 | /** |
302 | * @brief Get peer transmission type. It can either be audio or video. | 292 | * @brief Get peer transmission type. It can either be audio or video. |
@@ -307,7 +297,7 @@ int toxav_send_audio ( ToxAv *av, const int16_t *frame, int frame_size); | |||
307 | * @retval ToxAvCallType On success. | 297 | * @retval ToxAvCallType On success. |
308 | * @retval ToxAvError On error. | 298 | * @retval ToxAvError On error. |
309 | */ | 299 | */ |
310 | int toxav_get_peer_transmission_type ( ToxAv *av, int peer ); | 300 | int toxav_get_peer_transmission_type ( ToxAv *av, uint32_t call_index, int peer ); |
311 | 301 | ||
312 | /** | 302 | /** |
313 | * @brief Get id of peer participating in conversation | 303 | * @brief Get id of peer participating in conversation |
@@ -317,7 +307,7 @@ int toxav_get_peer_transmission_type ( ToxAv *av, int peer ); | |||
317 | * @return int | 307 | * @return int |
318 | * @retval ToxAvError No peer id | 308 | * @retval ToxAvError No peer id |
319 | */ | 309 | */ |
320 | int toxav_get_peer_id ( ToxAv* av, int peer ); | 310 | int toxav_get_peer_id ( ToxAv* av, uint32_t call_index, int peer ); |
321 | 311 | ||
322 | /** | 312 | /** |
323 | * @brief Is certain capability supported | 313 | * @brief Is certain capability supported |
diff --git a/toxcore/DHT.c b/toxcore/DHT.c index 1089e2ff..870e6ca2 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c | |||
@@ -27,6 +27,8 @@ | |||
27 | #include "config.h" | 27 | #include "config.h" |
28 | #endif | 28 | #endif |
29 | 29 | ||
30 | #include "logger.h" | ||
31 | |||
30 | #include "DHT.h" | 32 | #include "DHT.h" |
31 | 33 | ||
32 | #ifdef ENABLE_ASSOC_DHT | 34 | #ifdef ENABLE_ASSOC_DHT |
@@ -198,18 +200,12 @@ static int client_or_ip_port_in_list(Client_data *list, uint32_t length, uint8_t | |||
198 | /* Refresh the client timestamp. */ | 200 | /* Refresh the client timestamp. */ |
199 | if (ip_port.ip.family == AF_INET) { | 201 | if (ip_port.ip.family == AF_INET) { |
200 | 202 | ||
201 | #ifdef LOGGING | 203 | LOGGER_SCOPE( if (!ipport_equal(&list[i].assoc4.ip_port, &ip_port)) { |
202 | 204 | LOGGER_INFO("coipil[%u]: switching ipv4 from %s:%u to %s:%u", i, | |
203 | if (!ipport_equal(&list[i].assoc4.ip_port, &ip_port)) { | 205 | ip_ntoa(&list[i].assoc4.ip_port.ip), ntohs(list[i].assoc4.ip_port.port), |
204 | size_t x; | 206 | ip_ntoa(&ip_port.ip), ntohs(ip_port.port)); |
205 | x = sprintf(logbuffer, "coipil[%u]: switching ipv4 from %s:%u ", i, | 207 | } |
206 | ip_ntoa(&list[i].assoc4.ip_port.ip), ntohs(list[i].assoc4.ip_port.port)); | 208 | ); |
207 | sprintf(logbuffer + x, "to %s:%u\n", | ||
208 | ip_ntoa(&ip_port.ip), ntohs(ip_port.port)); | ||
209 | loglog(logbuffer); | ||
210 | } | ||
211 | |||
212 | #endif | ||
213 | 209 | ||
214 | if (LAN_ip(list[i].assoc4.ip_port.ip) != 0 && LAN_ip(ip_port.ip) == 0) | 210 | if (LAN_ip(list[i].assoc4.ip_port.ip) != 0 && LAN_ip(ip_port.ip) == 0) |
215 | return 1; | 211 | return 1; |
@@ -217,19 +213,13 @@ static int client_or_ip_port_in_list(Client_data *list, uint32_t length, uint8_t | |||
217 | list[i].assoc4.ip_port = ip_port; | 213 | list[i].assoc4.ip_port = ip_port; |
218 | list[i].assoc4.timestamp = temp_time; | 214 | list[i].assoc4.timestamp = temp_time; |
219 | } else if (ip_port.ip.family == AF_INET6) { | 215 | } else if (ip_port.ip.family == AF_INET6) { |
220 | 216 | ||
221 | #ifdef LOGGING | 217 | LOGGER_SCOPE( if (!ipport_equal(&list[i].assoc4.ip_port, &ip_port)) { |
222 | 218 | LOGGER_INFO("coipil[%u]: switching ipv6 from %s:%u to %s:%u", i, | |
223 | if (!ipport_equal(&list[i].assoc6.ip_port, &ip_port)) { | 219 | ip_ntoa(&list[i].assoc6.ip_port.ip), ntohs(list[i].assoc6.ip_port.port), |
224 | size_t x; | 220 | ip_ntoa(&ip_port.ip), ntohs(ip_port.port)); |
225 | x = sprintf(logbuffer, "coipil[%u]: switching ipv6 from %s:%u ", i, | 221 | } |
226 | ip_ntoa(&list[i].assoc6.ip_port.ip), ntohs(list[i].assoc6.ip_port.port)); | 222 | ); |
227 | sprintf(logbuffer + x, "to %s:%u\n", | ||
228 | ip_ntoa(&ip_port.ip), ntohs(ip_port.port)); | ||
229 | loglog(logbuffer); | ||
230 | } | ||
231 | |||
232 | #endif | ||
233 | 223 | ||
234 | if (LAN_ip(list[i].assoc6.ip_port.ip) != 0 && LAN_ip(ip_port.ip) == 0) | 224 | if (LAN_ip(list[i].assoc6.ip_port.ip) != 0 && LAN_ip(ip_port.ip) == 0) |
235 | return 1; | 225 | return 1; |
@@ -251,10 +241,9 @@ static int client_or_ip_port_in_list(Client_data *list, uint32_t length, uint8_t | |||
251 | /* Initialize client timestamp. */ | 241 | /* Initialize client timestamp. */ |
252 | list[i].assoc4.timestamp = temp_time; | 242 | list[i].assoc4.timestamp = temp_time; |
253 | memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); | 243 | memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); |
254 | #ifdef LOGGING | 244 | |
255 | sprintf(logbuffer, "coipil[%u]: switching client_id (ipv4) \n", i); | 245 | LOGGER_DEBUG("coipil[%u]: switching client_id (ipv4)", i); |
256 | loglog(logbuffer); | 246 | |
257 | #endif | ||
258 | /* kill the other address, if it was set */ | 247 | /* kill the other address, if it was set */ |
259 | memset(&list[i].assoc6, 0, sizeof(list[i].assoc6)); | 248 | memset(&list[i].assoc6, 0, sizeof(list[i].assoc6)); |
260 | return 1; | 249 | return 1; |
@@ -262,10 +251,9 @@ static int client_or_ip_port_in_list(Client_data *list, uint32_t length, uint8_t | |||
262 | /* Initialize client timestamp. */ | 251 | /* Initialize client timestamp. */ |
263 | list[i].assoc6.timestamp = temp_time; | 252 | list[i].assoc6.timestamp = temp_time; |
264 | memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); | 253 | memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); |
265 | #ifdef LOGGING | 254 | |
266 | sprintf(logbuffer, "coipil[%u]: switching client_id (ipv6) \n", i); | 255 | LOGGER_DEBUG("coipil[%u]: switching client_id (ipv6)", i); |
267 | loglog(logbuffer); | 256 | |
268 | #endif | ||
269 | /* kill the other address, if it was set */ | 257 | /* kill the other address, if it was set */ |
270 | memset(&list[i].assoc4, 0, sizeof(list[i].assoc4)); | 258 | memset(&list[i].assoc4, 0, sizeof(list[i].assoc4)); |
271 | return 1; | 259 | return 1; |
@@ -469,18 +457,11 @@ int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_fa | |||
469 | uint8_t num_found = Assoc_get_close_entries(dht->assoc, &request); | 457 | uint8_t num_found = Assoc_get_close_entries(dht->assoc, &request); |
470 | 458 | ||
471 | if (!num_found) { | 459 | if (!num_found) { |
472 | #ifdef LOGGING | 460 | LOGGER_DEBUG("get_close_nodes(): Assoc_get_close_entries() returned zero nodes"); |
473 | loglog("get_close_nodes(): Assoc_get_close_entries() returned zero nodes.\n"); | ||
474 | #endif | ||
475 | |||
476 | return get_somewhat_close_nodes(dht, client_id, nodes_list, sa_family, is_LAN, want_good); | 461 | return get_somewhat_close_nodes(dht, client_id, nodes_list, sa_family, is_LAN, want_good); |
477 | } | 462 | } |
478 | 463 | ||
479 | #ifdef LOGGING | 464 | LOGGER_DEBUG("get_close_nodes(): Assoc_get_close_entries() returned %i 'direct' and %i 'indirect' nodes", request.count_good, num_found - request.count_good); |
480 | sprintf(logbuffer, "get_close_nodes(): Assoc_get_close_entries() returned %i 'direct' and %i 'indirect' nodes.\n", | ||
481 | request.count_good, num_found - request.count_good); | ||
482 | loglog(logbuffer); | ||
483 | #endif | ||
484 | 465 | ||
485 | uint8_t i, num_returned = 0; | 466 | uint8_t i, num_returned = 0; |
486 | 467 | ||
diff --git a/toxcore/Makefile.inc b/toxcore/Makefile.inc index 5e529267..5f9ab0d7 100644 --- a/toxcore/Makefile.inc +++ b/toxcore/Makefile.inc | |||
@@ -31,6 +31,8 @@ libtoxcore_la_SOURCES = ../toxcore/DHT.h \ | |||
31 | ../toxcore/assoc.c \ | 31 | ../toxcore/assoc.c \ |
32 | ../toxcore/onion.h \ | 32 | ../toxcore/onion.h \ |
33 | ../toxcore/onion.c \ | 33 | ../toxcore/onion.c \ |
34 | ../toxcore/logger.h \ | ||
35 | ../toxcore/logger.c \ | ||
34 | ../toxcore/onion_announce.h \ | 36 | ../toxcore/onion_announce.h \ |
35 | ../toxcore/onion_announce.c \ | 37 | ../toxcore/onion_announce.c \ |
36 | ../toxcore/onion_client.h \ | 38 | ../toxcore/onion_client.h \ |
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index db5390c0..2033e6a9 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include "config.h" | 25 | #include "config.h" |
26 | #endif | 26 | #endif |
27 | 27 | ||
28 | #include "logger.h" | ||
28 | #include "Messenger.h" | 29 | #include "Messenger.h" |
29 | #include "assoc.h" | 30 | #include "assoc.h" |
30 | #include "network.h" | 31 | #include "network.h" |
@@ -2245,7 +2246,7 @@ void do_messenger(Messenger *m) | |||
2245 | #ifdef LOGGING | 2246 | #ifdef LOGGING |
2246 | 2247 | ||
2247 | if (unix_time() > lastdump + DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS) { | 2248 | if (unix_time() > lastdump + DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS) { |
2248 | loglog(" = = = = = = = = \n"); | 2249 | |
2249 | #ifdef ENABLE_ASSOC_DHT | 2250 | #ifdef ENABLE_ASSOC_DHT |
2250 | Assoc_status(m->dht->assoc); | 2251 | Assoc_status(m->dht->assoc); |
2251 | #endif | 2252 | #endif |
@@ -2254,12 +2255,10 @@ void do_messenger(Messenger *m) | |||
2254 | size_t c; | 2255 | size_t c; |
2255 | 2256 | ||
2256 | for (c = 0; c < m->numchats; c++) { | 2257 | for (c = 0; c < m->numchats; c++) { |
2257 | loglog("---------------- \n"); | ||
2258 | Assoc_status(m->chats[c]->assoc); | 2258 | Assoc_status(m->chats[c]->assoc); |
2259 | } | 2259 | } |
2260 | } | 2260 | } |
2261 | 2261 | ||
2262 | loglog(" = = = = = = = = \n"); | ||
2263 | 2262 | ||
2264 | lastdump = unix_time(); | 2263 | lastdump = unix_time(); |
2265 | uint32_t client, last_pinged; | 2264 | uint32_t client, last_pinged; |
@@ -2276,14 +2275,12 @@ void do_messenger(Messenger *m) | |||
2276 | if (last_pinged > 999) | 2275 | if (last_pinged > 999) |
2277 | last_pinged = 999; | 2276 | last_pinged = 999; |
2278 | 2277 | ||
2279 | snprintf(logbuffer, sizeof(logbuffer), "C[%2u] %s:%u [%3u] %s\n", | 2278 | LOGGER_DEBUG("C[%2u] %s:%u [%3u] %s", |
2280 | client, ip_ntoa(&assoc->ip_port.ip), ntohs(assoc->ip_port.port), | 2279 | client, ip_ntoa(&assoc->ip_port.ip), ntohs(assoc->ip_port.port), |
2281 | last_pinged, ID2String(cptr->client_id)); | 2280 | last_pinged, ID2String(cptr->client_id)); |
2282 | loglog(logbuffer); | ||
2283 | } | 2281 | } |
2284 | } | 2282 | } |
2285 | 2283 | ||
2286 | loglog(" = = = = = = = = \n"); | ||
2287 | 2284 | ||
2288 | uint32_t friend, dhtfriend; | 2285 | uint32_t friend, dhtfriend; |
2289 | 2286 | ||
@@ -2311,9 +2308,7 @@ void do_messenger(Messenger *m) | |||
2311 | dht2m[m2dht[friend]] = friend; | 2308 | dht2m[m2dht[friend]] = friend; |
2312 | 2309 | ||
2313 | if (m->numfriends != m->dht->num_friends) { | 2310 | if (m->numfriends != m->dht->num_friends) { |
2314 | sprintf(logbuffer, "Friend num in DHT %u != friend num in msger %u\n", | 2311 | LOGGER_DEBUG("Friend num in DHT %u != friend num in msger %u\n", m->dht->num_friends, m->numfriends); |
2315 | m->dht->num_friends, m->numfriends); | ||
2316 | loglog(logbuffer); | ||
2317 | } | 2312 | } |
2318 | 2313 | ||
2319 | uint32_t ping_lastrecv; | 2314 | uint32_t ping_lastrecv; |
@@ -2334,14 +2329,11 @@ void do_messenger(Messenger *m) | |||
2334 | if (ping_lastrecv > 999) | 2329 | if (ping_lastrecv > 999) |
2335 | ping_lastrecv = 999; | 2330 | ping_lastrecv = 999; |
2336 | 2331 | ||
2337 | snprintf(logbuffer, sizeof(logbuffer), "F[%2u:%2u] <%s> %02i [%03u] %s\n", | 2332 | LOGGER_DEBUG("F[%2u:%2u] <%s> %02i [%03u] %s", |
2338 | dht2m[friend], friend, msgfptr->name, msgfptr->crypt_connection_id, | 2333 | dht2m[friend], friend, msgfptr->name, msgfptr->crypt_connection_id, |
2339 | ping_lastrecv, ID2String(msgfptr->client_id)); | 2334 | ping_lastrecv, ID2String(msgfptr->client_id)); |
2340 | loglog(logbuffer); | ||
2341 | } else { | 2335 | } else { |
2342 | snprintf(logbuffer, sizeof(logbuffer), "F[--:%2u] %s\n", | 2336 | LOGGER_DEBUG("F[--:%2u] %s", friend, ID2String(dhtfptr->client_id)); |
2343 | friend, ID2String(dhtfptr->client_id)); | ||
2344 | loglog(logbuffer); | ||
2345 | } | 2337 | } |
2346 | 2338 | ||
2347 | for (client = 0; client < MAX_FRIEND_CLIENTS; client++) { | 2339 | for (client = 0; client < MAX_FRIEND_CLIENTS; client++) { |
@@ -2355,20 +2347,16 @@ void do_messenger(Messenger *m) | |||
2355 | 2347 | ||
2356 | if (last_pinged > 999) | 2348 | if (last_pinged > 999) |
2357 | last_pinged = 999; | 2349 | last_pinged = 999; |
2358 | 2350 | ||
2359 | snprintf(logbuffer, sizeof(logbuffer), "F[%2u] => C[%2u] %s:%u [%3u] %s\n", | 2351 | LOGGER_DEBUG("F[%2u] => C[%2u] %s:%u [%3u] %s", |
2360 | friend, client, ip_ntoa(&assoc->ip_port.ip), | 2352 | friend, client, ip_ntoa(&assoc->ip_port.ip), |
2361 | ntohs(assoc->ip_port.port), last_pinged, | 2353 | ntohs(assoc->ip_port.port), last_pinged, |
2362 | ID2String(cptr->client_id)); | 2354 | ID2String(cptr->client_id)); |
2363 | loglog(logbuffer); | ||
2364 | } | 2355 | } |
2365 | } | 2356 | } |
2366 | } | 2357 | } |
2367 | |||
2368 | loglog(" = = = = = = = = \n"); | ||
2369 | } | 2358 | } |
2370 | 2359 | #endif /* LOGGING */ | |
2371 | #endif | ||
2372 | } | 2360 | } |
2373 | 2361 | ||
2374 | /* | 2362 | /* |
diff --git a/toxcore/assoc.c b/toxcore/assoc.c index 2c1f0bad..c8f58c9c 100644 --- a/toxcore/assoc.c +++ b/toxcore/assoc.c | |||
@@ -3,6 +3,7 @@ | |||
3 | #include "config.h" | 3 | #include "config.h" |
4 | #endif | 4 | #endif |
5 | 5 | ||
6 | #include "logger.h" | ||
6 | #include "DHT.h" | 7 | #include "DHT.h" |
7 | #include "assoc.h" | 8 | #include "assoc.h" |
8 | #include "ping.h" | 9 | #include "ping.h" |
@@ -524,9 +525,7 @@ static void client_id_self_update(Assoc *assoc) | |||
524 | assoc->self_hash = id_hash(assoc, assoc->self_client_id); | 525 | assoc->self_hash = id_hash(assoc, assoc->self_client_id); |
525 | } | 526 | } |
526 | 527 | ||
527 | #ifdef LOGGING | 528 | LOGGER_DEBUG("id is now set, purging cache of self-references"); |
528 | loglog("assoc: id is now set, purging cache of self-references...\n"); | ||
529 | #endif | ||
530 | 529 | ||
531 | /* if we already added some (or loaded some) entries, | 530 | /* if we already added some (or loaded some) entries, |
532 | * look and remove if we find a match | 531 | * look and remove if we find a match |
@@ -821,10 +820,8 @@ Assoc *new_Assoc(size_t bits, size_t entries, uint8_t *public_id) | |||
821 | entries_test = prime_upto_min9(entries_test - 1); | 820 | entries_test = prime_upto_min9(entries_test - 1); |
822 | 821 | ||
823 | if (entries_test != entries) { | 822 | if (entries_test != entries) { |
824 | #ifdef LOGGING | 823 | |
825 | sprintf(logbuffer, "new_Assoc(): trimmed %i to %i.\n", (int)entries, (int)entries_test); | 824 | LOGGER_DEBUG("trimmed %i to %i.\n", (int)entries, (int)entries_test); |
826 | loglog(logbuffer); | ||
827 | #endif | ||
828 | entries = (size_t)entries_test; | 825 | entries = (size_t)entries_test; |
829 | } | 826 | } |
830 | } | 827 | } |
@@ -873,7 +870,7 @@ void Assoc_self_client_id_changed(Assoc *assoc, uint8_t *id) | |||
873 | 870 | ||
874 | #ifdef LOGGING | 871 | #ifdef LOGGING |
875 | static char *idpart2str(uint8_t *id, size_t len); | 872 | static char *idpart2str(uint8_t *id, size_t len); |
876 | #endif | 873 | #endif /* LOGGING */ |
877 | 874 | ||
878 | /* refresh buckets */ | 875 | /* refresh buckets */ |
879 | void do_Assoc(Assoc *assoc, DHT *dht) | 876 | void do_Assoc(Assoc *assoc, DHT *dht) |
@@ -929,53 +926,30 @@ void do_Assoc(Assoc *assoc, DHT *dht) | |||
929 | break; | 926 | break; |
930 | } | 927 | } |
931 | 928 | ||
932 | #ifdef LOGGING | ||
933 | size_t total = 0, written = sprintf(logbuffer, "assoc: [%u] => ", | ||
934 | (uint32_t)(candidate % assoc->candidates_bucket_count)); | ||
935 | |||
936 | if (written > 0) | ||
937 | total += written; | ||
938 | |||
939 | #endif | ||
940 | |||
941 | if (seen) { | 929 | if (seen) { |
942 | IPPTsPng *ippts = seen->seen_family == AF_INET ? &seen->client.assoc4 : &seen->client.assoc6; | 930 | IPPTsPng *ippts = seen->seen_family == AF_INET ? &seen->client.assoc4 : &seen->client.assoc6; |
943 | #ifdef LOGGING | 931 | |
944 | written = sprintf(logbuffer + total, " S[%s...] %s:%u", idpart2str(seen->client.client_id, 8), | 932 | LOGGER_DEBUG("[%u] => S[%s...] %s:%u", (uint32_t)(candidate % assoc->candidates_bucket_count), |
945 | ip_ntoa(&ippts->ip_port.ip), htons(ippts->ip_port.port)); | 933 | idpart2str(seen->client.client_id, 8), ip_ntoa(&ippts->ip_port.ip), htons(ippts->ip_port.port)); |
946 | 934 | ||
947 | if (written > 0) | ||
948 | total += written; | ||
949 | |||
950 | #endif | ||
951 | DHT_getnodes(dht, &ippts->ip_port, seen->client.client_id, target_id); | 935 | DHT_getnodes(dht, &ippts->ip_port, seen->client.client_id, target_id); |
952 | seen->getnodes = unix_time(); | 936 | seen->getnodes = unix_time(); |
953 | } | 937 | } |
954 | 938 | ||
955 | if (heard && (heard != seen)) { | 939 | if (heard && (heard != seen)) { |
956 | IP_Port *ipp = heard->heard_family == AF_INET ? &heard->assoc_heard4 : &heard->assoc_heard6; | 940 | IP_Port *ipp = heard->heard_family == AF_INET ? &heard->assoc_heard4 : &heard->assoc_heard6; |
957 | #ifdef LOGGING | 941 | |
958 | written = sprintf(logbuffer + total, " H[%s...] %s:%u", idpart2str(heard->client.client_id, 8), ip_ntoa(&ipp->ip), | 942 | LOGGER_DEBUG("[%u] => H[%s...] %s:%u", (uint32_t)(candidate % assoc->candidates_bucket_count), |
959 | htons(ipp->port)); | 943 | idpart2str(heard->client.client_id, 8), ip_ntoa(&ipp->ip), htons(ipp->port)); |
960 | 944 | ||
961 | if (written > 0) | ||
962 | total += written; | ||
963 | |||
964 | #endif | ||
965 | DHT_getnodes(dht, ipp, heard->client.client_id, target_id); | 945 | DHT_getnodes(dht, ipp, heard->client.client_id, target_id); |
966 | heard->getnodes = unix_time(); | 946 | heard->getnodes = unix_time(); |
967 | } | 947 | } |
968 | 948 | ||
969 | #ifdef LOGGING | 949 | LOGGER_SCOPE ( |
970 | 950 | if ( !heard && !seen ) | |
971 | if (!heard && !seen) | 951 | LOGGER_DEBUG("[%u] => no nodes to talk to??", (uint32_t)(candidate % assoc->candidates_bucket_count)); |
972 | sprintf(logbuffer + total, "no nodes to talk to??\n"); | 952 | ); |
973 | else | ||
974 | /* for arcane reasons, sprintf(str, "\n") doesn't function */ | ||
975 | sprintf(logbuffer + total, "%s", "\n"); | ||
976 | |||
977 | loglog(logbuffer); | ||
978 | #endif | ||
979 | } | 953 | } |
980 | } | 954 | } |
981 | 955 | ||
@@ -1009,11 +983,11 @@ static char *idpart2str(uint8_t *id, size_t len) | |||
1009 | void Assoc_status(Assoc *assoc) | 983 | void Assoc_status(Assoc *assoc) |
1010 | { | 984 | { |
1011 | if (!assoc) { | 985 | if (!assoc) { |
1012 | loglog("Assoc status: no assoc\n"); | 986 | LOGGER_INFO("Assoc status: no assoc"); |
1013 | return; | 987 | return; |
1014 | } | 988 | } |
1015 | 989 | ||
1016 | loglog("[b:p] hash => [id...] used, seen, heard\n"); | 990 | LOGGER_INFO("[b:p] hash => [id...] used, seen, heard"); |
1017 | 991 | ||
1018 | size_t bid, cid, total = 0; | 992 | size_t bid, cid, total = 0; |
1019 | 993 | ||
@@ -1024,24 +998,23 @@ void Assoc_status(Assoc *assoc) | |||
1024 | Client_entry *entry = &bucket->list[cid]; | 998 | Client_entry *entry = &bucket->list[cid]; |
1025 | 999 | ||
1026 | if (entry->hash) { | 1000 | if (entry->hash) { |
1027 | sprintf(logbuffer, "[%3i:%3i] %08x => [%s...] %i, %i(%c), %i(%c)\n", | 1001 | total++; |
1028 | (int)bid, (int)cid, entry->hash, idpart2str(entry->client.client_id, 8), | 1002 | |
1029 | entry->used_at ? (int)(unix_time() - entry->used_at) : 0, | 1003 | LOGGER_INFO("[%3i:%3i] %08x => [%s...] %i, %i(%c), %i(%c)\n", |
1030 | entry->seen_at ? (int)(unix_time() - entry->seen_at) : 0, | 1004 | (int)bid, (int)cid, entry->hash, idpart2str(entry->client.client_id, 8), |
1031 | entry->seen_at ? (entry->seen_family == AF_INET ? '4' : (entry->seen_family == AF_INET6 ? '6' : '?')) : '?', | 1005 | entry->used_at ? (int)(unix_time() - entry->used_at) : 0, |
1006 | entry->seen_at ? (int)(unix_time() - entry->seen_at) : 0, | ||
1007 | entry->seen_at ? (entry->seen_family == AF_INET ? '4' : (entry->seen_family == AF_INET6 ? '6' : '?')) : '?', | ||
1032 | entry->heard_at ? (int)(unix_time() - entry->heard_at) : 0, | 1008 | entry->heard_at ? (int)(unix_time() - entry->heard_at) : 0, |
1033 | entry->heard_at ? (entry->heard_family == AF_INET ? '4' : (entry->heard_family == AF_INET6 ? '6' : '?')) : '?'); | 1009 | entry->heard_at ? (entry->heard_family == AF_INET ? '4' : (entry->heard_family == AF_INET6 ? '6' : '?')) : '?'); |
1034 | loglog(logbuffer); | ||
1035 | total++; | ||
1036 | } | 1010 | } |
1037 | } | 1011 | } |
1038 | } | 1012 | } |
1039 | 1013 | ||
1040 | if (total) { | 1014 | if (total) { |
1041 | sprintf(logbuffer, "Total: %i entries, table usage %i%%.\n", (int)total, | 1015 | LOGGER_INFO("Total: %i entries, table usage %i%%.\n", (int)total, |
1042 | (int)(total * 100 / (assoc->candidates_bucket_count * assoc->candidates_bucket_size))); | 1016 | (int)(total * 100 / (assoc->candidates_bucket_count * assoc->candidates_bucket_size))); |
1043 | loglog(logbuffer); | ||
1044 | } | 1017 | } |
1045 | } | 1018 | } |
1046 | 1019 | ||
1047 | #endif | 1020 | #endif /* LOGGING */ |
diff --git a/toxcore/assoc.h b/toxcore/assoc.h index 9dbc75f2..0fdff4fe 100644 --- a/toxcore/assoc.h +++ b/toxcore/assoc.h | |||
@@ -98,6 +98,6 @@ void kill_Assoc(Assoc *assoc); | |||
98 | 98 | ||
99 | #ifdef LOGGING | 99 | #ifdef LOGGING |
100 | void Assoc_status(Assoc *assoc); | 100 | void Assoc_status(Assoc *assoc); |
101 | #endif | 101 | #endif /* LOGGING */ |
102 | 102 | ||
103 | #endif /* !__ASSOC_H__ */ | 103 | #endif /* !__ASSOC_H__ */ |
diff --git a/toxcore/logger.c b/toxcore/logger.c new file mode 100644 index 00000000..e700fe71 --- /dev/null +++ b/toxcore/logger.c | |||
@@ -0,0 +1,159 @@ | |||
1 | /* logger.c | ||
2 | * | ||
3 | * Wrapping logger functions in nice macros | ||
4 | * | ||
5 | * Copyright (C) 2013 Tox project All Rights Reserved. | ||
6 | * | ||
7 | * This file is part of Tox. | ||
8 | * | ||
9 | * Tox is free software: you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation, either version 3 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * Tox is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with Tox. If not, see <http://www.gnu.org/licenses/>. | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #ifdef HAVE_CONFIG_H | ||
25 | #include "config.h" | ||
26 | #endif /* HAVE_CONFIG_H */ | ||
27 | |||
28 | |||
29 | #include "logger.h" | ||
30 | |||
31 | #ifdef LOGGING | ||
32 | |||
33 | #include "network.h" /* for time */ | ||
34 | |||
35 | #include <stdio.h> | ||
36 | #include <errno.h> | ||
37 | #include <stdlib.h> | ||
38 | #include <stdarg.h> | ||
39 | #include <inttypes.h> | ||
40 | #include <time.h> | ||
41 | |||
42 | #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) | ||
43 | #define strerror_r(errno,buf,len) strerror_s(buf,len,errno) | ||
44 | #endif | ||
45 | |||
46 | static struct logger_config { | ||
47 | FILE* log_file; | ||
48 | LoggerLevel level; | ||
49 | uint64_t start_time; /* Time when lib loaded */ | ||
50 | } | ||
51 | logger = { | ||
52 | NULL, | ||
53 | DEBUG, | ||
54 | 0 | ||
55 | }; | ||
56 | |||
57 | void __attribute__((destructor)) terminate_logger() | ||
58 | { | ||
59 | if ( !logger.log_file ) return; | ||
60 | |||
61 | time_t tim = time(NULL); | ||
62 | |||
63 | logger_write(ERROR, "============== Closing logger ==============\n" | ||
64 | "Time: %s", asctime(localtime(&tim))); | ||
65 | |||
66 | fclose(logger.log_file); | ||
67 | } | ||
68 | |||
69 | unsigned logger_get_pid() | ||
70 | { | ||
71 | return | ||
72 | #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) | ||
73 | GetCurrentProcessId(); | ||
74 | #else | ||
75 | getpid(); | ||
76 | #endif | ||
77 | } | ||
78 | |||
79 | const char* logger_stringify_level(LoggerLevel level) | ||
80 | { | ||
81 | static const char* strings [] = | ||
82 | { | ||
83 | "INFO", | ||
84 | "DEBUG", | ||
85 | "WARNING", | ||
86 | "ERROR" | ||
87 | }; | ||
88 | |||
89 | return strings[level]; | ||
90 | } | ||
91 | |||
92 | |||
93 | int logger_init(const char* file_name, LoggerLevel level) | ||
94 | { | ||
95 | char* final_l = calloc(sizeof(char), strlen(file_name) + 32); | ||
96 | sprintf(final_l, "%s"/*.%u"*/, file_name, logger_get_pid()); | ||
97 | |||
98 | if ( logger.log_file ) { | ||
99 | fprintf(stderr, "Error opening logger name: %s with level %d: already opened!\n", final_l, level); | ||
100 | free (final_l); | ||
101 | return -1; | ||
102 | } | ||
103 | |||
104 | logger.log_file = fopen(final_l, "wb"); | ||
105 | |||
106 | if ( logger.log_file == NULL ) { | ||
107 | char error[1000]; | ||
108 | if ( strerror_r(errno, error, 1000) == 0 ) | ||
109 | fprintf(stderr, "Error opening logger file: %s; info: %s\n", final_l, error); | ||
110 | else | ||
111 | fprintf(stderr, "Error opening logger file: %s\n", final_l); | ||
112 | |||
113 | free (final_l); | ||
114 | return -1; | ||
115 | } | ||
116 | |||
117 | |||
118 | logger.level = level; | ||
119 | logger.start_time = current_time(); | ||
120 | |||
121 | |||
122 | time_t tim = time(NULL); | ||
123 | logger_write(ERROR, "============== Starting logger ==============\n" | ||
124 | "Time: %s", asctime(localtime(&tim))); | ||
125 | |||
126 | |||
127 | |||
128 | free (final_l); | ||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | |||
133 | void logger_write (LoggerLevel level, const char* format, ...) | ||
134 | { | ||
135 | if (logger.log_file == NULL) { | ||
136 | /*fprintf(stderr, "Logger file is NULL!\n");*/ | ||
137 | return; | ||
138 | } | ||
139 | |||
140 | if (logger.level > level) return; /* Don't print some levels xuh */ | ||
141 | |||
142 | va_list _arg; | ||
143 | va_start (_arg, format); | ||
144 | vfprintf (logger.log_file, format, _arg); | ||
145 | va_end (_arg); | ||
146 | |||
147 | fflush(logger.log_file); | ||
148 | } | ||
149 | |||
150 | char* logger_timestr(char* dest) | ||
151 | { | ||
152 | uint64_t diff = (current_time() - logger.start_time) / 1000; /* ms */ | ||
153 | sprintf(dest, "%"PRIu64"", diff); | ||
154 | |||
155 | return dest; | ||
156 | } | ||
157 | |||
158 | |||
159 | #endif /* LOGGING */ \ No newline at end of file | ||
diff --git a/toxcore/logger.h b/toxcore/logger.h new file mode 100644 index 00000000..6c65850e --- /dev/null +++ b/toxcore/logger.h | |||
@@ -0,0 +1,86 @@ | |||
1 | /* logger.h | ||
2 | * | ||
3 | * Wrapping logger functions in nice macros | ||
4 | * | ||
5 | * Copyright (C) 2013 Tox project All Rights Reserved. | ||
6 | * | ||
7 | * This file is part of Tox. | ||
8 | * | ||
9 | * Tox is free software: you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation, either version 3 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * Tox is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with Tox. If not, see <http://www.gnu.org/licenses/>. | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | |||
25 | #ifndef __TOXLOGGER | ||
26 | #define __TOXLOGGER | ||
27 | |||
28 | // #define LOGGING | ||
29 | |||
30 | #ifdef LOGGING | ||
31 | #include <string.h> | ||
32 | |||
33 | typedef enum _LoggerLevel | ||
34 | { | ||
35 | INFO, | ||
36 | DEBUG, | ||
37 | WARNING, | ||
38 | ERROR | ||
39 | } LoggerLevel; | ||
40 | |||
41 | /* | ||
42 | * Set 'level' as the lowest printable level | ||
43 | */ | ||
44 | int logger_init(const char* file_name, LoggerLevel level); | ||
45 | const char* logger_stringify_level(LoggerLevel level); | ||
46 | unsigned logger_get_pid(); | ||
47 | void logger_write (LoggerLevel level, const char* format, ...); | ||
48 | char* logger_timestr (char* dest); | ||
49 | |||
50 | #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) | ||
51 | #define _SFILE (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__) | ||
52 | #else | ||
53 | #define _SFILE (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) | ||
54 | #endif | ||
55 | |||
56 | #define WRITE_FORMAT(__LEVEL__, format) char* the_str = calloc(sizeof(char), strlen(format)+ 500); sprintf(the_str, "[%u] [%s] [%s] [%s:%d %s()] %s\n", \ | ||
57 | logger_get_pid(), logger_stringify_level(__LEVEL__), logger_timestr(__time__), _SFILE, __LINE__, __func__, format) | ||
58 | |||
59 | /* Use these macros */ | ||
60 | |||
61 | #define LOGGER_INIT(name, level) logger_init(name, level); | ||
62 | #define LOGGER_INFO(format, ...) do { char __time__[20]; WRITE_FORMAT(INFO, format); logger_write( INFO, the_str, ##__VA_ARGS__ ); free(the_str); } while (0) | ||
63 | #define LOGGER_DEBUG(format, ...) do { char __time__[20]; WRITE_FORMAT(DEBUG, format); logger_write( DEBUG, the_str, ##__VA_ARGS__ ); free(the_str); } while (0) | ||
64 | #define LOGGER_WARNING(format, ...) do { char __time__[20]; WRITE_FORMAT(WARNING, format); logger_write( WARNING, the_str, ##__VA_ARGS__ ); free(the_str); } while (0) | ||
65 | #define LOGGER_ERROR(format, ...) do { char __time__[20]; WRITE_FORMAT(ERROR, format); logger_write( ERROR, the_str, ##__VA_ARGS__ ); free(the_str); } while (0) | ||
66 | |||
67 | /* To do some checks or similar only when logging use this */ | ||
68 | #define LOGGER_SCOPE(__SCOPE_DO__) do { __SCOPE_DO__ } while(0) | ||
69 | |||
70 | #else | ||
71 | |||
72 | |||
73 | #define LOGGER_INIT(name, level) | ||
74 | #define LOGGER_INFO(format, ...) | ||
75 | #define LOGGER_DEBUG(format, ...) | ||
76 | #define LOGGER_WARNING(format, ...) | ||
77 | #define LOGGER_ERROR(format, ...) | ||
78 | |||
79 | #define LOGGER_SCOPE(__SCOPE_DO__) | ||
80 | |||
81 | #endif /* LOGGING */ | ||
82 | |||
83 | |||
84 | |||
85 | |||
86 | #endif /* __TOXLOGGER */ \ No newline at end of file | ||
diff --git a/toxcore/network.c b/toxcore/network.c index 47afab8e..7262f352 100644 --- a/toxcore/network.c +++ b/toxcore/network.c | |||
@@ -29,6 +29,9 @@ | |||
29 | #include "config.h" | 29 | #include "config.h" |
30 | #endif | 30 | #endif |
31 | 31 | ||
32 | #define LOGGING | ||
33 | #include "logger.h" | ||
34 | |||
32 | #if !defined(_WIN32) && !defined(__WIN32__) && !defined (WIN32) | 35 | #if !defined(_WIN32) && !defined(__WIN32__) && !defined (WIN32) |
33 | #include <errno.h> | 36 | #include <errno.h> |
34 | #endif | 37 | #endif |
@@ -205,9 +208,32 @@ uint64_t random_64b(void) | |||
205 | return randnum; | 208 | return randnum; |
206 | } | 209 | } |
207 | 210 | ||
208 | #ifdef LOGGING | 211 | /* In case no logging */ |
209 | static void loglogdata(char *message, uint8_t *buffer, size_t buflen, IP_Port *ip_port, ssize_t res); | 212 | #ifndef LOGGING |
210 | #endif | 213 | |
214 | #define loglogdata(__message__, __buffer__, __buflen__, __ip_port__, __res__) | ||
215 | |||
216 | #else | ||
217 | |||
218 | #define data_0(__buflen__, __buffer__) __buflen__ > 4 ? ntohl(*(uint32_t *)&__buffer__[1]) : 0 | ||
219 | #define data_1(__buflen__, __buffer__) __buflen__ > 7 ? ntohl(*(uint32_t *)&__buffer__[5]) : 0 | ||
220 | |||
221 | #define loglogdata(__message__, __buffer__, __buflen__, __ip_port__, __res__) \ | ||
222 | (__ip_port__) .ip; \ | ||
223 | if (__res__ < 0) /* Windows doesn't necessarily know %zu */ \ | ||
224 | LOGGER_INFO("[%2u] %s %3hu%c %s:%hu (%u: %s) | %04x%04x", \ | ||
225 | __buffer__[0], __message__, (__buflen__ < 999 ? (uint16_t)__buflen__ : 999), 'E', \ | ||
226 | ip_ntoa(&((__ip_port__).ip)), ntohs((__ip_port__).port), errno, strerror(errno), data_0(__buflen__, __buffer__), data_1(__buflen__, __buffer__)); \ | ||
227 | else if ((__res__ > 0) && ((size_t)__res__ <= __buflen__)) \ | ||
228 | LOGGER_INFO("[%2u] %s %3zu%c %s:%hu (%u: %s) | %04x%04x", \ | ||
229 | __buffer__[0], __message__, (__res__ < 999 ? (size_t)__res__ : 999), ((size_t)__res__ < __buflen__ ? '<' : '='), \ | ||
230 | ip_ntoa(&((__ip_port__).ip)), ntohs((__ip_port__).port), 0, "OK", data_0(__buflen__, __buffer__), data_1(__buflen__, __buffer__)); \ | ||
231 | else /* empty or overwrite */ \ | ||
232 | LOGGER_INFO("[%2u] %s %zu%c%zu %s:%hu (%u: %s) | %04x%04x", \ | ||
233 | __buffer__[0], __message__, (size_t)__res__, (!__res__ ? '!' : '>'), __buflen__, \ | ||
234 | ip_ntoa(&((__ip_port__).ip)), ntohs((__ip_port__).port), 0, "OK", data_0(__buflen__, __buffer__), data_1(__buflen__, __buffer__)); | ||
235 | |||
236 | #endif /* LOGGING */ | ||
211 | 237 | ||
212 | /* Basic network functions: | 238 | /* Basic network functions: |
213 | * Function to send packet(data) of length length to ip_port. | 239 | * Function to send packet(data) of length length to ip_port. |
@@ -266,9 +292,9 @@ int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t le | |||
266 | } | 292 | } |
267 | 293 | ||
268 | int res = sendto(net->sock, (char *) data, length, 0, (struct sockaddr *)&addr, addrsize); | 294 | int res = sendto(net->sock, (char *) data, length, 0, (struct sockaddr *)&addr, addrsize); |
269 | #ifdef LOGGING | 295 | |
270 | loglogdata("O=>", data, length, &ip_port, res); | 296 | loglogdata("O=>", data, length, ip_port, res); |
271 | #endif | 297 | |
272 | 298 | ||
273 | if ((res >= 0) && ((uint32_t)res == length)) | 299 | if ((res >= 0) && ((uint32_t)res == length)) |
274 | net->send_fail_eagain = 0; | 300 | net->send_fail_eagain = 0; |
@@ -297,14 +323,10 @@ static int receivepacket(sock_t sock, IP_Port *ip_port, uint8_t *data, uint32_t | |||
297 | int fail_or_len = recvfrom(sock, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen); | 323 | int fail_or_len = recvfrom(sock, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen); |
298 | 324 | ||
299 | if (fail_or_len <= 0) { | 325 | if (fail_or_len <= 0) { |
300 | #ifdef LOGGING | 326 | |
301 | 327 | LOGGER_SCOPE( if ((fail_or_len < 0) && (errno != EWOULDBLOCK)) | |
302 | if ((fail_or_len < 0) && (errno != EWOULDBLOCK)) { | 328 | LOGGER_ERROR("Unexpected error reading from socket: %u, %s\n", errno, strerror(errno)); ); |
303 | sprintf(logbuffer, "Unexpected error reading from socket: %u, %s\n", errno, strerror(errno)); | 329 | |
304 | loglog(logbuffer); | ||
305 | } | ||
306 | |||
307 | #endif | ||
308 | return -1; /* Nothing received or empty packet. */ | 330 | return -1; /* Nothing received or empty packet. */ |
309 | } | 331 | } |
310 | 332 | ||
@@ -329,9 +351,7 @@ static int receivepacket(sock_t sock, IP_Port *ip_port, uint8_t *data, uint32_t | |||
329 | } else | 351 | } else |
330 | return -1; | 352 | return -1; |
331 | 353 | ||
332 | #ifdef LOGGING | 354 | loglogdata("=>O", data, MAX_UDP_PACKET_SIZE, *ip_port, *length); |
333 | loglogdata("=>O", data, MAX_UDP_PACKET_SIZE, ip_port, *length); | ||
334 | #endif | ||
335 | 355 | ||
336 | return 0; | 356 | return 0; |
337 | } | 357 | } |
@@ -354,10 +374,7 @@ void networking_poll(Networking_Core *net) | |||
354 | if (length < 1) continue; | 374 | if (length < 1) continue; |
355 | 375 | ||
356 | if (!(net->packethandlers[data[0]].function)) { | 376 | if (!(net->packethandlers[data[0]].function)) { |
357 | #ifdef LOGGING | 377 | LOGGER_WARNING("[%02u] -- Packet has no handler.\n", data[0]); |
358 | sprintf(logbuffer, "[%02u] -- Packet has no handler.\n", data[0]); | ||
359 | loglog(logbuffer); | ||
360 | #endif | ||
361 | continue; | 378 | continue; |
362 | } | 379 | } |
363 | 380 | ||
@@ -460,22 +477,14 @@ int networking_wait_execute(uint8_t *data, long seconds, long microseconds) | |||
460 | timeout.tv_usec = microseconds; | 477 | timeout.tv_usec = microseconds; |
461 | } | 478 | } |
462 | 479 | ||
463 | #ifdef LOGGING | ||
464 | errno = 0; | ||
465 | #endif | ||
466 | /* returns -1 on error, 0 on timeout, the socket on activity */ | 480 | /* returns -1 on error, 0 on timeout, the socket on activity */ |
467 | int res = select(nfds, &readfds, &writefds, &exceptfds, timeout_ptr); | 481 | int res = select(nfds, &readfds, &writefds, &exceptfds, timeout_ptr); |
468 | #ifdef LOGGING | 482 | |
469 | 483 | LOGGER_SCOPE( | |
470 | /* only dump if not timeout */ | 484 | if (res) LOGGER_INFO("select(%d, %d): %d (%d, %s) - %d %d %d\n", microseconds, seconds, res, errno, |
471 | if (res) { | 485 | strerror(errno), FD_ISSET(s->sock, &readfds), FD_ISSET(s->sock, &writefds), |
472 | sprintf(logbuffer, "select(%d, %d): %d (%d, %s) - %d %d %d\n", microseconds, seconds, res, errno, | 486 | FD_ISSET(s->sock, &exceptfds)); |
473 | strerror(errno), FD_ISSET(s->sock, &readfds), FD_ISSET(s->sock, &writefds), | 487 | ); |
474 | FD_ISSET(s->sock, &exceptfds)); | ||
475 | loglog(logbuffer); | ||
476 | } | ||
477 | |||
478 | #endif | ||
479 | 488 | ||
480 | if (FD_ISSET(s->sock, &writefds)) { | 489 | if (FD_ISSET(s->sock, &writefds)) { |
481 | s->send_fail_reset = 1; | 490 | s->send_fail_reset = 1; |
@@ -628,20 +637,12 @@ Networking_Core *new_networking(IP ip, uint16_t port) | |||
628 | } | 637 | } |
629 | 638 | ||
630 | if (ip.family == AF_INET6) { | 639 | if (ip.family == AF_INET6) { |
640 | |||
631 | #ifdef LOGGING | 641 | #ifdef LOGGING |
632 | int is_dualstack = | 642 | int is_dualstack = |
633 | #endif | 643 | #endif /* LOGGING */ |
634 | set_socket_dualstack(temp->sock); | 644 | set_socket_dualstack(temp->sock); |
635 | #ifdef LOGGING | 645 | LOGGER_DEBUG( "Dual-stack socket: %s", is_dualstack ? "enabled" : "Failed to enable, won't be able to receive from/send to IPv4 addresses" ); |
636 | |||
637 | if (is_dualstack) { | ||
638 | loglog("Dual-stack socket: enabled.\n"); | ||
639 | } else { | ||
640 | loglog("Dual-stack socket: Failed to enable, won't be able to receive from/send to IPv4 addresses.\n"); | ||
641 | } | ||
642 | |||
643 | #endif | ||
644 | |||
645 | /* multicast local nodes */ | 646 | /* multicast local nodes */ |
646 | struct ipv6_mreq mreq; | 647 | struct ipv6_mreq mreq; |
647 | memset(&mreq, 0, sizeof(mreq)); | 648 | memset(&mreq, 0, sizeof(mreq)); |
@@ -649,21 +650,13 @@ Networking_Core *new_networking(IP ip, uint16_t port) | |||
649 | mreq.ipv6mr_multiaddr.s6_addr[ 1] = 0x02; | 650 | mreq.ipv6mr_multiaddr.s6_addr[ 1] = 0x02; |
650 | mreq.ipv6mr_multiaddr.s6_addr[15] = 0x01; | 651 | mreq.ipv6mr_multiaddr.s6_addr[15] = 0x01; |
651 | mreq.ipv6mr_interface = 0; | 652 | mreq.ipv6mr_interface = 0; |
653 | |||
652 | #ifdef LOGGING | 654 | #ifdef LOGGING |
653 | errno = 0; | ||
654 | int res = | 655 | int res = |
655 | #endif | 656 | #endif /* LOGGING */ |
656 | setsockopt(temp->sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq)); | 657 | setsockopt(temp->sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq)); |
657 | #ifdef LOGGING | 658 | |
658 | 659 | LOGGER_DEBUG(res < 0 ? "Failed to activate local multicast membership. (%u, %s)" : "Local multicast group FF02::1 joined successfully", errno, strerror(errno) ); | |
659 | if (res < 0) { | ||
660 | sprintf(logbuffer, "Failed to activate local multicast membership. (%u, %s)\n", | ||
661 | errno, strerror(errno)); | ||
662 | loglog(logbuffer); | ||
663 | } else | ||
664 | loglog("Local multicast group FF02::1 joined successfully.\n"); | ||
665 | |||
666 | #endif | ||
667 | } | 660 | } |
668 | 661 | ||
669 | /* a hanging program or a different user might block the standard port; | 662 | /* a hanging program or a different user might block the standard port; |
@@ -691,13 +684,9 @@ Networking_Core *new_networking(IP ip, uint16_t port) | |||
691 | 684 | ||
692 | if (!res) { | 685 | if (!res) { |
693 | temp->port = *portptr; | 686 | temp->port = *portptr; |
694 | #ifdef LOGGING | 687 | |
695 | loginit(temp->port); | 688 | LOGGER_DEBUG("Bound successfully to %s:%u", ip_ntoa(&ip), ntohs(temp->port)); |
696 | 689 | ||
697 | sprintf(logbuffer, "Bound successfully to %s:%u.\n", ip_ntoa(&ip), ntohs(temp->port)); | ||
698 | loglog(logbuffer); | ||
699 | #endif | ||
700 | |||
701 | /* errno isn't reset on success, only set on failure, the failed | 690 | /* errno isn't reset on success, only set on failure, the failed |
702 | * binds with parallel clients yield a -EPERM to the outside if | 691 | * binds with parallel clients yield a -EPERM to the outside if |
703 | * errno isn't cleared here */ | 692 | * errno isn't cleared here */ |
@@ -1038,31 +1027,3 @@ int addr_resolve_or_parse_ip(const char *address, IP *to, IP *extra) | |||
1038 | 1027 | ||
1039 | return 1; | 1028 | return 1; |
1040 | }; | 1029 | }; |
1041 | |||
1042 | #ifdef LOGGING | ||
1043 | static char errmsg_ok[3] = "OK"; | ||
1044 | static void loglogdata(char *message, uint8_t *buffer, size_t buflen, IP_Port *ip_port, ssize_t res) | ||
1045 | { | ||
1046 | uint16_t port = ntohs(ip_port->port); | ||
1047 | uint32_t data[2]; | ||
1048 | data[0] = buflen > 4 ? ntohl(*(uint32_t *)&buffer[1]) : 0; | ||
1049 | data[1] = buflen > 7 ? ntohl(*(uint32_t *)&buffer[5]) : 0; | ||
1050 | |||
1051 | /* Windows doesn't necessarily know %zu */ | ||
1052 | if (res < 0) { | ||
1053 | snprintf(logbuffer, sizeof(logbuffer), "[%2u] %s %3hu%c %s:%hu (%u: %s) | %04x%04x\n", | ||
1054 | buffer[0], message, (buflen < 999 ? (uint16_t)buflen : 999), 'E', | ||
1055 | ip_ntoa(&ip_port->ip), port, errno, strerror(errno), data[0], data[1]); | ||
1056 | } else if ((res > 0) && ((size_t)res <= buflen)) | ||
1057 | snprintf(logbuffer, sizeof(logbuffer), "[%2u] %s %3zu%c %s:%hu (%u: %s) | %04x%04x\n", | ||
1058 | buffer[0], message, (res < 999 ? (size_t)res : 999), ((size_t)res < buflen ? '<' : '='), | ||
1059 | ip_ntoa(&ip_port->ip), port, 0, errmsg_ok, data[0], data[1]); | ||
1060 | else /* empty or overwrite */ | ||
1061 | snprintf(logbuffer, sizeof(logbuffer), "[%2u] %s %zu%c%zu %s:%hu (%u: %s) | %04x%04x\n", | ||
1062 | buffer[0], message, (size_t)res, (!res ? '!' : '>'), buflen, | ||
1063 | ip_ntoa(&ip_port->ip), port, 0, errmsg_ok, data[0], data[1]); | ||
1064 | |||
1065 | logbuffer[sizeof(logbuffer) - 1] = 0; | ||
1066 | loglog(logbuffer); | ||
1067 | } | ||
1068 | #endif | ||
diff --git a/toxcore/tox.c b/toxcore/tox.c index c07473dd..9b99174c 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #endif | 26 | #endif |
27 | 27 | ||
28 | #include "Messenger.h" | 28 | #include "Messenger.h" |
29 | #include "logger.h" | ||
29 | 30 | ||
30 | #define __TOX_DEFINED__ | 31 | #define __TOX_DEFINED__ |
31 | typedef struct Messenger Tox; | 32 | typedef struct Messenger Tox; |
@@ -773,6 +774,7 @@ int tox_isconnected(Tox *tox) | |||
773 | */ | 774 | */ |
774 | Tox *tox_new(uint8_t ipv6enabled) | 775 | Tox *tox_new(uint8_t ipv6enabled) |
775 | { | 776 | { |
777 | LOGGER_INIT(LOGGER_OUTPUT_FILE, LOGGER_LEVEL); | ||
776 | return new_messenger(ipv6enabled); | 778 | return new_messenger(ipv6enabled); |
777 | } | 779 | } |
778 | 780 | ||
diff --git a/toxcore/util.c b/toxcore/util.c index d56c446e..edc611ec 100644 --- a/toxcore/util.c +++ b/toxcore/util.c | |||
@@ -134,87 +134,3 @@ int load_state(load_state_callback_func load_state_callback, void *outer, | |||
134 | 134 | ||
135 | return length == 0 ? 0 : -1; | 135 | return length == 0 ? 0 : -1; |
136 | }; | 136 | }; |
137 | |||
138 | #ifdef LOGGING | ||
139 | time_t starttime = 0; | ||
140 | size_t logbufferprelen = 0; | ||
141 | char *logbufferpredata = NULL; | ||
142 | char *logbufferprehead = NULL; | ||
143 | char logbuffer[512]; | ||
144 | static FILE *logfile = NULL; | ||
145 | void loginit(uint16_t port) | ||
146 | { | ||
147 | if (logfile) | ||
148 | fclose(logfile); | ||
149 | |||
150 | if (!starttime) { | ||
151 | unix_time_update(); | ||
152 | starttime = unix_time(); | ||
153 | } | ||
154 | |||
155 | struct tm *tm = localtime(&starttime); | ||
156 | |||
157 | /* "%F %T" might not be Windows compatible */ | ||
158 | if (strftime(logbuffer + 32, sizeof(logbuffer) - 32, "%F %T", tm)) | ||
159 | sprintf(logbuffer, "%u-%s.log", ntohs(port), logbuffer + 32); | ||
160 | else | ||
161 | sprintf(logbuffer, "%u-%lu.log", ntohs(port), starttime); | ||
162 | |||
163 | logfile = fopen(logbuffer, "w"); | ||
164 | |||
165 | if (logbufferpredata) { | ||
166 | if (logfile) | ||
167 | fprintf(logfile, "%s", logbufferpredata); | ||
168 | |||
169 | free(logbufferpredata); | ||
170 | logbufferpredata = NULL; | ||
171 | } | ||
172 | |||
173 | }; | ||
174 | void loglog(char *text) | ||
175 | { | ||
176 | if (logfile) { | ||
177 | fprintf(logfile, "%4u %s", (uint32_t)(unix_time() - starttime), text); | ||
178 | fflush(logfile); | ||
179 | |||
180 | return; | ||
181 | } | ||
182 | |||
183 | /* log messages before file was opened: store */ | ||
184 | |||
185 | size_t len = strlen(text); | ||
186 | |||
187 | if (!starttime) { | ||
188 | unix_time_update(); | ||
189 | starttime = unix_time(); | ||
190 | |||
191 | logbufferprelen = 1024 + len - (len % 1024); | ||
192 | logbufferpredata = malloc(logbufferprelen); | ||
193 | logbufferprehead = logbufferpredata; | ||
194 | } | ||
195 | |||
196 | /* loginit() called meanwhile? (but failed to open) */ | ||
197 | if (!logbufferpredata) | ||
198 | return; | ||
199 | |||
200 | if (len + (logbufferprehead - logbufferpredata) + 16U < logbufferprelen) { | ||
201 | size_t logpos = logbufferprehead - logbufferpredata; | ||
202 | size_t lennew = logbufferprelen * 1.4; | ||
203 | logbufferpredata = realloc(logbufferpredata, lennew); | ||
204 | logbufferprehead = logbufferpredata + logpos; | ||
205 | logbufferprelen = lennew; | ||
206 | } | ||
207 | |||
208 | int written = sprintf(logbufferprehead, "%4u %s", (uint32_t)(unix_time() - starttime), text); | ||
209 | logbufferprehead += written; | ||
210 | } | ||
211 | |||
212 | void logexit() | ||
213 | { | ||
214 | if (logfile) { | ||
215 | fclose(logfile); | ||
216 | logfile = NULL; | ||
217 | } | ||
218 | }; | ||
219 | #endif | ||
220 | |||
diff --git a/toxcore/util.h b/toxcore/util.h index ae364d52..e40b6968 100644 --- a/toxcore/util.h +++ b/toxcore/util.h | |||
@@ -45,11 +45,4 @@ typedef int (*load_state_callback_func)(void *outer, uint8_t *data, uint32_t len | |||
45 | int load_state(load_state_callback_func load_state_callback, void *outer, | 45 | int load_state(load_state_callback_func load_state_callback, void *outer, |
46 | uint8_t *data, uint32_t length, uint16_t cookie_inner); | 46 | uint8_t *data, uint32_t length, uint16_t cookie_inner); |
47 | 47 | ||
48 | #ifdef LOGGING | ||
49 | extern char logbuffer[512]; | ||
50 | void loginit(uint16_t port); | ||
51 | void loglog(char *text); | ||
52 | void logexit(); | ||
53 | #endif | ||
54 | |||
55 | #endif /* __UTIL_H__ */ | 48 | #endif /* __UTIL_H__ */ |