summaryrefslogtreecommitdiff
path: root/toxrtp/toxrtp.c
diff options
context:
space:
mode:
authormannol <eniz_vukovic@hotmail.com>2014-01-25 01:32:33 +0100
committermannol <eniz_vukovic@hotmail.com>2014-01-25 01:32:33 +0100
commit65d320e31daa4709bb48b7f2a52c269dde0927e9 (patch)
tree45081a96be413d850a837d6afcee19fcfbfe7aca /toxrtp/toxrtp.c
parent51d8c41390be853a13693476802a834daf8d156a (diff)
Done with encryption and core adaptations.
Diffstat (limited to 'toxrtp/toxrtp.c')
-rw-r--r--toxrtp/toxrtp.c693
1 files changed, 0 insertions, 693 deletions
diff --git a/toxrtp/toxrtp.c b/toxrtp/toxrtp.c
deleted file mode 100644
index 6844b0b1..00000000
--- a/toxrtp/toxrtp.c
+++ /dev/null
@@ -1,693 +0,0 @@
1/* rtp_impl.c
2 *
3 * Rtp implementation includes rtp_session_s struct which is a session identifier.
4 * It contains session information and it's a must for every session.
5 * It's best if you don't touch any variable directly but use callbacks to do so. !Red!
6 *
7 *
8 * Copyright (C) 2013 Tox project All Rights Reserved.
9 *
10 * This file is part of Tox.
11 *
12 * Tox is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation, either version 3 of the License, or
15 * (at your option) any later version.
16 *
17 * Tox is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
24 *
25 */
26
27#ifdef HAVE_CONFIG_H
28#include "config.h"
29#endif /* HAVE_CONFIG_H */
30
31#include "toxrtp.h"
32#include "toxrtp_message.h"
33#include "toxrtp_helper.h"
34#include <assert.h>
35#include <pthread.h>
36#include "../toxcore/util.h"
37#include "../toxcore/network.h"
38
39/* Some defines */
40#define PAYLOAD_ID_VALUE_OPUS 1
41#define PAYLOAD_ID_VALUE_VP8 2
42
43#define size_32 4
44/* End of defines */
45
46#ifdef _USE_ERRORS
47#include "toxrtp_error_id.h"
48#endif /* _USE_ERRORS */
49
50static const uint32_t _payload_table[] = /* PAYLOAD TABLE */
51{
52 8000, 8000, 8000, 8000, 8000, 8000, 16000, 8000, 8000, 8000, /* 0-9 */
53 44100, 44100, 0, 0, 90000, 8000, 11025, 22050, 0, 0, /* 10-19 */
54 0, 0, 0, 0, 0, 90000, 90000, 0, 90000, 0, /* 20-29 */
55 0, 90000, 90000, 90000, 90000, 0, 0, 0, 0, 0, /* 30-39 */
56 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40-49 */
57 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 50-59 */
58 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60-69 */
59 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 70-79 */
60 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80-89 */
61 0, 0, 0, 0, 0, 0, PAYLOAD_ID_VALUE_OPUS, 0, 0, 0, /* 90-99 */
62 0, 0, 0, 0, 0, 0, PAYLOAD_ID_VALUE_VP8, 0, 0, 0, /* 100-109 */
63 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 110-119 */
64 0, 0, 0, 0, 0, 0, 0, 0 /* 120-127 */
65};
66
67/* Current compatibility solution */
68int m_sendpacket(Networking_Core* _core_handler, void *ip_port, uint8_t *data, uint32_t length)
69{
70 return sendpacket(_core_handler, *((IP_Port*) ip_port), data, length);
71}
72
73rtp_session_t* rtp_init_session ( int max_users, int _multi_session )
74{
75#ifdef _USE_ERRORS
76 REGISTER_RTP_ERRORS
77#endif /* _USE_ERRORS */
78
79 rtp_session_t* _retu = calloc(sizeof(rtp_session_t), 1);
80 assert(_retu);
81
82 _retu->_dest_list = _retu->_last_user = NULL;
83
84 _retu->_max_users = max_users;
85 _retu->_packets_recv = 0;
86 _retu->_packets_sent = 0;
87 _retu->_bytes_sent = 0;
88 _retu->_bytes_recv = 0;
89 _retu->_last_error = NULL;
90 _retu->_packet_loss = 0;
91
92 /*
93 * SET HEADER FIELDS
94 */
95
96 _retu->_version = RTP_VERSION; /* It's always 2 */
97 _retu->_padding = 0; /* If some additional data is needed about
98 * the packet */
99 _retu->_extension = 0; /* If extension to header is needed */
100 _retu->_cc = 1; /* It basically represents amount of contributors */
101 _retu->_csrc = NULL; /* Container */
102 _retu->_ssrc = t_random ( -1 );
103 _retu->_marker = 0;
104 _retu->_payload_type = 0; /* You should specify payload type */
105
106 /* Sequence starts at random number and goes to _MAX_SEQU_NUM */
107 _retu->_sequence_number = t_random ( _MAX_SEQU_NUM );
108 _retu->_last_sequence_number = _retu->_sequence_number; /* Do not touch this variable */
109
110 _retu->_initial_time = t_time(); /* In seconds */
111 assert(_retu->_initial_time);
112 _retu->_time_elapsed = 0; /* In seconds */
113
114 _retu->_ext_header = NULL; /* When needed allocate */
115 _retu->_exthdr_framerate = -1;
116 _retu->_exthdr_resolution = -1;
117
118 _retu->_csrc = calloc(sizeof(uint32_t), 1);
119 assert(_retu->_csrc);
120
121 _retu->_csrc[0] = _retu->_ssrc; /* Set my ssrc to the list receive */
122
123 _retu->_prefix_length = 0;
124 _retu->_prefix = NULL;
125
126 _retu->_multi_session = _multi_session;
127
128 /* Initial */
129 _retu->_current_framerate = 0;
130
131
132 _retu->_oldest_msg = _retu->_last_msg = NULL;
133
134 pthread_mutex_init(&_retu->_mutex, NULL);
135 /*
136 *
137 */
138 return _retu;
139}
140
141int rtp_terminate_session ( rtp_session_t* _session )
142{
143 if ( !_session )
144 return FAILURE;
145
146 if ( _session->_dest_list ){
147 rtp_dest_list_t* _fordel = NULL;
148 rtp_dest_list_t* _tmp = _session->_dest_list;
149
150 while( _tmp ){
151 _fordel = _tmp;
152 _tmp = _tmp->next;
153 free(_fordel);
154 }
155 }
156
157 if ( _session->_ext_header )
158 free ( _session->_ext_header );
159
160 if ( _session->_csrc )
161 free ( _session->_csrc );
162
163 if ( _session->_prefix )
164 free ( _session->_prefix );
165
166 pthread_mutex_destroy(&_session->_mutex);
167
168 /* And finally free session */
169 free ( _session );
170
171 return SUCCESS;
172}
173
174uint16_t rtp_get_resolution_marking_height ( rtp_ext_header_t* _header, uint32_t _position )
175{
176 if ( _header->_ext_type & RTP_EXT_TYPE_RESOLUTION )
177 return _header->_hd_ext[_position];
178 else
179 return 0;
180}
181
182uint16_t rtp_get_resolution_marking_width ( rtp_ext_header_t* _header, uint32_t _position )
183{
184 if ( _header->_ext_type & RTP_EXT_TYPE_RESOLUTION )
185 return ( _header->_hd_ext[_position] >> 16 );
186 else
187 return 0;
188}
189
190void rtp_free_msg ( rtp_session_t* _session, rtp_msg_t* _message )
191{
192 free ( _message->_data );
193
194 if ( !_session ){
195 free ( _message->_header->_csrc );
196 if ( _message->_ext_header ){
197 free ( _message->_ext_header->_hd_ext );
198 free ( _message->_ext_header );
199 }
200 } else {
201 if ( _session->_csrc != _message->_header->_csrc )
202 free ( _message->_header->_csrc );
203 if ( _message->_ext_header && _session->_ext_header != _message->_ext_header ) {
204 free ( _message->_ext_header->_hd_ext );
205 free ( _message->_ext_header );
206 }
207 }
208
209 free ( _message->_header );
210 free ( _message );
211}
212
213rtp_header_t* rtp_build_header ( rtp_session_t* _session )
214{
215 rtp_header_t* _retu;
216 _retu = calloc ( sizeof * _retu, 1 );
217 assert(_retu);
218
219 rtp_header_add_flag_version ( _retu, _session->_version );
220 rtp_header_add_flag_padding ( _retu, _session->_padding );
221 rtp_header_add_flag_extension ( _retu, _session->_extension );
222 rtp_header_add_flag_CSRC_count ( _retu, _session->_cc );
223 rtp_header_add_setting_marker ( _retu, _session->_marker );
224 rtp_header_add_setting_payload ( _retu, _session->_payload_type );
225
226 _retu->_sequence_number = _session->_sequence_number;
227 _session->_time_elapsed = t_time() - _session->_initial_time;
228 _retu->_timestamp = t_time();
229 _retu->_ssrc = _session->_ssrc;
230
231 if ( _session->_cc > 0 ) {
232 _retu->_csrc = calloc(sizeof(uint32_t), _session->_cc);
233 assert(_retu->_csrc);
234
235 int i;
236
237 for ( i = 0; i < _session->_cc; i++ ) {
238 _retu->_csrc[i] = _session->_csrc[i];
239 }
240 } else {
241 _retu->_csrc = NULL;
242 }
243
244 _retu->_length = _MIN_HEADER_LENGTH + ( _session->_cc * size_32 );
245
246 return _retu;
247}
248
249void rtp_set_payload_type ( rtp_session_t* _session, uint8_t _payload_value )
250{
251 _session->_payload_type = _payload_value;
252}
253uint32_t rtp_get_payload_type ( rtp_session_t* _session )
254{
255 return _payload_table[_session->_payload_type];
256}
257
258int rtp_add_receiver ( rtp_session_t* _session, tox_IP_Port* _dest )
259{
260 if ( !_session )
261 return FAILURE;
262
263 rtp_dest_list_t* _new_user = calloc(sizeof(rtp_dest_list_t), 1);
264 assert(_new_user);
265
266 _new_user->next = NULL;
267 _new_user->_dest = *_dest;
268
269 if ( _session->_last_user == NULL ) { /* New member */
270 _session->_dest_list = _session->_last_user = _new_user;
271
272 } else { /* Append */
273 _session->_last_user->next = _new_user;
274 _session->_last_user = _new_user;
275 }
276
277 return SUCCESS;
278}
279
280int rtp_send_msg ( rtp_session_t* _session, rtp_msg_t* _msg, void* _core_handler )
281{
282 if ( !_msg || _msg->_data == NULL || _msg->_length <= 0 ) {
283 t_perror ( RTP_ERROR_EMPTY_MESSAGE );
284 return FAILURE;
285 }
286
287 int _last;
288 unsigned long long _total = 0;
289
290 size_t _length = _msg->_length;
291 uint8_t _send_data [ MAX_UDP_PACKET_SIZE ];
292
293 uint16_t _prefix_length = _session->_prefix_length;
294
295 _send_data[0] = 70;
296
297 if ( _session->_prefix && _length + _prefix_length < MAX_UDP_PACKET_SIZE ) {
298 /*t_memcpy(_send_data, _session->_prefix, _prefix_length);*/
299 t_memcpy ( _send_data + 1, _msg->_data, _length );
300 } else {
301 t_memcpy ( _send_data + 1, _msg->_data, _length );
302 }
303
304 /* Set sequ number */
305 if ( _session->_sequence_number >= _MAX_SEQU_NUM ) {
306 _session->_sequence_number = 0;
307 } else {
308 _session->_sequence_number++;
309 }
310
311 /* Start sending loop */
312 rtp_dest_list_t* _it;
313 for ( _it = _session->_dest_list; _it != NULL; _it = _it->next ) {
314
315 _last = m_sendpacket ( _core_handler, &_it->_dest, _send_data, _length + 1);
316
317 if ( _last < 0 ) {
318 t_perror ( RTP_ERROR_STD_SEND_FAILURE );
319 printf("Stderror: %s", strerror(errno));
320 } else {
321 _session->_packets_sent ++;
322 _total += _last;
323 }
324
325 }
326
327 rtp_free_msg ( _session, _msg );
328 _session->_bytes_sent += _total;
329 return SUCCESS;
330}
331
332rtp_msg_t* rtp_recv_msg ( rtp_session_t* _session )
333{
334 if ( !_session )
335 return NULL;
336
337 rtp_msg_t* _retu = _session->_oldest_msg;
338
339 pthread_mutex_lock(&_session->_mutex);
340
341 if ( _retu )
342 _session->_oldest_msg = _retu->_next;
343
344 if ( !_session->_oldest_msg )
345 _session->_last_msg = NULL;
346
347 pthread_mutex_unlock(&_session->_mutex);
348
349 return _retu;
350}
351
352void rtp_store_msg ( rtp_session_t* _session, rtp_msg_t* _msg )
353{
354 if ( rtp_check_late_message(_session, _msg) < 0 ) {
355 rtp_register_msg(_session, _msg);
356 }
357
358 pthread_mutex_lock(&_session->_mutex);
359
360 if ( _session->_last_msg ) {
361 _session->_last_msg->_next = _msg;
362 _session->_last_msg = _msg;
363 } else {
364 _session->_last_msg = _session->_oldest_msg = _msg;
365 }
366
367 pthread_mutex_unlock(&_session->_mutex);
368 return;
369}
370
371int rtp_release_session_recv ( rtp_session_t* _session )
372{
373 if ( !_session ){
374 return FAILURE;
375 }
376
377 rtp_msg_t* _tmp,* _it;
378
379 pthread_mutex_lock(&_session->_mutex);
380
381 for ( _it = _session->_oldest_msg; _it; _it = _tmp ){
382 _tmp = _it->_next;
383 rtp_free_msg(_session, _it);
384 }
385
386 _session->_last_msg = _session->_oldest_msg = NULL;
387
388 pthread_mutex_unlock(&_session->_mutex);
389
390 return SUCCESS;
391}
392
393rtp_msg_t* rtp_msg_new ( rtp_session_t* _session, const uint8_t* _data, uint32_t _length )
394{
395 if ( !_session )
396 return NULL;
397
398 uint8_t* _from_pos;
399 rtp_msg_t* _retu = calloc(sizeof(rtp_msg_t), 1);
400 assert(_retu);
401
402 /* Sets header values and copies the extension header in _retu */
403 _retu->_header = rtp_build_header ( _session ); /* It allocates memory and all */
404 _retu->_ext_header = _session->_ext_header;
405
406 uint32_t _total_lenght = _length + _retu->_header->_length;
407
408 if ( _retu->_ext_header ) {
409
410 _total_lenght += ( _MIN_EXT_HEADER_LENGTH + _retu->_ext_header->_ext_len * size_32 );
411 /* Allocate Memory for _retu->_data */
412 _retu->_data = calloc ( sizeof _retu->_data, _total_lenght );
413 assert(_retu->_data);
414
415 _from_pos = rtp_add_header ( _retu->_header, _retu->_data );
416 _from_pos = rtp_add_extention_header ( _retu->_ext_header, _from_pos + 1 );
417 } else {
418 /* Allocate Memory for _retu->_data */
419 _retu->_data = calloc ( sizeof _retu->_data, _total_lenght );
420 assert(_retu->_data);
421
422 _from_pos = rtp_add_header ( _retu->_header, _retu->_data );
423 }
424
425 /*
426 * Parses the extension header into the message
427 * Of course if any
428 */
429
430 /* Appends _data on to _retu->_data */
431 t_memcpy ( _from_pos + 1, _data, _length );
432
433 _retu->_length = _total_lenght;
434
435 _retu->_next = NULL;
436
437 return _retu;
438}
439
440rtp_msg_t* rtp_msg_parse ( rtp_session_t* _session, const uint8_t* _data, uint32_t _length )
441{
442 rtp_msg_t* _retu = calloc(sizeof(rtp_msg_t), 1);
443 assert(_retu);
444
445 _retu->_header = rtp_extract_header ( _data, _length ); /* It allocates memory and all */
446 if ( !_retu->_header ){
447 free(_retu);
448 return NULL;
449 }
450
451 _retu->_length = _length - _retu->_header->_length;
452
453 uint16_t _from_pos = _retu->_header->_length;
454
455
456 if ( rtp_header_get_flag_extension ( _retu->_header ) ) {
457 _retu->_ext_header = rtp_extract_ext_header ( _data + _from_pos, _length );
458 if ( _retu->_ext_header ){
459 _retu->_length -= ( _MIN_EXT_HEADER_LENGTH + _retu->_ext_header->_ext_len * size_32 );
460 _from_pos += ( _MIN_EXT_HEADER_LENGTH + _retu->_ext_header->_ext_len * size_32 );
461 } else {
462 free (_retu->_ext_header);
463 free (_retu->_header);
464 free (_retu);
465 return NULL;
466 }
467 } else {
468 _retu->_ext_header = NULL;
469 }
470
471 /* Get the payload */
472 _retu->_data = calloc ( sizeof ( uint8_t ), _retu->_length );
473 assert(_retu->_data);
474
475 t_memcpy ( _retu->_data, _data + _from_pos, _length - _from_pos );
476
477 _retu->_next = NULL;
478
479
480 if ( _session && !_session->_multi_session && rtp_check_late_message(_session, _retu) < 0 ){
481 rtp_register_msg(_session, _retu);
482 }
483
484 return _retu;
485}
486
487int rtp_check_late_message (rtp_session_t* _session, rtp_msg_t* _msg)
488{
489 /*
490 * Check Sequence number. If this new msg has lesser number then the _session->_last_sequence_number
491 * it shows that the message came in late
492 */
493 if ( _msg->_header->_sequence_number < _session->_last_sequence_number &&
494 _msg->_header->_timestamp < _session->_current_timestamp
495 ) {
496 return SUCCESS; /* Drop the packet. You can check if the packet dropped by checking _packet_loss increment. */
497 }
498 return FAILURE;
499}
500
501void rtp_register_msg ( rtp_session_t* _session, rtp_msg_t* _msg )
502{
503 _session->_last_sequence_number = _msg->_header->_sequence_number;
504 _session->_current_timestamp = _msg->_header->_timestamp;
505}
506
507
508int rtp_add_resolution_marking ( rtp_session_t* _session, uint16_t _width, uint16_t _height )
509{
510 if ( !_session )
511 return FAILURE;
512
513 rtp_ext_header_t* _ext_header = _session->_ext_header;
514 _session->_exthdr_resolution = 0;
515
516 if ( ! ( _ext_header ) ) {
517 _session->_ext_header = calloc (sizeof(rtp_ext_header_t), 1);
518 assert(_session->_ext_header);
519
520 _session->_extension = 1;
521 _session->_ext_header->_ext_len = 1;
522 _ext_header = _session->_ext_header;
523 _session->_ext_header->_hd_ext = calloc(sizeof(uint32_t), 1);
524 assert(_session->_ext_header->_hd_ext);
525
526 } else { /* If there is need for more headers this will be needed to change */
527 if ( !(_ext_header->_ext_type & RTP_EXT_TYPE_RESOLUTION) ){
528 uint32_t _exthdr_framerate = _ext_header->_hd_ext[_session->_exthdr_framerate];
529 /* it's position is at 2nd place by default */
530 _session->_exthdr_framerate ++;
531
532 /* Update length */
533 _ext_header->_ext_len++;
534
535 /* Allocate the value */
536 _ext_header->_hd_ext = realloc(_ext_header->_hd_ext, sizeof(rtp_ext_header_t) * _ext_header->_ext_len);
537 assert(_ext_header->_hd_ext);
538
539 /* Reset other values */
540 _ext_header->_hd_ext[_session->_exthdr_framerate] = _exthdr_framerate;
541 }
542 }
543
544 /* Add flag */
545 _ext_header->_ext_type |= RTP_EXT_TYPE_RESOLUTION;
546
547 _ext_header->_hd_ext[_session->_exthdr_resolution] = _width << 16 | ( uint32_t ) _height;
548
549 return SUCCESS;
550}
551
552int rtp_remove_resolution_marking ( rtp_session_t* _session )
553{
554 if ( _session->_extension == 0 || ! ( _session->_ext_header ) ) {
555 t_perror ( RTP_ERROR_INVALID_EXTERNAL_HEADER );
556 return FAILURE;
557 }
558
559 if ( !( _session->_ext_header->_ext_type & RTP_EXT_TYPE_RESOLUTION ) ) {
560 t_perror ( RTP_ERROR_INVALID_EXTERNAL_HEADER );
561 return FAILURE;
562 }
563
564 _session->_ext_header->_ext_type &= ~RTP_EXT_TYPE_RESOLUTION; /* Remove the flag */
565 _session->_exthdr_resolution = -1; /* Remove identifier */
566
567 /* Check if extension is empty */
568 if ( _session->_ext_header->_ext_type == 0 ){
569
570 free ( _session->_ext_header->_hd_ext );
571 free ( _session->_ext_header );
572
573 _session->_ext_header = NULL; /* It's very important */
574 _session->_extension = 0;
575
576 } else {
577 _session->_ext_header->_ext_len --;
578
579 /* this will also be needed to change if there are more than 2 headers */
580 if ( _session->_ext_header->_ext_type & RTP_EXT_TYPE_FRAMERATE ){
581 memcpy(_session->_ext_header->_hd_ext + 1, _session->_ext_header->_hd_ext, _session->_ext_header->_ext_len);
582 _session->_exthdr_framerate = 0;
583 _session->_ext_header->_hd_ext = realloc( _session->_ext_header->_hd_ext, sizeof( rtp_ext_header_t ) * _session->_ext_header->_ext_len );
584 assert(_session->_ext_header->_hd_ext);
585 }
586 }
587
588 return SUCCESS;
589}
590
591int rtp_add_framerate_marking ( rtp_session_t* _session, uint32_t _value )
592{
593 if ( !_session )
594 return FAILURE;
595
596 rtp_ext_header_t* _ext_header = _session->_ext_header;
597 _session->_exthdr_framerate = 0;
598
599 if ( ! ( _ext_header ) ) {
600 _session->_ext_header = calloc (sizeof(rtp_ext_header_t), 1);
601 assert(_session->_ext_header);
602
603 _session->_extension = 1;
604 _session->_ext_header->_ext_len = 1;
605 _ext_header = _session->_ext_header;
606 _session->_ext_header->_hd_ext = calloc(sizeof(uint32_t), 1);
607 assert(_session->_ext_header->_hd_ext);
608 } else { /* If there is need for more headers this will be needed to change */
609 if ( !(_ext_header->_ext_type & RTP_EXT_TYPE_FRAMERATE) ){
610 /* it's position is at 2nd place by default */
611 _session->_exthdr_framerate ++;
612
613 /* Update length */
614 _ext_header->_ext_len++;
615
616 /* Allocate the value */
617 _ext_header->_hd_ext = realloc(_ext_header->_hd_ext, sizeof(rtp_ext_header_t) * _ext_header->_ext_len);
618 assert(_ext_header->_hd_ext);
619
620 }
621 }
622
623 /* Add flag */
624 _ext_header->_ext_type |= RTP_EXT_TYPE_FRAMERATE;
625
626 _ext_header->_hd_ext[_session->_exthdr_framerate] = _value;
627
628 return SUCCESS;
629}
630
631
632int rtp_remove_framerate_marking ( rtp_session_t* _session )
633{
634 if ( _session->_extension == 0 || ! ( _session->_ext_header ) ) {
635 t_perror ( RTP_ERROR_INVALID_EXTERNAL_HEADER );
636 return FAILURE;
637 }
638
639 if ( !( _session->_ext_header->_ext_type & RTP_EXT_TYPE_FRAMERATE ) ) {
640 t_perror ( RTP_ERROR_INVALID_EXTERNAL_HEADER );
641 return FAILURE;
642 }
643
644 _session->_ext_header->_ext_type &= ~RTP_EXT_TYPE_FRAMERATE; /* Remove the flag */
645 _session->_exthdr_framerate = -1; /* Remove identifier */
646 _session->_ext_header->_ext_len --;
647
648 /* Check if extension is empty */
649 if ( _session->_ext_header->_ext_type == 0 ){
650
651 free ( _session->_ext_header->_hd_ext );
652 free ( _session->_ext_header );
653
654 _session->_ext_header = NULL; /* It's very important */
655 _session->_extension = 0;
656
657 } else if ( !_session->_ext_header->_ext_len ) {
658
659 /* this will also be needed to change if there are more than 2 headers */
660 _session->_ext_header->_hd_ext = realloc( _session->_ext_header->_hd_ext, sizeof( rtp_ext_header_t ) * _session->_ext_header->_ext_len );
661 assert(_session->_ext_header->_hd_ext);
662
663 }
664
665 return SUCCESS;
666}
667
668uint32_t rtp_get_framerate_marking ( rtp_ext_header_t* _header )
669{
670 if ( _header->_ext_len == 1 ){
671 return _header->_hd_ext[0];
672 } else {
673 return _header->_hd_ext[1];
674 }
675}
676
677int rtp_set_prefix ( rtp_session_t* _session, uint8_t* _prefix, uint16_t _prefix_length )
678{
679 if ( !_session )
680 return FAILURE;
681
682 if ( _session->_prefix ) {
683 free ( _session->_prefix );
684 }
685
686 _session->_prefix = calloc ( ( sizeof * _session->_prefix ), _prefix_length );
687 assert(_session->_prefix);
688
689 t_memcpy ( _session->_prefix, _prefix, _prefix_length );
690 _session->_prefix_length = _prefix_length;
691
692 return SUCCESS;
693}