diff options
author | irungentoo <irungentoo@gmail.com> | 2014-02-16 19:13:34 -0500 |
---|---|---|
committer | irungentoo <irungentoo@gmail.com> | 2014-02-16 19:13:34 -0500 |
commit | 9d1eb27717472f5655242fac7b8123a44f1ff33c (patch) | |
tree | fd205f1ea53749717d9930d93ddb153fc8a16929 /toxmsi/toxmsi.c | |
parent | fd3dc22ef3bd77beb78faf24cd43e9d2b9706f5d (diff) | |
parent | f79b327fd639b2dcca9d4d2c137f93c1dce622fc (diff) |
Merge branch 'av-fix' into av-good
Diffstat (limited to 'toxmsi/toxmsi.c')
-rw-r--r-- | toxmsi/toxmsi.c | 835 |
1 files changed, 0 insertions, 835 deletions
diff --git a/toxmsi/toxmsi.c b/toxmsi/toxmsi.c deleted file mode 100644 index 38af28fb..00000000 --- a/toxmsi/toxmsi.c +++ /dev/null | |||
@@ -1,835 +0,0 @@ | |||
1 | |||
2 | #ifdef HAVE_CONFIG_H | ||
3 | #include "config.h" | ||
4 | #endif /* HAVE_CONFIG_H */ | ||
5 | |||
6 | #define _BSD_SOURCE | ||
7 | |||
8 | #include "toxmsi.h" | ||
9 | #include "toxmsi_event.h" | ||
10 | #include "toxmsi_message.h" | ||
11 | #include "../toxrtp/toxrtp_helper.h" | ||
12 | #include "../toxcore/network.h" | ||
13 | |||
14 | #include <assert.h> | ||
15 | #include <unistd.h> | ||
16 | #include <string.h> | ||
17 | |||
18 | #define same(x, y) strcmp((const char*) x, (const char*) y) == 0 | ||
19 | |||
20 | typedef enum { | ||
21 | error_deadcall = 1, /* has call id but it's from old call */ | ||
22 | error_id_mismatch, /* non-existing call */ | ||
23 | |||
24 | error_no_callid, /* not having call id */ | ||
25 | error_no_call, /* no call in session */ | ||
26 | |||
27 | error_busy | ||
28 | } msi_error_t; /* Error codes */ | ||
29 | |||
30 | static inline const uint8_t *stringify_error(msi_error_t _error_code) | ||
31 | { | ||
32 | static const uint8_t* strings[] = | ||
33 | { | ||
34 | (uint8_t*)"", | ||
35 | (uint8_t*)"Using dead call", | ||
36 | (uint8_t*)"Call id not set to any call", | ||
37 | (uint8_t*)"Call id not available", | ||
38 | (uint8_t*)"No active call in session", | ||
39 | (uint8_t*)"Callee busy" | ||
40 | }; | ||
41 | |||
42 | return strings[_error_code]; | ||
43 | } | ||
44 | |||
45 | static inline const uint8_t *stringify_error_code(msi_error_t _error_code) | ||
46 | { | ||
47 | static const uint8_t* strings[] = | ||
48 | { | ||
49 | (uint8_t*)"", | ||
50 | (uint8_t*)"1", | ||
51 | (uint8_t*)"2", | ||
52 | (uint8_t*)"3", | ||
53 | (uint8_t*)"4", | ||
54 | (uint8_t*)"5" | ||
55 | }; | ||
56 | |||
57 | return strings[_error_code]; | ||
58 | } | ||
59 | |||
60 | /* ******************* */ | ||
61 | /* --------- GLOBAL FUNCTIONS USED BY THIS FILE --------- */ | ||
62 | |||
63 | /* CALLBACKS */ | ||
64 | /*int (*msi_send_message_callback) ( int, uint8_t*, uint32_t ) = NULL;*/ | ||
65 | int ( *msi_send_message_callback ) ( void* _core_handler, tox_IP_Port, uint8_t*, uint32_t ) = NULL; | ||
66 | int ( *msi_recv_message_callback ) ( tox_IP_Port*, uint8_t*, uint32_t* ) = NULL; | ||
67 | |||
68 | MCBTYPE ( *msi_recv_invite_callback ) ( MCBARGS ) = NULL; | ||
69 | MCBTYPE ( *msi_start_call_callback ) ( MCBARGS ) = NULL; | ||
70 | MCBTYPE ( *msi_reject_call_callback ) ( MCBARGS ) = NULL; | ||
71 | MCBTYPE ( *msi_cancel_call_callback ) ( MCBARGS ) = NULL; | ||
72 | MCBTYPE ( *msi_end_call_callback ) ( MCBARGS ) = NULL; | ||
73 | |||
74 | MCBTYPE ( *msi_ringing_callback ) ( MCBARGS ) = NULL; | ||
75 | MCBTYPE ( *msi_starting_callback ) ( MCBARGS ) = NULL; | ||
76 | MCBTYPE ( *msi_ending_callback ) ( MCBARGS ) = NULL; | ||
77 | MCBTYPE ( *msi_error_callback ) ( MCBARGS ) = NULL; | ||
78 | |||
79 | MCBTYPE ( *msi_timeout_callback ) ( MCBARGS ) = NULL; | ||
80 | /* End of CALLBACKS */ | ||
81 | |||
82 | /*------------------------*/ | ||
83 | /*------------------------*/ | ||
84 | /*------------------------*/ | ||
85 | /*------------------------*/ | ||
86 | /*------------------------*/ | ||
87 | /*------------------------*/ | ||
88 | /*------------------------*/ | ||
89 | /*------------------------*/ | ||
90 | /*------------------------*/ | ||
91 | /*------------------------*/ | ||
92 | /*------------------------*/ | ||
93 | /*------------------------*/ | ||
94 | |||
95 | /* REGISTER CALLBACKS */ | ||
96 | /*void msi_register_callback_send(int (*callback) ( int, uint8_t*, uint32_t ) )*/ | ||
97 | void msi_register_callback_send ( int ( *callback ) ( void* _core_handler, tox_IP_Port, uint8_t*, uint32_t ) ) | ||
98 | { | ||
99 | msi_send_message_callback = callback; | ||
100 | } | ||
101 | |||
102 | void msi_register_callback_recv ( int ( *callback ) ( tox_IP_Port*, uint8_t*, uint32_t* ) ) | ||
103 | { | ||
104 | msi_recv_message_callback = callback; | ||
105 | } | ||
106 | |||
107 | /* Function to be called when received invite. | ||
108 | * This callback is all about what you do with it. | ||
109 | * Everything else is done internally. | ||
110 | */ | ||
111 | void msi_register_callback_recv_invite ( MCALLBACK ) | ||
112 | { | ||
113 | msi_recv_invite_callback = callback; | ||
114 | } | ||
115 | |||
116 | /* Function to be called when the call is started | ||
117 | * This callback is all about what you do with it. | ||
118 | * Everything else is done internally. | ||
119 | */ | ||
120 | void msi_register_callback_call_started ( MCALLBACK ) | ||
121 | { | ||
122 | msi_start_call_callback = callback; | ||
123 | } | ||
124 | |||
125 | /* Function to be called when call is rejected | ||
126 | * This callback is all about what you do with it. | ||
127 | * Everything else is done internally. | ||
128 | */ | ||
129 | void msi_register_callback_call_rejected ( MCALLBACK ) | ||
130 | { | ||
131 | msi_reject_call_callback = callback; | ||
132 | } | ||
133 | |||
134 | /* Function to be called when call is canceled | ||
135 | * This callback is all about what you do with it. | ||
136 | * Everything else is done internally. | ||
137 | */ | ||
138 | void msi_register_callback_call_canceled ( MCALLBACK ) | ||
139 | { | ||
140 | msi_cancel_call_callback = callback; | ||
141 | } | ||
142 | |||
143 | void msi_register_callback_call_ended ( MCALLBACK ) | ||
144 | { | ||
145 | msi_end_call_callback = callback; | ||
146 | } | ||
147 | |||
148 | |||
149 | /* Functions to be called when gotten x response */ | ||
150 | |||
151 | void msi_register_callback_recv_ringing ( MCALLBACK ) | ||
152 | { | ||
153 | msi_ringing_callback = callback; | ||
154 | } | ||
155 | void msi_register_callback_recv_starting ( MCALLBACK ) | ||
156 | { | ||
157 | msi_starting_callback = callback; | ||
158 | } | ||
159 | void msi_register_callback_recv_ending ( MCALLBACK ) | ||
160 | { | ||
161 | msi_ending_callback = callback; | ||
162 | } | ||
163 | |||
164 | void msi_register_callback_recv_error ( MCALLBACK ) | ||
165 | { | ||
166 | msi_error_callback = callback; | ||
167 | } | ||
168 | |||
169 | /* Timeout */ | ||
170 | void msi_register_callback_requ_timeout ( MCALLBACK ) | ||
171 | { | ||
172 | msi_timeout_callback = callback; | ||
173 | } | ||
174 | /* END REGISTERING */ | ||
175 | |||
176 | /*------------------------*/ | ||
177 | /*------------------------*/ | ||
178 | /*------------------------*/ | ||
179 | /*------------------------*/ | ||
180 | /*------------------------*/ | ||
181 | /*------------------------*/ | ||
182 | /*------------------------*/ | ||
183 | /*------------------------*/ | ||
184 | /*------------------------*/ | ||
185 | /*------------------------*/ | ||
186 | /*------------------------*/ | ||
187 | /*------------------------*/ | ||
188 | |||
189 | /* Function for receiving and parsing a message that will be used internally */ | ||
190 | |||
191 | msi_msg_t* receive_message ( msi_session_t* _session ) | ||
192 | { | ||
193 | assert(_session); | ||
194 | |||
195 | |||
196 | msi_msg_t* _retu = _session->_oldest_msg; | ||
197 | |||
198 | pthread_mutex_lock ( &_session->_mutex ); | ||
199 | |||
200 | if ( _retu ) | ||
201 | _session->_oldest_msg = _retu->_next; | ||
202 | |||
203 | if ( !_session->_oldest_msg ) | ||
204 | _session->_last_msg = NULL; | ||
205 | |||
206 | pthread_mutex_unlock ( &_session->_mutex ); | ||
207 | |||
208 | return _retu; | ||
209 | } | ||
210 | |||
211 | void msi_store_msg ( msi_session_t* _session, msi_msg_t* _msg ) | ||
212 | { | ||
213 | assert(_session); | ||
214 | assert(_msg); | ||
215 | |||
216 | pthread_mutex_lock ( &_session->_mutex ); | ||
217 | |||
218 | if ( _session->_last_msg ) { | ||
219 | _session->_last_msg->_next = _msg; | ||
220 | _session->_last_msg = _msg; | ||
221 | } else { | ||
222 | _session->_last_msg = _session->_oldest_msg = _msg; | ||
223 | } | ||
224 | |||
225 | pthread_mutex_unlock ( &_session->_mutex ); | ||
226 | } | ||
227 | |||
228 | int msi_send_msg ( msi_session_t* _session, msi_msg_t* _msg ) | ||
229 | { | ||
230 | int _status; | ||
231 | |||
232 | if ( !_session->_call ) /* Which should never happen */ | ||
233 | return FAILURE; | ||
234 | |||
235 | msi_msg_set_call_id ( _msg, _session->_call->_id ); | ||
236 | |||
237 | uint8_t _msg_string_final [MSI_MAXMSG_SIZE]; | ||
238 | t_memset ( _msg_string_final, '\0', MSI_MAXMSG_SIZE ); | ||
239 | |||
240 | _msg_string_final[0] = 69; | ||
241 | |||
242 | uint8_t* _msg_string = msi_msg_to_string ( _msg ); | ||
243 | |||
244 | size_t _lenght = t_memlen ( _msg_string ); | ||
245 | |||
246 | memcpy ( _msg_string_final + 1, _msg_string, _lenght ); | ||
247 | |||
248 | _lenght += 1; | ||
249 | |||
250 | _status = ( *msi_send_message_callback ) ( _session->_core_handler, _session->_friend_id, _msg_string_final, _lenght ); | ||
251 | |||
252 | free ( _msg_string ); | ||
253 | |||
254 | return _status; | ||
255 | } | ||
256 | |||
257 | /* Random stuff */ | ||
258 | void flush_peer_type ( msi_session_t* _session, msi_msg_t* _msg, int _peer_id ) | ||
259 | { | ||
260 | if ( _msg->_call_type ) { | ||
261 | if ( strcmp ( ( const char* ) _msg->_call_type->_header_value, CT_AUDIO_HEADER_VALUE ) == 0 ) { | ||
262 | _session->_call->_type_peer[_peer_id] = type_audio; | ||
263 | |||
264 | } else if ( strcmp ( ( const char* ) _msg->_call_type->_header_value, CT_VIDEO_HEADER_VALUE ) == 0 ) { | ||
265 | _session->_call->_type_peer[_peer_id] = type_video; | ||
266 | } else {} /* Error */ | ||
267 | } else {} /* Error */ | ||
268 | } | ||
269 | |||
270 | int has_call_error ( msi_session_t* _session, msi_msg_t* _msg ) | ||
271 | { | ||
272 | msi_msg_t* _msg_error = msi_msg_new ( TYPE_RESPONSE, stringify_response ( _error ) ); | ||
273 | |||
274 | if ( !_msg->_call_id ) { | ||
275 | msi_msg_set_reason(_msg_error, stringify_error_code(error_no_callid) ); | ||
276 | |||
277 | } else if ( !_session->_call ) { | ||
278 | msi_msg_set_reason(_msg_error, stringify_error_code(error_no_call) ); | ||
279 | |||
280 | } else if ( strcmp((const char*)_session->_call->_id, (const char*)_msg->_call_id->_header_value ) != 0 ) { | ||
281 | msi_msg_set_reason(_msg_error, stringify_error_code(error_id_mismatch) ); | ||
282 | } | ||
283 | |||
284 | if ( _msg_error->_reason ) { | ||
285 | msi_send_msg ( _session, _msg_error ); | ||
286 | msi_free_msg ( _msg_error ); | ||
287 | return SUCCESS; | ||
288 | } | ||
289 | |||
290 | msi_free_msg ( _msg_error ); | ||
291 | return FAILURE; | ||
292 | } | ||
293 | |||
294 | /* --------- END OF GLOBAL FUNCTIONS USED BY THIS FILE --------- */ | ||
295 | |||
296 | /*------------------------*/ | ||
297 | /*------------------------*/ | ||
298 | /*------------------------*/ | ||
299 | /*------------------------*/ | ||
300 | /*------------------------*/ | ||
301 | /*------------------------*/ | ||
302 | /*------------------------*/ | ||
303 | /*------------------------*/ | ||
304 | /*------------------------*/ | ||
305 | /*------------------------*/ | ||
306 | /*------------------------*/ | ||
307 | /*------------------------*/ | ||
308 | |||
309 | msi_session_t* msi_init_session ( void* _core_handler, const uint8_t* _user_agent ) | ||
310 | { | ||
311 | assert(_core_handler); | ||
312 | assert(_user_agent); | ||
313 | |||
314 | msi_session_t* _session = calloc ( sizeof ( msi_session_t ), 1 ); | ||
315 | assert(_session); | ||
316 | |||
317 | _session->_oldest_msg = _session->_last_msg = NULL; | ||
318 | _session->_core_handler = _core_handler; | ||
319 | |||
320 | _session->_user_agent = t_strallcpy ( _user_agent ); | ||
321 | _session->_agent_handler = NULL; | ||
322 | |||
323 | _session->_key = 0; | ||
324 | _session->_call = NULL; | ||
325 | |||
326 | _session->_frequ = 10000; /* default value? */ | ||
327 | _session->_call_timeout = 30000; /* default value? */ | ||
328 | |||
329 | /* Use the same frequency */ | ||
330 | _session->_event_handler = init_event_poll ( _session->_frequ ); | ||
331 | |||
332 | pthread_mutex_init ( &_session->_mutex, NULL ); | ||
333 | |||
334 | return _session; | ||
335 | } | ||
336 | |||
337 | int msi_terminate_session ( msi_session_t* _session ) | ||
338 | { | ||
339 | assert(_session); | ||
340 | |||
341 | int _status = 0; | ||
342 | |||
343 | terminate_event_poll ( _session->_event_handler ); | ||
344 | free ( _session ); | ||
345 | /* TODO: terminate the rest of the session */ | ||
346 | |||
347 | pthread_mutex_destroy ( &_session->_mutex ); | ||
348 | |||
349 | return _status; | ||
350 | } | ||
351 | |||
352 | msi_call_t* msi_init_call ( msi_session_t* _session, int _peers, uint32_t _timeoutms ) | ||
353 | { | ||
354 | assert(_session); | ||
355 | assert(_peers); | ||
356 | |||
357 | msi_call_t* _call = calloc ( sizeof ( msi_call_t ), 1 ); | ||
358 | _call->_type_peer = calloc ( sizeof ( call_type ), _peers ); | ||
359 | |||
360 | assert(_call); | ||
361 | assert(_call->_type_peer); | ||
362 | |||
363 | _call->_participants = _peers; | ||
364 | _call->_key = _session->_key; | ||
365 | _call->_timeoutst = _timeoutms; | ||
366 | _call->_outgoing_timer_id = 0; | ||
367 | |||
368 | return _call; | ||
369 | } | ||
370 | |||
371 | int msi_terminate_call ( msi_session_t* _session ) | ||
372 | { | ||
373 | assert(_session); | ||
374 | |||
375 | if ( _session->_call->_type_peer ) | ||
376 | free ( _session->_call->_type_peer ); | ||
377 | |||
378 | cancel_timer_event(_session->_event_handler, _session->_call->_outgoing_timer_id); | ||
379 | |||
380 | free ( _session->_call ); | ||
381 | |||
382 | _session->_call = NULL; | ||
383 | |||
384 | return SUCCESS; | ||
385 | } | ||
386 | /*------------------------*/ | ||
387 | /*------------------------*/ | ||
388 | /*------------------------*/ | ||
389 | /*------------------------*/ | ||
390 | /*------------------------*/ | ||
391 | /*------------------------*/ | ||
392 | /*------------------------*/ | ||
393 | /*------------------------*/ | ||
394 | /*------------------------*/ | ||
395 | /*------------------------*/ | ||
396 | /*------------------------*/ | ||
397 | /*------------------------*/ | ||
398 | |||
399 | /* STATE HANDLERS */ | ||
400 | |||
401 | /* REQUESTS */ | ||
402 | int msi_handle_recv_invite ( msi_session_t* _session, msi_msg_t* _msg ) | ||
403 | { | ||
404 | assert(_session); | ||
405 | |||
406 | if ( _session->_call ) { | ||
407 | msi_msg_t* _msg_error = msi_msg_new ( TYPE_RESPONSE, stringify_response ( _error ) ); | ||
408 | msi_msg_set_reason(_msg_error, stringify_error_code(error_busy)); | ||
409 | msi_send_msg(_session, _msg_error); | ||
410 | msi_free_msg(_msg_error); | ||
411 | |||
412 | return 0; | ||
413 | } | ||
414 | if ( !_msg->_call_id ) { | ||
415 | msi_msg_t* _msg_error = msi_msg_new ( TYPE_RESPONSE, stringify_response ( _error ) ); | ||
416 | msi_msg_set_reason(_msg_error, stringify_error_code(error_no_callid)); | ||
417 | msi_send_msg(_session, _msg_error); | ||
418 | msi_free_msg(_msg_error); | ||
419 | return 0; | ||
420 | } | ||
421 | |||
422 | _session->_call = msi_init_call ( _session, 1, _session->_call_timeout ); | ||
423 | t_memcpy(_session->_call->_id, _msg->_call_id->_header_value, _CALL_ID_LEN); | ||
424 | _session->_call->_state = call_starting; | ||
425 | |||
426 | flush_peer_type ( _session, _msg, 0 ); | ||
427 | |||
428 | msi_msg_t* _msg_ringing = msi_msg_new ( TYPE_RESPONSE, stringify_response ( _ringing ) ); | ||
429 | msi_send_msg ( _session, _msg_ringing ); | ||
430 | msi_free_msg ( _msg_ringing ); | ||
431 | |||
432 | throw_event ( _session->_event_handler, msi_recv_invite_callback, _session ); | ||
433 | return 1; | ||
434 | } | ||
435 | int msi_handle_recv_start ( msi_session_t* _session, msi_msg_t* _msg ) | ||
436 | { | ||
437 | assert(_session); | ||
438 | |||
439 | if ( has_call_error(_session, _msg) == 0 ) | ||
440 | return 0; | ||
441 | |||
442 | _session->_call->_state = call_active; | ||
443 | |||
444 | flush_peer_type ( _session, _msg, 0 ); | ||
445 | |||
446 | throw_event ( _session->_event_handler, msi_start_call_callback, _session ); | ||
447 | return 1; | ||
448 | } | ||
449 | int msi_handle_recv_reject ( msi_session_t* _session, msi_msg_t* _msg ) | ||
450 | { | ||
451 | assert(_session); | ||
452 | |||
453 | if ( has_call_error(_session, _msg) == 0 ) | ||
454 | return 0; | ||
455 | |||
456 | msi_msg_t* _msg_end = msi_msg_new ( TYPE_REQUEST, stringify_request ( _end ) ); | ||
457 | msi_send_msg ( _session, _msg_end ); | ||
458 | msi_free_msg ( _msg_end ); | ||
459 | |||
460 | throw_event ( _session->_event_handler, msi_reject_call_callback, _session ); | ||
461 | |||
462 | return 1; | ||
463 | } | ||
464 | int msi_handle_recv_cancel ( msi_session_t* _session, msi_msg_t* _msg ) | ||
465 | { | ||
466 | assert(_session); | ||
467 | |||
468 | if ( has_call_error(_session, _msg) == 0 ) | ||
469 | return 0; | ||
470 | |||
471 | msi_msg_t* _msg_ending = msi_msg_new ( TYPE_RESPONSE, stringify_response ( _ending ) ); | ||
472 | msi_send_msg ( _session, _msg_ending ); | ||
473 | msi_free_msg ( _msg_ending ); | ||
474 | |||
475 | msi_terminate_call ( _session ); | ||
476 | |||
477 | throw_event ( _session->_event_handler, msi_cancel_call_callback, _session ); | ||
478 | |||
479 | return 1; | ||
480 | } | ||
481 | int msi_handle_recv_end ( msi_session_t* _session, msi_msg_t* _msg ) | ||
482 | { | ||
483 | assert(_session); | ||
484 | |||
485 | if ( has_call_error(_session, _msg) == 0 ) | ||
486 | return 0; | ||
487 | |||
488 | msi_msg_t* _msg_ending = msi_msg_new ( TYPE_RESPONSE, stringify_response ( _ending ) ); | ||
489 | msi_send_msg ( _session, _msg_ending ); | ||
490 | msi_free_msg ( _msg_ending ); | ||
491 | |||
492 | msi_terminate_call ( _session ); | ||
493 | |||
494 | throw_event ( _session->_event_handler, msi_end_call_callback, _session ); | ||
495 | |||
496 | return 1; | ||
497 | } | ||
498 | /*--------*/ | ||
499 | |||
500 | /* RESPONSES */ | ||
501 | int msi_handle_recv_ringing ( msi_session_t* _session, msi_msg_t* _msg ) | ||
502 | { | ||
503 | assert(_session); | ||
504 | |||
505 | if ( has_call_error(_session, _msg) == 0 ) | ||
506 | return 0; | ||
507 | |||
508 | throw_event ( _session->_event_handler, msi_ringing_callback, _session ); | ||
509 | |||
510 | return 1; | ||
511 | } | ||
512 | int msi_handle_recv_starting ( msi_session_t* _session, msi_msg_t* _msg ) | ||
513 | { | ||
514 | assert(_session); | ||
515 | |||
516 | if ( has_call_error(_session, _msg) == 0 ) | ||
517 | return 0; | ||
518 | |||
519 | _session->_call->_state = call_active; | ||
520 | |||
521 | msi_msg_t* _msg_start = msi_msg_new ( TYPE_REQUEST, stringify_request ( _start ) ); | ||
522 | msi_send_msg ( _session, _msg_start ); | ||
523 | msi_free_msg ( _msg_start ); | ||
524 | |||
525 | flush_peer_type ( _session, _msg, 0 ); | ||
526 | |||
527 | throw_event ( _session->_event_handler, msi_starting_callback, _session ); | ||
528 | cancel_timer_event(_session->_event_handler, _session->_call->_outgoing_timer_id); | ||
529 | _session->_call->_outgoing_timer_id = 0; | ||
530 | |||
531 | return 1; | ||
532 | } | ||
533 | int msi_handle_recv_ending ( msi_session_t* _session, msi_msg_t* _msg ) | ||
534 | { | ||
535 | assert(_session); | ||
536 | |||
537 | if ( has_call_error(_session, _msg) == 0 ) | ||
538 | return 0; | ||
539 | |||
540 | msi_terminate_call ( _session ); | ||
541 | throw_event ( _session->_event_handler, msi_ending_callback, _session ); | ||
542 | |||
543 | return 1; | ||
544 | } | ||
545 | int msi_handle_recv_error ( msi_session_t* _session, msi_msg_t* _msg ) | ||
546 | { | ||
547 | assert(_session); | ||
548 | assert(_session->_call); | ||
549 | |||
550 | /* Handle error accordingly */ | ||
551 | if ( _msg->_reason ) { | ||
552 | _session->_last_error_id = atoi((const char*)_msg->_reason->_header_value); | ||
553 | _session->_last_error_str = stringify_error(_session->_last_error_id); | ||
554 | } | ||
555 | |||
556 | msi_terminate_call(_session); | ||
557 | |||
558 | throw_event ( _session->_event_handler, msi_error_callback, _session ); | ||
559 | |||
560 | return 1; | ||
561 | } | ||
562 | /* ------------------ */ | ||
563 | |||
564 | MCBTYPE msi_handle_timeout (void* _arg) | ||
565 | { | ||
566 | msi_session_t* _session = _arg; | ||
567 | msi_terminate_call(_session); | ||
568 | |||
569 | (*msi_timeout_callback) (_arg); | ||
570 | (*msi_ending_callback) (_arg); | ||
571 | |||
572 | } | ||
573 | |||
574 | /*------------------------*/ | ||
575 | /*------------------------*/ | ||
576 | /*------------------------*/ | ||
577 | /*------------------------*/ | ||
578 | /*------------------------*/ | ||
579 | /*------------------------*/ | ||
580 | /*------------------------*/ | ||
581 | /*------------------------*/ | ||
582 | /*------------------------*/ | ||
583 | /*------------------------*/ | ||
584 | /*------------------------*/ | ||
585 | /*------------------------*/ | ||
586 | |||
587 | int msi_invite ( msi_session_t* _session, call_type _call_type, uint32_t _timeoutms ) | ||
588 | { | ||
589 | assert(_session); | ||
590 | |||
591 | if ( !msi_send_message_callback ) | ||
592 | return 0; | ||
593 | |||
594 | msi_msg_t* _msg_invite = msi_msg_new ( TYPE_REQUEST, stringify_request ( _invite ) ); | ||
595 | |||
596 | _session->_call = msi_init_call ( _session, 1, _timeoutms ); /* Just one for now */ | ||
597 | msi_genterate_call_id(_session->_call->_id, _CALL_ID_LEN); | ||
598 | _session->_call->_type_local = _call_type; | ||
599 | /* Do whatever with message */ | ||
600 | |||
601 | if ( _call_type == type_audio ) { | ||
602 | msi_msg_set_call_type ( _msg_invite, ( const uint8_t* ) CT_AUDIO_HEADER_VALUE ); | ||
603 | } else { | ||
604 | msi_msg_set_call_type ( _msg_invite, ( const uint8_t* ) CT_VIDEO_HEADER_VALUE ); | ||
605 | } | ||
606 | |||
607 | msi_send_msg ( _session, _msg_invite ); | ||
608 | msi_free_msg ( _msg_invite ); | ||
609 | |||
610 | _session->_call->_state = call_inviting; | ||
611 | |||
612 | _session->_call->_outgoing_timer_id = throw_timer_event(_session->_event_handler, msi_handle_timeout, _session, _timeoutms ); | ||
613 | |||
614 | return 1; | ||
615 | } | ||
616 | int msi_hangup ( msi_session_t* _session ) | ||
617 | { | ||
618 | assert(_session); | ||
619 | |||
620 | if ( !_session->_call || ( !msi_send_message_callback && _session->_call->_state != call_active ) ) | ||
621 | return 0; | ||
622 | |||
623 | msi_msg_t* _msg_ending = msi_msg_new ( TYPE_REQUEST, stringify_request ( _end ) ); | ||
624 | msi_send_msg ( _session, _msg_ending ); | ||
625 | msi_free_msg ( _msg_ending ); | ||
626 | |||
627 | return 1; | ||
628 | } | ||
629 | |||
630 | |||
631 | int msi_answer ( msi_session_t* _session, call_type _call_type ) | ||
632 | { | ||
633 | assert(_session); | ||
634 | |||
635 | if ( !msi_send_message_callback || !_session->_call ) | ||
636 | return 0; | ||
637 | |||
638 | msi_msg_t* _msg_starting = msi_msg_new ( TYPE_RESPONSE, stringify_response ( _starting ) ); | ||
639 | _session->_call->_type_local = _call_type; | ||
640 | |||
641 | if ( _call_type == type_audio ) { | ||
642 | msi_msg_set_call_type ( _msg_starting, ( const uint8_t* ) CT_AUDIO_HEADER_VALUE ); | ||
643 | } else { | ||
644 | msi_msg_set_call_type ( _msg_starting, ( const uint8_t* ) CT_VIDEO_HEADER_VALUE ); | ||
645 | } | ||
646 | |||
647 | msi_send_msg ( _session, _msg_starting ); | ||
648 | msi_free_msg ( _msg_starting ); | ||
649 | |||
650 | _session->_call->_state = call_active; | ||
651 | return 1; | ||
652 | } | ||
653 | int msi_cancel ( msi_session_t* _session ) | ||
654 | { | ||
655 | assert(_session); | ||
656 | |||
657 | if ( !_session->_call || !msi_send_message_callback ) | ||
658 | return 0; | ||
659 | |||
660 | msi_msg_t* _msg_cancel = msi_msg_new ( TYPE_REQUEST, stringify_request ( _cancel ) ); | ||
661 | msi_send_msg ( _session, _msg_cancel ); | ||
662 | msi_free_msg ( _msg_cancel ); | ||
663 | |||
664 | |||
665 | |||
666 | return 1; | ||
667 | } | ||
668 | int msi_reject ( msi_session_t* _session ) | ||
669 | { | ||
670 | assert(_session); | ||
671 | |||
672 | if ( !_session->_call || !msi_send_message_callback ) | ||
673 | return 0; | ||
674 | |||
675 | msi_msg_t* _msg_reject = msi_msg_new ( TYPE_REQUEST, stringify_request ( _reject ) ); | ||
676 | msi_send_msg ( _session, _msg_reject ); | ||
677 | msi_free_msg ( _msg_reject ); | ||
678 | |||
679 | return 1; | ||
680 | } | ||
681 | |||
682 | /*------------------------*/ | ||
683 | /*------------------------*/ | ||
684 | /*------------------------*/ | ||
685 | /*------------------------*/ | ||
686 | /*------------------------*/ | ||
687 | /*------------------------*/ | ||
688 | /*------------------------*/ | ||
689 | /*------------------------*/ | ||
690 | /*------------------------*/ | ||
691 | /*------------------------*/ | ||
692 | /*------------------------*/ | ||
693 | /*------------------------*/ | ||
694 | |||
695 | /* OUR MAIN POOL FUNCTION */ | ||
696 | /* | ||
697 | * Forks it self to other thread and then handles the session initiation. | ||
698 | * | ||
699 | * BASIC call flow: | ||
700 | * | ||
701 | * ALICE BOB | ||
702 | * | invite --> | | ||
703 | * | | | ||
704 | * | <-- ringing | | ||
705 | * | | | ||
706 | * | <-- starting | | ||
707 | * | | | ||
708 | * | start --> | | ||
709 | * | | | ||
710 | * | <-- MEDIA TRANS --> | | ||
711 | * | | | ||
712 | * | end --> | | ||
713 | * | | | ||
714 | * | <-- ending | | ||
715 | * | ||
716 | * Alice calls Bob by sending invite packet. | ||
717 | * Bob recvs the packet and sends an ringing packet; | ||
718 | * which notifies Alice that her invite is acknowledged. | ||
719 | * Ringing screen shown on both sides. | ||
720 | * Bob accepts the invite for a call by sending starting packet. | ||
721 | * Alice recvs the starting packet and sends the started packet to | ||
722 | * inform Bob that she recved the starting packet. | ||
723 | * Now the media transmission is established ( i.e. RTP transmission ). | ||
724 | * Alice hangs up and sends end packet. | ||
725 | * Bob recves the end packet and sends ending packet | ||
726 | * as the acknowledgement that the call is ending. | ||
727 | * | ||
728 | * | ||
729 | */ | ||
730 | |||
731 | |||
732 | /* | ||
733 | * Needs a bit more work on the protocol | ||
734 | */ | ||
735 | void* msi_poll_stack ( void* _session_p ) | ||
736 | { | ||
737 | msi_session_t* _session = ( msi_session_t* ) _session_p; | ||
738 | msi_msg_t* _msg = NULL; | ||
739 | |||
740 | uint32_t* _frequ = &_session->_frequ; | ||
741 | while ( _session ) { | ||
742 | |||
743 | /* At this point it's already parsed */ | ||
744 | _msg = receive_message ( _session ); | ||
745 | |||
746 | if ( _msg ) { | ||
747 | |||
748 | if ( _msg->_request ) { /* Handle request */ | ||
749 | |||
750 | const uint8_t* _request_value = _msg->_request->_header_value; | ||
751 | |||
752 | if ( same ( _request_value, stringify_request ( _invite ) ) ) { | ||
753 | msi_handle_recv_invite ( _session, _msg ); | ||
754 | |||
755 | } else if ( same ( _request_value, stringify_request ( _start ) ) ) { | ||
756 | msi_handle_recv_start ( _session, _msg ); | ||
757 | |||
758 | } else if ( same ( _request_value, stringify_request ( _cancel ) ) ) { | ||
759 | msi_handle_recv_cancel ( _session, _msg ); | ||
760 | |||
761 | } else if ( same ( _request_value, stringify_request ( _reject ) ) ) { | ||
762 | msi_handle_recv_reject ( _session, _msg ); | ||
763 | |||
764 | } else if ( same ( _request_value, stringify_request ( _end ) ) ) { | ||
765 | msi_handle_recv_end ( _session, _msg ); | ||
766 | } | ||
767 | |||
768 | } else if ( _msg->_response ) { /* Handle response */ | ||
769 | |||
770 | const uint8_t* _response_value = _msg->_response->_header_value; | ||
771 | |||
772 | if ( same ( _response_value, stringify_response ( _ringing ) ) ) { | ||
773 | msi_handle_recv_ringing ( _session, _msg ); | ||
774 | |||
775 | } else if ( same ( _response_value, stringify_response ( _starting ) ) ) { | ||
776 | msi_handle_recv_starting ( _session, _msg ); | ||
777 | |||
778 | } else if ( same ( _response_value, stringify_response ( _ending ) ) ) { | ||
779 | msi_handle_recv_ending ( _session, _msg ); | ||
780 | |||
781 | } else if ( same ( _response_value, stringify_response ( _error ) ) ) { | ||
782 | msi_handle_recv_error ( _session, _msg ); | ||
783 | } | ||
784 | |||
785 | } | ||
786 | |||
787 | msi_free_msg ( _msg ); | ||
788 | |||
789 | } | ||
790 | usleep ( *_frequ ); | ||
791 | } | ||
792 | |||
793 | return NULL; | ||
794 | } | ||
795 | |||
796 | /*------------------------*/ | ||
797 | /*------------------------*/ | ||
798 | /*------------------------*/ | ||
799 | /*------------------------*/ | ||
800 | /*------------------------*/ | ||
801 | /*------------------------*/ | ||
802 | /*------------------------*/ | ||
803 | /*------------------------*/ | ||
804 | /*------------------------*/ | ||
805 | /*------------------------*/ | ||
806 | /*------------------------*/ | ||
807 | /*------------------------*/ | ||
808 | |||
809 | /* Easy way to start the poll */ | ||
810 | |||
811 | pthread_t msi_start_main_loop ( msi_session_t* _session, uint32_t _frequms ) | ||
812 | { | ||
813 | assert(_session); | ||
814 | |||
815 | int _status; | ||
816 | pthread_t _thread_id; | ||
817 | |||
818 | |||
819 | _session->_frequ = _frequms * 1000; | ||
820 | |||
821 | _status = pthread_create ( &_thread_id, NULL, msi_poll_stack, _session ); | ||
822 | |||
823 | if ( _status < 0 ) { | ||
824 | printf ( "Error while starting main loop: %d, %s\n", errno, strerror ( errno ) ); | ||
825 | return _status; | ||
826 | } | ||
827 | |||
828 | _status = pthread_detach ( _thread_id ); | ||
829 | |||
830 | if ( _status < 0 ) { | ||
831 | printf ( "Error while starting main loop: %d, %s\n", errno, strerror ( errno ) ); | ||
832 | } | ||
833 | |||
834 | return _thread_id; | ||
835 | } | ||