diff options
Diffstat (limited to 'toxav/phone.c')
-rwxr-xr-x | toxav/phone.c | 737 |
1 files changed, 737 insertions, 0 deletions
diff --git a/toxav/phone.c b/toxav/phone.c new file mode 100755 index 00000000..b55a072c --- /dev/null +++ b/toxav/phone.c | |||
@@ -0,0 +1,737 @@ | |||
1 | /** phone.c | ||
2 | * | ||
3 | * NOTE NOTE NOTE NOTE NOTE NOTE | ||
4 | * | ||
5 | * This file is for testing/reference purposes only, hence | ||
6 | * it is _poorly_ designed and it does not fully reflect the | ||
7 | * quaility of msi nor rtp. Although toxmsi* and toxrtp* are tested | ||
8 | * there is always possiblity of crashes. If crash occures, | ||
9 | * contact me ( mannol ) on either irc channel #tox-dev @ freenode.net:6667 | ||
10 | * or eniz_vukovic@hotmail.com | ||
11 | * | ||
12 | * NOTE NOTE NOTE NOTE NOTE NOTE | ||
13 | * | ||
14 | * Copyright (C) 2013 Tox project All Rights Reserved. | ||
15 | * | ||
16 | * This file is part of Tox. | ||
17 | * | ||
18 | * Tox is free software: you can redistribute it and/or modify | ||
19 | * it under the terms of the GNU General Public License as published by | ||
20 | * the Free Software Foundation, either version 3 of the License, or | ||
21 | * (at your option) any later version. | ||
22 | * | ||
23 | * Tox is distributed in the hope that it will be useful, | ||
24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
26 | * GNU General Public License for more details. | ||
27 | * | ||
28 | * You should have received a copy of the GNU General Public License | ||
29 | * along with Tox. If not, see <http://www.gnu.org/licenses/>. | ||
30 | * | ||
31 | */ | ||
32 | |||
33 | #ifdef HAVE_CONFIG_H | ||
34 | #include "config.h" | ||
35 | #endif /* HAVE_CONFIG_H */ | ||
36 | |||
37 | #define _BSD_SOURCE | ||
38 | #define _GNU_SOURCE | ||
39 | |||
40 | #include <stdio.h> | ||
41 | #include <string.h> | ||
42 | #include <stdlib.h> | ||
43 | |||
44 | #include "toxmsi.h" | ||
45 | #include "toxrtp.h" | ||
46 | #include <stdarg.h> | ||
47 | #include <unistd.h> | ||
48 | #include <assert.h> | ||
49 | |||
50 | #include "../toxcore/network.h" | ||
51 | #include "../toxcore/event.h" | ||
52 | #include "../toxcore/tox.h" | ||
53 | |||
54 | /* Define client version */ | ||
55 | #define _USERAGENT "v.0.3.0" | ||
56 | |||
57 | |||
58 | typedef struct av_friend_s { | ||
59 | int _id; | ||
60 | int _active; /* 0=false; 1=true; */ | ||
61 | } av_friend_t; | ||
62 | |||
63 | typedef struct av_session_s { | ||
64 | MSISession* _msi; | ||
65 | |||
66 | RTPSession* _rtp_audio; | ||
67 | RTPSession* _rtp_video; | ||
68 | |||
69 | pthread_mutex_t _mutex; | ||
70 | |||
71 | Tox* _messenger; | ||
72 | av_friend_t* _friends; | ||
73 | int _friend_cout; | ||
74 | uint8_t _my_public_id[200]; | ||
75 | } av_session_t; | ||
76 | |||
77 | |||
78 | void av_allocate_friend(av_session_t* _phone, int _id, int _active) | ||
79 | { | ||
80 | static int _new_id = 0; | ||
81 | |||
82 | if ( !_phone->_friends ) { | ||
83 | _phone->_friends = calloc(sizeof(av_friend_t), 1); | ||
84 | _phone->_friend_cout = 1; | ||
85 | } else{ | ||
86 | _phone->_friend_cout ++; | ||
87 | _phone->_friends = realloc(_phone->_friends, sizeof(av_friend_t) * _phone->_friend_cout); | ||
88 | } | ||
89 | |||
90 | if ( _id = -1 ) { | ||
91 | _phone->_friends->_id = _new_id; | ||
92 | _new_id ++; | ||
93 | } else _phone->_friends->_id = _id; | ||
94 | |||
95 | _phone->_friends->_active = _active; | ||
96 | } | ||
97 | av_friend_t* av_get_friend(av_session_t* _phone, int _id) | ||
98 | { | ||
99 | av_friend_t* _friends = _phone->_friends; | ||
100 | |||
101 | if ( !_friends ) return NULL; | ||
102 | |||
103 | int _it = 0; | ||
104 | for (; _it < _phone->_friend_cout; _it ++) | ||
105 | if ( _friends[_it]._id == _id ) | ||
106 | return _friends + _it; | ||
107 | |||
108 | return NULL; | ||
109 | } | ||
110 | |||
111 | |||
112 | /***************** MISC *****************/ | ||
113 | |||
114 | void INFO (const char* _format, ...) | ||
115 | { | ||
116 | printf("\r[!] "); | ||
117 | va_list _arg; | ||
118 | va_start (_arg, _format); | ||
119 | vfprintf (stdout, _format, _arg); | ||
120 | va_end (_arg); | ||
121 | printf("\n\r >> "); | ||
122 | fflush(stdout); | ||
123 | } | ||
124 | |||
125 | unsigned char *hex_string_to_bin(char hex_string[]) | ||
126 | { | ||
127 | size_t i, len = strlen(hex_string); | ||
128 | unsigned char *val = calloc(sizeof(char), len); | ||
129 | char *pos = hex_string; | ||
130 | |||
131 | for (i = 0; i < len; ++i, pos += 2) | ||
132 | sscanf(pos, "%2hhx", &val[i]); | ||
133 | |||
134 | return val; | ||
135 | } | ||
136 | |||
137 | int getinput( char* _buff, size_t _limit, int* _len ) | ||
138 | { | ||
139 | if ( fgets(_buff, _limit, stdin) == NULL ) | ||
140 | return -1; | ||
141 | |||
142 | *_len = strlen(_buff) - 1; | ||
143 | |||
144 | /* Get rid of newline */ | ||
145 | _buff[*_len] = '\0'; | ||
146 | |||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | char* trim_spaces ( char* buff ) | ||
151 | { | ||
152 | |||
153 | int _i = 0, _len = strlen(buff); | ||
154 | |||
155 | char* container = calloc(sizeof(char), _len); | ||
156 | int _ci = 0; | ||
157 | |||
158 | for ( ; _i < _len; _i++ ) { | ||
159 | while ( _i < _len && buff[_i] == ' ' ) | ||
160 | _i++; | ||
161 | |||
162 | if ( _i < _len ){ | ||
163 | container[_ci] = buff[_i]; | ||
164 | _ci ++; | ||
165 | } | ||
166 | } | ||
167 | |||
168 | memcpy( buff, container, _ci ); | ||
169 | buff[_ci] = '\0'; | ||
170 | free(container); | ||
171 | return buff; | ||
172 | } | ||
173 | |||
174 | #define FRADDR_TOSTR_CHUNK_LEN 8 | ||
175 | |||
176 | static void fraddr_to_str(uint8_t *id_bin, char *id_str) | ||
177 | { | ||
178 | uint i, delta = 0, pos_extra, sum_extra = 0; | ||
179 | |||
180 | for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; i++) { | ||
181 | sprintf(&id_str[2 * i + delta], "%02hhX", id_bin[i]); | ||
182 | |||
183 | if ((i + 1) == TOX_CLIENT_ID_SIZE) | ||
184 | pos_extra = 2 * (i + 1) + delta; | ||
185 | |||
186 | if (i >= TOX_CLIENT_ID_SIZE) | ||
187 | sum_extra |= id_bin[i]; | ||
188 | |||
189 | if (!((i + 1) % FRADDR_TOSTR_CHUNK_LEN)) { | ||
190 | id_str[2 * (i + 1) + delta] = ' '; | ||
191 | delta++; | ||
192 | } | ||
193 | } | ||
194 | |||
195 | id_str[2 * i + delta] = 0; | ||
196 | |||
197 | if (!sum_extra) | ||
198 | id_str[pos_extra] = 0; | ||
199 | } | ||
200 | |||
201 | void* phone_handle_media_transport_poll ( void* _hmtc_args_p ) | ||
202 | { | ||
203 | RTPMessage* _audio_msg, * _video_msg; | ||
204 | av_session_t* _phone = _hmtc_args_p; | ||
205 | MSISession* _session = _phone->_msi; | ||
206 | |||
207 | RTPSession* _rtp_audio = _phone->_rtp_audio; | ||
208 | RTPSession* _rtp_video = _phone->_rtp_video; | ||
209 | |||
210 | |||
211 | Tox* _messenger = _phone->_messenger; | ||
212 | |||
213 | |||
214 | while ( _session->call ) { | ||
215 | |||
216 | _audio_msg = rtp_recv_msg ( _rtp_audio ); | ||
217 | _video_msg = rtp_recv_msg ( _rtp_video ); | ||
218 | |||
219 | if ( _audio_msg ) { | ||
220 | /* Do whatever with msg | ||
221 | printf("%d - %s\n", _audio_msg->header->sequnum, _audio_msg->data);*/ | ||
222 | rtp_free_msg ( _rtp_audio, _audio_msg ); | ||
223 | } | ||
224 | |||
225 | if ( _video_msg ) { | ||
226 | /* Do whatever with msg | ||
227 | p rintf("%d - %s\n", _video_msg->header->sequnum, _video_msg->data);*/ | ||
228 | rtp_free_msg ( _rtp_video, _video_msg ); | ||
229 | } | ||
230 | |||
231 | /* | ||
232 | * Send test message to the 'remote' | ||
233 | */ | ||
234 | rtp_send_msg ( _rtp_audio, _messenger, (const uint8_t*)"audio\0", 6 ); | ||
235 | |||
236 | if ( _session->call->type_local == type_video ){ /* if local call send video */ | ||
237 | rtp_send_msg ( _rtp_video, _messenger, (const uint8_t*)"video\0", 6 ); | ||
238 | } | ||
239 | |||
240 | _audio_msg = _video_msg = NULL; | ||
241 | |||
242 | |||
243 | /* Send ~1k messages per second | ||
244 | * That _should_ be enough for both Audio and Video | ||
245 | */ | ||
246 | usleep ( 1000 ); | ||
247 | /* -------------------- */ | ||
248 | } | ||
249 | |||
250 | if ( _audio_msg ) rtp_free_msg(_rtp_audio, _audio_msg); | ||
251 | rtp_release_session_recv(_rtp_audio); | ||
252 | rtp_terminate_session(_rtp_audio, _messenger); | ||
253 | |||
254 | if ( _video_msg ) rtp_free_msg(_rtp_video, _video_msg); | ||
255 | rtp_release_session_recv(_rtp_video); | ||
256 | rtp_terminate_session(_rtp_video, _messenger); | ||
257 | |||
258 | INFO("Media thread finished!"); | ||
259 | |||
260 | pthread_exit ( NULL ); | ||
261 | } | ||
262 | |||
263 | int phone_startmedia_loop ( av_session_t* _phone ) | ||
264 | { | ||
265 | if ( !_phone ){ | ||
266 | return -1; | ||
267 | } | ||
268 | |||
269 | _phone->_rtp_audio = rtp_init_session ( | ||
270 | type_audio, | ||
271 | _phone->_messenger, | ||
272 | _phone->_msi->call->peers[0], | ||
273 | _phone->_msi->call->key_peer, | ||
274 | _phone->_msi->call->key_local, | ||
275 | _phone->_msi->call->nonce_peer, | ||
276 | _phone->_msi->call->nonce_local | ||
277 | ); | ||
278 | |||
279 | _phone->_rtp_audio = rtp_init_session ( | ||
280 | type_video, | ||
281 | _phone->_messenger, | ||
282 | _phone->_msi->call->peers[0], | ||
283 | _phone->_msi->call->key_peer, | ||
284 | _phone->_msi->call->key_local, | ||
285 | _phone->_msi->call->nonce_peer, | ||
286 | _phone->_msi->call->nonce_local | ||
287 | ); | ||
288 | |||
289 | |||
290 | if ( 0 > event.rise(phone_handle_media_transport_poll, _phone) ) | ||
291 | { | ||
292 | printf("Error while starting phone_handle_media_transport_poll()\n"); | ||
293 | return -1; | ||
294 | } | ||
295 | else return 0; | ||
296 | } | ||
297 | |||
298 | |||
299 | /* Some example callbacks */ | ||
300 | |||
301 | void* callback_recv_invite ( void* _arg ) | ||
302 | { | ||
303 | const char* _call_type; | ||
304 | |||
305 | MSISession* _msi = _arg; | ||
306 | |||
307 | switch ( _msi->call->type_peer[_msi->call->peer_count - 1] ){ | ||
308 | case type_audio: | ||
309 | _call_type = "audio"; | ||
310 | break; | ||
311 | case type_video: | ||
312 | _call_type = "video"; | ||
313 | break; | ||
314 | } | ||
315 | |||
316 | INFO( "Incoming %s call!", _call_type ); | ||
317 | |||
318 | } | ||
319 | void* callback_recv_ringing ( void* _arg ) | ||
320 | { | ||
321 | INFO ( "Ringing!" ); | ||
322 | } | ||
323 | void* callback_recv_starting ( void* _arg ) | ||
324 | { | ||
325 | MSISession* _session = _arg; | ||
326 | if ( 0 != phone_startmedia_loop(_session->agent_handler) ){ | ||
327 | INFO("Starting call failed!"); | ||
328 | } else { | ||
329 | INFO ("Call started! ( press h to hangup )"); | ||
330 | } | ||
331 | } | ||
332 | void* callback_recv_ending ( void* _arg ) | ||
333 | { | ||
334 | INFO ( "Call ended!" ); | ||
335 | } | ||
336 | |||
337 | void* callback_recv_error ( void* _arg ) | ||
338 | { | ||
339 | MSISession* _session = _arg; | ||
340 | |||
341 | INFO( "Error: %s", _session->last_error_str ); | ||
342 | } | ||
343 | |||
344 | void* callback_call_started ( void* _arg ) | ||
345 | { | ||
346 | MSISession* _session = _arg; | ||
347 | if ( 0 != phone_startmedia_loop(_session->agent_handler) ){ | ||
348 | INFO("Starting call failed!"); | ||
349 | } else { | ||
350 | INFO ("Call started! ( press h to hangup )"); | ||
351 | } | ||
352 | |||
353 | } | ||
354 | void* callback_call_canceled ( void* _arg ) | ||
355 | { | ||
356 | INFO ( "Call canceled!" ); | ||
357 | } | ||
358 | void* callback_call_rejected ( void* _arg ) | ||
359 | { | ||
360 | INFO ( "Call rejected!" ); | ||
361 | } | ||
362 | void* callback_call_ended ( void* _arg ) | ||
363 | { | ||
364 | INFO ( "Call ended!" ); | ||
365 | } | ||
366 | |||
367 | void* callback_requ_timeout ( void* _arg ) | ||
368 | { | ||
369 | INFO( "No answer! " ); | ||
370 | } | ||
371 | |||
372 | int av_connect_to_dht(av_session_t* _phone, char* _dht_key, const char* _dht_addr, unsigned short _dht_port) | ||
373 | { | ||
374 | unsigned char *_binary_string = hex_string_to_bin(_dht_key); | ||
375 | |||
376 | uint16_t _port = htons(_dht_port); | ||
377 | |||
378 | int _if = tox_bootstrap_from_address(_phone->_messenger, _dht_addr, 1, _port, _binary_string ); | ||
379 | |||
380 | free(_binary_string); | ||
381 | |||
382 | return _if ? 0 : -1; | ||
383 | } | ||
384 | |||
385 | av_session_t* av_init_session() | ||
386 | { | ||
387 | av_session_t* _retu = malloc(sizeof(av_session_t)); | ||
388 | |||
389 | /* Initialize our mutex */ | ||
390 | pthread_mutex_init ( &_retu->_mutex, NULL ); | ||
391 | |||
392 | _retu->_messenger = tox_new(1); | ||
393 | |||
394 | if ( !_retu->_messenger ) { | ||
395 | fprintf ( stderr, "tox_new() failed!\n" ); | ||
396 | return NULL; | ||
397 | } | ||
398 | |||
399 | _retu->_friends = NULL; | ||
400 | |||
401 | _retu->_rtp_audio = NULL; | ||
402 | _retu->_rtp_video = NULL; | ||
403 | |||
404 | uint8_t _byte_address[TOX_FRIEND_ADDRESS_SIZE]; | ||
405 | tox_get_address(_retu->_messenger, _byte_address ); | ||
406 | fraddr_to_str( _byte_address, _retu->_my_public_id ); | ||
407 | |||
408 | |||
409 | /* Initialize msi */ | ||
410 | _retu->_msi = msi_init_session ( _retu->_messenger, _USERAGENT ); | ||
411 | |||
412 | if ( !_retu->_msi ) { | ||
413 | fprintf ( stderr, "msi_init_session() failed\n" ); | ||
414 | return NULL; | ||
415 | } | ||
416 | |||
417 | _retu->_msi->agent_handler = _retu; | ||
418 | |||
419 | /* ------------------ */ | ||
420 | msi_register_callback(callback_call_started, cb_onstart); | ||
421 | msi_register_callback(callback_call_canceled, cb_oncancel); | ||
422 | msi_register_callback(callback_call_rejected, cb_onreject); | ||
423 | msi_register_callback(callback_call_ended, cb_onend); | ||
424 | msi_register_callback(callback_recv_invite, cb_oninvite); | ||
425 | |||
426 | msi_register_callback(callback_recv_ringing, cb_ringing); | ||
427 | msi_register_callback(callback_recv_starting, cb_starting); | ||
428 | msi_register_callback(callback_recv_ending, cb_ending); | ||
429 | |||
430 | msi_register_callback(callback_recv_error, cb_error); | ||
431 | msi_register_callback(callback_requ_timeout, cb_timeout); | ||
432 | /* ------------------ */ | ||
433 | |||
434 | return _retu; | ||
435 | } | ||
436 | |||
437 | int av_terminate_session(av_session_t* _phone) | ||
438 | { | ||
439 | if ( _phone->_msi->call ){ | ||
440 | msi_hangup(_phone->_msi); /* Hangup the phone first */ | ||
441 | } | ||
442 | |||
443 | free(_phone->_friends); | ||
444 | msi_terminate_session(_phone->_msi); | ||
445 | pthread_mutex_destroy ( &_phone->_mutex ); | ||
446 | |||
447 | Tox* _p = _phone->_messenger; | ||
448 | _phone->_messenger = NULL; usleep(100000); /* Wait for tox_pool to end */ | ||
449 | tox_kill(_p); | ||
450 | |||
451 | printf("\r[i] Quit!\n"); | ||
452 | return 0; | ||
453 | } | ||
454 | |||
455 | /****** AV HELPER FUNCTIONS ******/ | ||
456 | |||
457 | /* Auto accept friend request */ | ||
458 | void av_friend_requ(uint8_t *_public_key, uint8_t *_data, uint16_t _length, void *_userdata) | ||
459 | { | ||
460 | av_session_t* _phone = _userdata; | ||
461 | av_allocate_friend (_phone, -1, 0); | ||
462 | |||
463 | INFO("Got friend request with message: %s", _data); | ||
464 | |||
465 | tox_add_friend_norequest(_phone->_messenger, _public_key); | ||
466 | |||
467 | INFO("Auto-accepted! Friend id: %d", _phone->_friends->_id ); | ||
468 | } | ||
469 | |||
470 | void av_friend_active(Tox *_messenger, int _friendnumber, uint8_t *_string, uint16_t _length, void *_userdata) | ||
471 | { | ||
472 | av_session_t* _phone = _userdata; | ||
473 | INFO("Friend no. %d is online", _friendnumber); | ||
474 | |||
475 | av_friend_t* _this_friend = av_get_friend(_phone, _friendnumber); | ||
476 | |||
477 | if ( !_this_friend ) { | ||
478 | INFO("But it's not registered!"); | ||
479 | return; | ||
480 | } | ||
481 | |||
482 | (*_this_friend)._active = 1; | ||
483 | } | ||
484 | |||
485 | int av_add_friend(av_session_t* _phone, char* _friend_hash) | ||
486 | { | ||
487 | trim_spaces(_friend_hash); | ||
488 | |||
489 | unsigned char *_bin_string = hex_string_to_bin(_friend_hash); | ||
490 | int _number = tox_add_friend(_phone->_messenger, _bin_string, (uint8_t *)"Tox phone "_USERAGENT, sizeof("Tox phone "_USERAGENT)); | ||
491 | free(_bin_string); | ||
492 | |||
493 | if ( _number >= 0) { | ||
494 | INFO("Added friend as %d", _number ); | ||
495 | av_allocate_friend(_phone, _number, 0); | ||
496 | } | ||
497 | else | ||
498 | INFO("Unknown error %i", _number ); | ||
499 | |||
500 | return _number; | ||
501 | } | ||
502 | /*********************************/ | ||
503 | |||
504 | void do_phone ( av_session_t* _phone ) | ||
505 | { | ||
506 | INFO("Welcome to tox_phone version: " _USERAGENT "\n" | ||
507 | "Usage: \n" | ||
508 | "f [pubkey] (add friend)\n" | ||
509 | "c [a/v] (type) [friend] (friend id) (calls friend if online)\n" | ||
510 | "h (if call is active hang up)\n" | ||
511 | "a [a/v] (answer incoming call: a - audio / v - audio + video (audio is default))\n" | ||
512 | "r (reject incoming call)\n" | ||
513 | "q (quit)\n" | ||
514 | "================================================================================" | ||
515 | ); | ||
516 | |||
517 | while ( 1 ) | ||
518 | { | ||
519 | char _line [ 1500 ]; | ||
520 | int _len; | ||
521 | |||
522 | if ( -1 == getinput(_line, 1500, &_len) ){ | ||
523 | printf(" >> "); | ||
524 | fflush(stdout); | ||
525 | continue; | ||
526 | } | ||
527 | |||
528 | if ( _len > 1 && _line[1] != ' ' && _line[1] != '\n' ){ | ||
529 | INFO("Invalid input!"); | ||
530 | continue; | ||
531 | } | ||
532 | |||
533 | switch (_line[0]){ | ||
534 | |||
535 | case 'f': | ||
536 | { | ||
537 | char _id [128]; | ||
538 | strncpy(_id, _line + 2, 128); | ||
539 | |||
540 | av_add_friend(_phone, _id); | ||
541 | |||
542 | } break; | ||
543 | case 'c': | ||
544 | { | ||
545 | if ( _phone->_msi->call ){ | ||
546 | INFO("Already in a call"); | ||
547 | break; | ||
548 | } | ||
549 | |||
550 | MSICallType _ctype; | ||
551 | |||
552 | if ( _len < 5 ){ | ||
553 | INFO("Invalid input; usage: c a/v [friend]"); | ||
554 | break; | ||
555 | } | ||
556 | else if ( _line[2] == 'a' || _line[2] != 'v' ){ /* default and audio */ | ||
557 | _ctype = type_audio; | ||
558 | } | ||
559 | else { /* video */ | ||
560 | _ctype = type_video; | ||
561 | } | ||
562 | |||
563 | char* _end; | ||
564 | int _friend = strtol(_line + 4, &_end, 10); | ||
565 | |||
566 | if ( *_end ){ | ||
567 | INFO("Friend num has to be numerical value"); | ||
568 | break; | ||
569 | } | ||
570 | |||
571 | /* Set timeout */ | ||
572 | msi_invite ( _phone->_msi, _ctype, 10 * 1000, _friend ); | ||
573 | INFO("Calling friend: %d!", _friend); | ||
574 | |||
575 | } break; | ||
576 | case 'h': | ||
577 | { | ||
578 | if ( !_phone->_msi->call ){ | ||
579 | INFO("No call!"); | ||
580 | break; | ||
581 | } | ||
582 | |||
583 | msi_hangup(_phone->_msi); | ||
584 | |||
585 | INFO("Hung up..."); | ||
586 | |||
587 | } break; | ||
588 | case 'a': | ||
589 | { | ||
590 | |||
591 | if ( _phone->_msi->call && _phone->_msi->call->state != call_starting ) { | ||
592 | break; | ||
593 | } | ||
594 | |||
595 | if ( _len > 1 && _line[2] == 'v' ) | ||
596 | msi_answer(_phone->_msi, type_video); | ||
597 | else | ||
598 | msi_answer(_phone->_msi, type_audio); | ||
599 | |||
600 | } break; | ||
601 | case 'r': | ||
602 | { | ||
603 | if ( _phone->_msi->call && _phone->_msi->call->state != call_starting ){ | ||
604 | break; | ||
605 | } | ||
606 | |||
607 | msi_reject(_phone->_msi); | ||
608 | |||
609 | INFO("Call Rejected..."); | ||
610 | |||
611 | } break; | ||
612 | case 'q': | ||
613 | { | ||
614 | INFO("Quitting!"); | ||
615 | return; | ||
616 | } | ||
617 | default: | ||
618 | { | ||
619 | INFO("Invalid command!"); | ||
620 | } break; | ||
621 | |||
622 | } | ||
623 | |||
624 | } | ||
625 | } | ||
626 | |||
627 | void* tox_poll (void* _messenger_p) | ||
628 | { | ||
629 | Tox** _messenger = _messenger_p; | ||
630 | while( *_messenger ) { | ||
631 | tox_do(*_messenger); | ||
632 | usleep(10000); | ||
633 | } | ||
634 | |||
635 | pthread_exit(NULL); | ||
636 | } | ||
637 | |||
638 | int av_wait_dht(av_session_t* _phone, int _wait_seconds, const char* _ip, char* _key, unsigned short _port) | ||
639 | { | ||
640 | if ( !_wait_seconds ) | ||
641 | return -1; | ||
642 | |||
643 | int _waited = 0; | ||
644 | |||
645 | while( !tox_isconnected(_phone->_messenger) ) { | ||
646 | |||
647 | if ( -1 == av_connect_to_dht(_phone, _key, _ip, _port) ) | ||
648 | { | ||
649 | INFO("Could not connect to: %s", _ip); | ||
650 | av_terminate_session(_phone); | ||
651 | return -1; | ||
652 | } | ||
653 | |||
654 | if ( _waited >= _wait_seconds ) return 0; | ||
655 | |||
656 | printf("."); | ||
657 | fflush(stdout); | ||
658 | |||
659 | _waited ++; | ||
660 | usleep(1000000); | ||
661 | } | ||
662 | |||
663 | int _r = _wait_seconds - _waited; | ||
664 | return _r ? _r : 1; | ||
665 | } | ||
666 | /* ---------------------- */ | ||
667 | |||
668 | int print_help ( const char* _name ) | ||
669 | { | ||
670 | printf ( "Usage: %s [IP] [PORT] [KEY]\n" | ||
671 | "\t[IP] (DHT ip)\n" | ||
672 | "\t[PORT] (DHT port)\n" | ||
673 | "\t[KEY] (DHT public key)\n" | ||
674 | "P.S. Friends and key are stored in ./tox_phone.conf\n" | ||
675 | ,_name ); | ||
676 | return 1; | ||
677 | } | ||
678 | |||
679 | int main ( int argc, char* argv [] ) | ||
680 | { | ||
681 | if ( argc < 1 || argc < 4 ) | ||
682 | return print_help(argv[0]); | ||
683 | |||
684 | char* _convertable; | ||
685 | |||
686 | int _wait_seconds = 5; | ||
687 | |||
688 | const char* _ip = argv[1]; | ||
689 | char* _key = argv[3]; | ||
690 | unsigned short _port = strtol(argv[2], &_convertable, 10); | ||
691 | |||
692 | if ( *_convertable ){ | ||
693 | printf("Invalid port: cannot convert string to long: %s", _convertable); | ||
694 | return 1; | ||
695 | } | ||
696 | |||
697 | av_session_t* _phone = av_init_session(); | ||
698 | |||
699 | tox_callback_friend_request(_phone->_messenger, av_friend_requ, _phone); | ||
700 | tox_callback_status_message(_phone->_messenger, av_friend_active, _phone); | ||
701 | |||
702 | system("clear"); | ||
703 | |||
704 | INFO("\r================================================================================\n" | ||
705 | "[!] Trying dht@%s:%d" | ||
706 | , _ip, _port); | ||
707 | |||
708 | /* Start tox protocol */ | ||
709 | event.rise( tox_poll, &_phone->_messenger ); | ||
710 | |||
711 | /* Just clean one line */ | ||
712 | printf("\r \r"); | ||
713 | fflush(stdout); | ||
714 | |||
715 | int _r; | ||
716 | for ( _r = 0; _r == 0; _r = av_wait_dht(_phone, _wait_seconds, _ip, _key, _port) ) _wait_seconds --; | ||
717 | |||
718 | |||
719 | if ( -1 == _r ) { | ||
720 | INFO("Error while connecting to dht: %s:%d", _ip, _port); | ||
721 | av_terminate_session(_phone); | ||
722 | return 1; | ||
723 | } | ||
724 | |||
725 | INFO("CONNECTED!\n" | ||
726 | "================================================================================\n" | ||
727 | "%s\n" | ||
728 | "================================================================================" | ||
729 | , _phone->_my_public_id ); | ||
730 | |||
731 | |||
732 | do_phone (_phone); | ||
733 | |||
734 | av_terminate_session(_phone); | ||
735 | |||
736 | return 0; | ||
737 | } | ||