summaryrefslogtreecommitdiff
path: root/toxrtp
diff options
context:
space:
mode:
authormannol <eniz_vukovic@hotmail.com>2013-10-13 16:16:47 +0200
committerBtbN <btbn@btbn.de>2013-10-13 16:16:47 +0200
commitda727875ac954b13ecb16521d255499511bb7424 (patch)
tree551904f3738612e9c15d98f320c323aa325a5cf8 /toxrtp
parent1b971de651278429eea312f3240e1c5b8fbc67a4 (diff)
tox A/V: RTP/MSI implementation
Diffstat (limited to 'toxrtp')
-rw-r--r--toxrtp/Makefile.inc34
-rw-r--r--toxrtp/tests/Makefile.inc1
-rw-r--r--toxrtp/tests/test_bidirect.c109
-rw-r--r--toxrtp/tests/test_headers.c316
-rw-r--r--toxrtp/tests/test_helper.c83
-rw-r--r--toxrtp/tests/test_helper.h61
-rw-r--r--toxrtp/toxrtp.c693
-rw-r--r--toxrtp/toxrtp.h188
-rw-r--r--toxrtp/toxrtp_error.c68
-rw-r--r--toxrtp/toxrtp_error.h25
-rw-r--r--toxrtp/toxrtp_error_id.h32
-rw-r--r--toxrtp/toxrtp_helper.c209
-rw-r--r--toxrtp/toxrtp_helper.h77
-rw-r--r--toxrtp/toxrtp_message.c351
-rw-r--r--toxrtp/toxrtp_message.h111
15 files changed, 2358 insertions, 0 deletions
diff --git a/toxrtp/Makefile.inc b/toxrtp/Makefile.inc
new file mode 100644
index 00000000..801a7fd3
--- /dev/null
+++ b/toxrtp/Makefile.inc
@@ -0,0 +1,34 @@
1if BUILD_AV
2
3lib_LTLIBRARIES += libtoxrtp.la
4
5libtoxrtp_la_include_HEADERS = \
6 ../toxrtp/toxrtp.h
7
8libtoxrtp_la_includedir = $(includedir)/tox
9
10libtoxrtp_la_SOURCES = ../toxrtp/toxrtp_error.h \
11 ../toxrtp/toxrtp_error.c \
12 ../toxrtp/toxrtp_error_id.h \
13 ../toxrtp/toxrtp_helper.h \
14 ../toxrtp/toxrtp_helper.c \
15 ../toxrtp/toxrtp.h \
16 ../toxrtp/toxrtp.c \
17 ../toxrtp/toxrtp_message.h \
18 ../toxrtp/toxrtp_message.c \
19 ../toxcore/network.h \
20 ../toxcore/network.c \
21 ../toxcore/util.h \
22 ../toxcore/util.c
23
24libtoxrtp_la_CFLAGS = -I../toxcore \
25 -I../toxrtp \
26 $(NACL_CFLAGS)
27
28libtoxrtp_la_LDFLAGS = $(TOXRTP_LT_LDFLAGS) \
29 $(NACL_LDFLAGS) \
30 $(EXTRA_LT_LDFLAGS)
31
32libtoxrtp_la_LIBS = $(NACL_LIBS)
33
34endif
diff --git a/toxrtp/tests/Makefile.inc b/toxrtp/tests/Makefile.inc
new file mode 100644
index 00000000..8d1c8b69
--- /dev/null
+++ b/toxrtp/tests/Makefile.inc
@@ -0,0 +1 @@
diff --git a/toxrtp/tests/test_bidirect.c b/toxrtp/tests/test_bidirect.c
new file mode 100644
index 00000000..b5a0899e
--- /dev/null
+++ b/toxrtp/tests/test_bidirect.c
@@ -0,0 +1,109 @@
1#define _BSD_SOURCE
2
3#include "../toxrtp.h"
4#include "../toxrtp_message.h"
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8#include <utime.h>
9#include <assert.h>
10
11#include "test_helper.h"
12#include "../../toxcore/tox.h"
13
14#ifdef _CT_BIDIRECT
15
16int _print_help( const char* name )
17{
18 char* _help = malloc( 300 );
19 memset(_help, '\0', 300);
20
21 strcat(_help, " Usage: ");
22 strcat(_help, name);
23 strcat(_help, "\n -d IP ( destination )\n"
24 " -p PORT ( dest Port )\n"
25 " -l PORT ( listen Port ) \n");
26
27 puts ( _help );
28
29 free(_help);
30 return FAILURE;
31}
32
33int main( int argc, char* argv[] )
34{
35 int status;
36 tox_IP_Port Ip_port;
37 const char* ip, *psend, *plisten;
38 uint16_t port_send, port_listen;
39 const uint8_t* test_bytes = "0123456789012345678901234567890123456789012345678901234567890123456789"
40 "0123456789012345678901234567890123456789012345678901234567890123456789"
41 "0123456789012345678901234567890123456789012345678901234567890123456789"
42 "0123456789012345678901234567890123456789012345678901234567890123456789";
43
44
45 rtp_session_t* _m_session;
46 rtp_msg_t *_m_msg_R, *_m_msg_S;
47 arg_t* _list = parse_args ( argc, argv );
48
49 ip = find_arg_duble(_list, "-d");
50 psend = find_arg_duble(_list, "-p");
51 plisten = find_arg_duble(_list, "-l");
52
53 if ( !ip || !plisten || !psend )
54 return _print_help(argv[0]);
55
56 port_send = atoi(psend);
57 port_listen = atoi(plisten);
58
59 IP_Port local, remote;
60
61 /*
62 * This is the Local ip. We initiate networking on
63 * this value for it's the local one. To make stuff simpler we receive over this value
64 * and send on the other one ( see remote )
65 */
66 local.ip.i = htonl(INADDR_ANY);
67 local.port = port_listen;
68 Networking_Core* _networking = new_networking(local.ip, port_listen);
69
70 if ( !_networking )
71 return FAILURE;
72
73 int _socket = _networking->sock;
74 /*
75 * Now this is the remote. It's used by rtp_session_t to determine the receivers ip etc.
76 */
77 t_setipport ( ip, port_send, &remote );
78 _m_session = rtp_init_session(-1, -1);
79 rtp_add_receiver( _m_session, &remote );
80
81 /* Now let's start our main loop in both recv and send mode */
82
83 for ( ;; )
84 {
85 /*
86 * This part checks for received messages and if gotten one
87 * display 'Received msg!' indicator and free message
88 */
89 _m_msg_R = rtp_recv_msg ( _m_session );
90
91 if ( _m_msg_R ) {
92 puts ( "Received msg!" );
93 rtp_free_msg(_m_session, _m_msg_R);
94 }
95 /* -------------------- */
96
97 /*
98 * This one makes a test msg and sends that message to the 'remote'
99 */
100 _m_msg_S = rtp_msg_new ( _m_session, test_bytes, 280 ) ;
101 rtp_send_msg ( _m_session, _m_msg_S, _socket );
102 usleep ( 10000 );
103 /* -------------------- */
104 }
105
106 return SUCCESS;
107}
108
109#endif /* _CT_BIDIRECT */
diff --git a/toxrtp/tests/test_headers.c b/toxrtp/tests/test_headers.c
new file mode 100644
index 00000000..be3f1375
--- /dev/null
+++ b/toxrtp/tests/test_headers.c
@@ -0,0 +1,316 @@
1/* test_headers.c
2 *
3 * Tests header parsing. You probably won't need this. !Red!
4 *
5 *
6 * Copyright (C) 2013 Tox project All Rights Reserved.
7 *
8 * This file is part of Tox.
9 *
10 * Tox is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * Tox is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 *
23 */
24
25#include "test_helper.h"
26#include "../toxrtp.h"
27#include "../toxrtp_message.h"
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <utime.h>
33#include <assert.h>
34#include "../toxrtp_error_id.h"
35
36#define _CT_HEADERS_
37
38#ifdef _CT_HEADERS
39
40int _socket;
41pthread_mutex_t _mutex;
42
43int print_help()
44{
45 puts (
46 " Usage: Tuxrtp [-s (send mode) -d IP ( destination ) -p PORT ( dest Port )] \n"
47 " [-r ( recv mode ) ]"
48 );
49 return FAILURE;
50}
51
52void print_session_stats ( rtp_session_t* _m_session )
53{
54 printf
55 (
56 "Session test:\n"
57 "\tPackets sent:%d\n"
58 "\tPackets recv:%d\n\n"
59 "\tBytes sent:%d\n"
60 "\tBytes recv:%d\n\n"
61 "\tHeader CCSRs:%d\n"
62 ,
63 _m_session->_packets_sent,
64 _m_session->_packets_recv,
65 _m_session->_bytes_sent,
66 _m_session->_bytes_recv,
67 _m_session->_cc
68 );
69
70 uint8_t i;
71 for ( i = 0; i < _m_session->_cc; i++ ) {
72 printf (
73 "\t%d > :%d\n", i, _m_session->_csrc[i]
74 );
75 }
76}
77
78void print_header_info ( rtp_header_t* _header )
79{
80 printf
81 (
82 "Header info:\n"
83 "\tVersion :%d\n"
84 "\tPadding :%d\n"
85 "\tExtension :%d\n"
86 "\tCSRC count :%d\n"
87 "\tPayload type :%d\n"
88 "\tMarker :%d\n\n"
89
90 "\tSSrc :%d\n"
91 "\tSequence num :%d\n"
92 "\tLenght: :%d\n"
93 "\tCSRC's:\n"
94 ,
95 rtp_header_get_flag_version ( _header ),
96 rtp_header_get_flag_padding ( _header ),
97 rtp_header_get_flag_extension ( _header ),
98 rtp_header_get_flag_CSRC_count ( _header ),
99 rtp_header_get_setting_payload_type ( _header ),
100 rtp_header_get_setting_marker ( _header ),
101
102 _header->_ssrc,
103 _header->_sequence_number,
104 _header->_length
105 );
106
107
108 uint8_t i;
109 for ( i = 0; i < rtp_header_get_flag_CSRC_count ( _header ); i++ ) {
110 printf (
111 "\t%d > :%d\n", i, _header->_csrc[i]
112 );
113 }
114
115 puts ( "\n" );
116}
117
118void print_ext_header_info(rtp_ext_header_t* _ext_header)
119{
120 printf
121 (
122 "External Header info: \n"
123 "\tLenght :%d\n"
124 "\tID :%d\n"
125 "\tValue H :%d\n"
126 "\tValue W :%d\n\n",
127 _ext_header->_ext_len,
128 _ext_header->_ext_type,
129 rtp_get_resolution_marking_height(_ext_header, 0),
130 rtp_get_resolution_marking_width(_ext_header, 0)
131 );
132}
133
134int rtp_handlepacket ( rtp_session_t* _session, rtp_msg_t* _msg )
135{
136 if ( !_msg )
137 return FAILURE;
138
139 if ( rtp_check_late_message(_session, _msg) < 0 ) {
140 rtp_register_msg(_session, _msg);
141 }
142
143 if ( _session->_last_msg ) {
144 _session->_last_msg->_next = _msg;
145 _session->_last_msg = _msg;
146 } else {
147 _session->_last_msg = _session->_oldest_msg = _msg;
148 }
149
150
151 return SUCCESS;
152}
153
154void* receivepacket_callback(void* _p_session)
155{
156 rtp_msg_t* _msg;
157 rtp_session_t* _session = _p_session;
158
159 uint32_t _bytes;
160 tox_IP_Port _from;
161 uint8_t _socket_data[MAX_UDP_PACKET_SIZE];
162
163 int _m_socket = _socket;
164
165 while ( 1 )
166 {
167 int _status = receivepacket ( _m_socket, &_from, _socket_data, &_bytes );
168
169 if ( _status == FAILURE ) { /* nothing recved */
170 usleep(1000);
171 continue;
172 }
173
174 pthread_mutex_lock ( &_mutex );
175
176 _msg = rtp_msg_parse ( NULL, _socket_data, _bytes );
177 rtp_handlepacket(_session, _msg);
178
179 pthread_mutex_unlock ( &_mutex );
180 }
181
182 pthread_exit(NULL);
183}
184
185int main ( int argc, char* argv[] )
186{
187 arg_t* _list = parse_args ( argc, argv );
188
189 if ( _list == NULL ) { /* failed */
190 return print_help();
191 }
192
193 pthread_mutex_init ( &_mutex, NULL );
194
195 int status;
196 IP_Port Ip_port;
197 const char* ip;
198 uint16_t port;
199
200
201 const uint8_t* test_bytes [300];
202 memset(test_bytes, 'a', 300);
203
204 rtp_session_t* _m_session;
205 rtp_msg_t* _m_msg;
206
207 if ( find_arg_simple ( _list, "-r" ) != FAILURE ) { /* Server mode */
208
209 IP_Port LOCAL_IP; /* since you need at least 1 recv-er */
210 LOCAL_IP.ip.i = htonl(INADDR_ANY);
211 LOCAL_IP.port = RTP_PORT;
212 LOCAL_IP.padding = -1;
213
214 _m_session = rtp_init_session ( -1, -1 );
215 Networking_Core* _networking = new_networking(LOCAL_IP.ip, RTP_PORT_LISTEN);
216 _socket = _networking->sock;
217
218
219 if ( !_networking ){
220 pthread_mutex_destroy ( &_mutex );
221 return FAILURE;
222 }
223
224 int _socket = _networking->sock;
225
226 if ( status < 0 ) {
227 pthread_mutex_destroy ( &_mutex );
228 return FAILURE;
229 }
230 /* -- start in recv mode, get 1 message and then analyze it -- */
231 pthread_t _tid;
232 RUN_IN_THREAD(receivepacket_callback, _tid, _m_session)
233
234 for ( ; ; ) { /* Recv for x seconds */
235 _m_msg = rtp_recv_msg ( _m_session );
236
237 /* _m_msg = rtp_session_get_message_queded ( _m_session ); DEPRECATED */
238 if ( _m_msg ) {
239 /*rtp_free_msg(_m_session, _m_msg);
240 _m_msg = NULL;*/
241 printf("Timestamp: %d\n", _m_msg->_header->_timestamp);
242 }
243
244 usleep ( 10000 );
245 }
246
247 if ( _m_msg->_header ) {
248 rtp_header_print ( _m_msg->_header );
249 }
250 if ( _m_msg->_ext_header ){
251 print_ext_header_info(_m_msg->_ext_header);
252 }
253
254 //print_session_stats ( _m_session );
255
256
257 //printf ( "Payload: ( %d ) \n%s\n", _m_msg->_length, _m_msg->_data );
258
259
260 } else if ( find_arg_simple ( _list, "-s" ) != FAILURE ) {
261 ip = find_arg_duble ( _list, "-d" );
262
263 if ( ip == NULL ) {
264 pthread_mutex_destroy ( &_mutex );
265 return FAILURE;
266 }
267
268 const char* _port = find_arg_duble ( _list, "-p" );
269
270 if ( _port != NULL ) {
271 port = atoi ( _port );
272 }
273
274 t_setipport ( ip, port, &Ip_port );
275 printf ( "Remote: %s:%d\n", ip, port );
276
277 Networking_Core* _networking = new_networking(Ip_port.ip, RTP_PORT);
278
279 if ( !_networking ){
280 pthread_mutex_destroy ( &_mutex );
281 return FAILURE;
282 }
283
284 int _socket = _networking->sock;
285
286 _m_session = rtp_init_session ( -1, -1 );
287 rtp_add_receiver( _m_session, &Ip_port );
288 //rtp_add_resolution_marking(_m_session, 1920, 1080);
289 //rtp_add_framerate_marking(_m_session, 1000);
290
291 puts ( "Now sending payload!\n" );
292 uint16_t _first_sequ = _m_session->_sequence_number;
293
294 /* use already defined buffer lenght */
295 while ( 1 ){
296 _m_msg = rtp_msg_new ( _m_session, test_bytes, 300 );
297 rtp_send_msg ( _m_session, _m_msg, _socket );
298 usleep(10000);
299 }
300
301 if ( _m_session->_last_error ) {
302 puts ( _m_session->_last_error );
303 }
304
305 return rtp_terminate_session(_m_session);
306
307 } else {
308 pthread_mutex_destroy ( &_mutex );
309 return FAILURE;
310 }
311 pthread_mutex_destroy ( &_mutex );
312
313 return SUCCESS;
314}
315
316#endif /* _CT_HEADERS */
diff --git a/toxrtp/tests/test_helper.c b/toxrtp/tests/test_helper.c
new file mode 100644
index 00000000..526b6b38
--- /dev/null
+++ b/toxrtp/tests/test_helper.c
@@ -0,0 +1,83 @@
1/* test_helper.c
2 *
3 * Tests support. !Red!
4 *
5 *
6 * Copyright (C) 2013 Tox project All Rights Reserved.
7 *
8 * This file is part of Tox.
9 *
10 * Tox is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * Tox is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 *
23 */
24
25#include "test_helper.h"
26
27#include <string.h>
28#include <stdlib.h>
29
30arg_t* parse_args ( int argc, char* argv[] )
31{
32 arg_t* _list = calloc(sizeof(arg_t), 1);
33 _list->next = _list->prev = NULL;
34
35 arg_t* it = _list;
36
37 size_t val;
38 for ( val = 0; val < argc; val ++ ) {
39 it->value = argv[val];
40
41 if ( val < argc - 1 ) { /* just about to end */
42 it->next = calloc(sizeof(arg_t), 1);
43 it->next->prev = it;
44 it = it->next;
45 it->next = NULL;
46 }
47 }
48
49 return _list;
50}
51
52int find_arg_simple ( arg_t* _head, const char* _id )
53{
54 arg_t* it = _head;
55
56 int i;
57 for ( i = 1; it != NULL; it = it->next ) {
58 if ( strcmp ( _id, it->value ) == 0 ) {
59 return i;
60 }
61
62 i++;
63 }
64
65 return FAILURE;
66}
67
68const char* find_arg_duble ( arg_t* _head, const char* _id )
69{
70 arg_t* _it;
71 for ( _it = _head; _it != NULL; _it = _it->next ) {
72 if ( strcmp ( _id, _it->value ) == 0 ) {
73 if ( _it->next && _it->next->value[0] != '-' ) { /* exclude option */
74 return _it->next->value;
75 } else {
76 return NULL;
77 }
78 }
79 }
80
81 return NULL;
82}
83
diff --git a/toxrtp/tests/test_helper.h b/toxrtp/tests/test_helper.h
new file mode 100644
index 00000000..de654743
--- /dev/null
+++ b/toxrtp/tests/test_helper.h
@@ -0,0 +1,61 @@
1/* test_helper.h
2 *
3 * Tests support. !Red!
4 *
5 *
6 * Copyright (C) 2013 Tox project All Rights Reserved.
7 *
8 * This file is part of Tox.
9 *
10 * Tox is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * Tox is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 *
23 */
24
25#ifndef _TEST__HELPER_
26#define _TEST__HELPER_
27
28#include "../toxrtp_helper.h"
29
30#define RTP_PORT 31003
31#define RTP_PORT_LISTEN 31001
32
33#define _SLEEP_INTERVAL 1000
34
35typedef struct arg_s {
36 const char* value;
37 struct arg_s* next;
38 struct arg_s* prev;
39
40} arg_t;
41
42
43
44/* Parses arguments into d-list arg_t */
45arg_t* parse_args ( int argc, char* argv[] );
46
47/* Get a single argument ( i.e. ./test -s |find if has 's' >> | find_arg_simple(_t, "-s") )
48 * A little error checking, of course, returns FAILURE if not found and if found returns position
49 * where it's found.
50 */
51int find_arg_simple ( arg_t* _head, const char* _id );
52
53/* Get a single argument ( i.e. ./test -d 127.0.0.1 |get 'd' value >> | find_arg_duble(_t, "-d") )
54 * A little error checking, of course, returns NULL if not found and if found returns value
55 * of that argument ( i.e. '127.0.0.1').
56 */
57const char* find_arg_duble ( arg_t* _head, const char* _id );
58
59#endif /* _TEST__HELPER_ */
60
61
diff --git a/toxrtp/toxrtp.c b/toxrtp/toxrtp.c
new file mode 100644
index 00000000..6844b0b1
--- /dev/null
+++ b/toxrtp/toxrtp.c
@@ -0,0 +1,693 @@
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}
diff --git a/toxrtp/toxrtp.h b/toxrtp/toxrtp.h
new file mode 100644
index 00000000..f6270c11
--- /dev/null
+++ b/toxrtp/toxrtp.h
@@ -0,0 +1,188 @@
1/* rtp_impl.h
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
28#ifndef _RTP__IMPL_H_
29#define _RTP__IMPL_H_
30
31#define RTP_VERSION 2
32#include <inttypes.h>
33#include "../toxcore/tox.h"
34
35/* Extension header flags */
36#define RTP_EXT_TYPE_RESOLUTION 0x01
37#define RTP_EXT_TYPE_FRAMERATE 0x02
38
39/* Some defines */
40
41#define RTP_PACKET 70
42
43/* Payload identifiers */
44
45/* Audio */
46#define _PAYLOAD_OPUS 96
47
48/* Video */
49#define _PAYLOAD_VP8 106
50
51/* End of Payload identifiers */
52
53/* End of defines */
54
55
56/* Our main session descriptor.
57 * It measures the session variables and controls
58 * the entire session. There are functions for manipulating
59 * the session so tend to use those instead of directly accessing
60 * session parameters.
61 */
62typedef struct rtp_session_s {
63 uint8_t _version;
64 uint8_t _padding;
65 uint8_t _extension;
66 uint8_t _cc;
67 uint8_t _marker;
68 uint8_t _payload_type;
69 uint16_t _sequence_number; /* Set when sending */
70 uint16_t _last_sequence_number; /* Check when recving msg */
71 uint32_t _initial_time;
72 uint32_t _time_elapsed;
73 uint32_t _current_timestamp;
74 uint32_t _ssrc;
75 uint32_t* _csrc;
76
77
78 /* If some additional data must be sent via message
79 * apply it here. Only by allocating this member you will be
80 * automatically placing it within a message.
81 */
82
83 struct rtp_ext_header_s* _ext_header;
84 /* External header identifiers */
85 int _exthdr_resolution;
86 int _exthdr_framerate;
87
88 int _max_users; /* -1 undefined */
89
90 uint64_t _packets_sent; /* measure packets */
91 uint64_t _packets_recv;
92
93 uint64_t _bytes_sent;
94 uint64_t _bytes_recv;
95
96 uint64_t _packet_loss;
97
98 const char* _last_error;
99
100 struct rtp_dest_list_s* _dest_list;
101 struct rtp_dest_list_s* _last_user; /* a tail for faster appending */
102
103 struct rtp_msg_s* _oldest_msg;
104 struct rtp_msg_s* _last_msg; /* tail */
105
106 uint16_t _prefix_length;
107 uint8_t* _prefix;
108
109 /* Specifies multiple session use.
110 * When using one session it uses default value ( -1 )
111 * Otherwise it's set to 1 and rtp_register_msg () is required
112 */
113 int _multi_session;
114
115 uint32_t _current_framerate;
116
117 pthread_mutex_t _mutex;
118
119} rtp_session_t;
120
121
122/*
123 * Now i don't believe we need to store this _from thing every time
124 * since we have csrc table but will leave it like this for a while
125 */
126
127
128void rtp_free_msg ( rtp_session_t* _session, struct rtp_msg_s* _msg );
129int rtp_release_session_recv ( rtp_session_t* _session );
130
131/* Functions handling receiving */
132struct rtp_msg_s* rtp_recv_msg ( rtp_session_t* _session );
133void rtp_store_msg ( rtp_session_t* _session, struct rtp_msg_s* _msg );
134
135/*
136 * rtp_msg_parse() stores headers separately from the payload data
137 * and so the _length variable is set accordingly
138 */
139struct rtp_msg_s* rtp_msg_parse ( rtp_session_t* _session, const uint8_t* _data, uint32_t _length );
140
141int rtp_check_late_message (rtp_session_t* _session, struct rtp_msg_s* _msg);
142void rtp_register_msg ( rtp_session_t* _session, struct rtp_msg_s* );
143
144/* Functions handling sending */
145int rtp_send_msg ( rtp_session_t* _session, struct rtp_msg_s* _msg, void* _core_handler );
146
147/*
148 * rtp_msg_new() stores headers and payload data in one container ( _data )
149 * and the _length is set accordingly. Returned message is used for sending only
150 * so there is not much use of the headers there
151 */
152struct rtp_msg_s* rtp_msg_new ( rtp_session_t* _session, const uint8_t* _data, uint32_t _length );
153
154
155/* Convenient functions for creating a header */
156struct rtp_header_s* rtp_build_header ( rtp_session_t* _session );
157
158/* Functions handling session control */
159
160/* Handling an rtp packet */
161/* int rtp_handlepacket(uint8_t * packet, uint32_t length, IP_Port source); */
162
163/* Session initiation and termination.
164 * Set _multi_session to -1 if not using multiple sessions
165 */
166rtp_session_t* rtp_init_session ( int _max_users, int _multi_session );
167int rtp_terminate_session ( rtp_session_t* _session );
168
169/* Adding receiver */
170int rtp_add_receiver ( rtp_session_t* _session, tox_IP_Port* _dest );
171
172/* Convenient functions for marking the resolution */
173int rtp_add_resolution_marking ( rtp_session_t* _session, uint16_t _width, uint16_t _height );
174int rtp_remove_resolution_marking ( rtp_session_t* _session );
175uint16_t rtp_get_resolution_marking_height ( struct rtp_ext_header_s* _header, uint32_t _position );
176uint16_t rtp_get_resolution_marking_width ( struct rtp_ext_header_s* _header, uint32_t _position );
177
178int rtp_add_framerate_marking ( rtp_session_t* _session, uint32_t _value );
179int rtp_remove_framerate_marking ( rtp_session_t* _session );
180uint32_t rtp_get_framerate_marking ( struct rtp_ext_header_s* _header );
181/* Convenient functions for marking the payload */
182void rtp_set_payload_type ( rtp_session_t* _session, uint8_t _payload_value );
183uint32_t rtp_get_payload_type ( rtp_session_t* _session );
184
185/* When using RTP in core be sure to set prefix when sending via rtp_send_msg */
186int rtp_set_prefix ( rtp_session_t* _session, uint8_t* _prefix, uint16_t _prefix_length );
187
188#endif /* _RTP__IMPL_H_ */
diff --git a/toxrtp/toxrtp_error.c b/toxrtp/toxrtp_error.c
new file mode 100644
index 00000000..3a7ff9a5
--- /dev/null
+++ b/toxrtp/toxrtp_error.c
@@ -0,0 +1,68 @@
1
2#ifdef HAVE_CONFIG_H
3#include "config.h"
4#endif /* HAVE_CONFIG_H */
5
6#include "toxrtp_error.h"
7#include "toxrtp_helper.h"
8
9#include <stdio.h>
10#include <stdarg.h>
11#include <string.h>
12#include <stdlib.h>
13#include <assert.h>
14
15typedef struct rtp_error_s {
16 char* _message;
17 int _id;
18
19} rtp_error_t;
20
21static rtp_error_t* _register = NULL;
22static size_t _it = 0;
23
24void t_rtperr_register ( int _id, const char* _info )
25{
26 size_t _info_size = strlen ( _info );
27
28 if ( !_register ) {
29 _register = calloc ( sizeof ( rtp_error_t ), 1 );
30 } else {
31 _register = realloc ( _register, sizeof ( rtp_error_t ) * ( _it + 1 ) );
32 }
33 assert(_register);
34
35
36 rtp_error_t* _current = & _register[_it];
37
38 _current->_id = _id;
39 _current->_message = calloc ( sizeof(char), _info_size );
40 assert(_current->_message);
41
42 t_memcpy ( (uint8_t*)_current->_message, (const uint8_t*)_info, _info_size );
43 _it ++;
44}
45
46const char* t_rtperr ( int _errno )
47{
48 if ( !_register )
49 return "Unregistered";
50
51 uint32_t _i;
52
53 for ( _i = _it; _i--; ) {
54 if ( _register[_i]._id == _errno ) {
55 return _register[_i]._message;
56 }
57 }
58
59 return "Invalid error id!";
60}
61
62void t_rtperr_print ( const char* _val, ... )
63{
64 va_list _args;
65 va_start ( _args, _val );
66 vfprintf ( stderr, _val, _args );
67 va_end ( _args );
68}
diff --git a/toxrtp/toxrtp_error.h b/toxrtp/toxrtp_error.h
new file mode 100644
index 00000000..0e017246
--- /dev/null
+++ b/toxrtp/toxrtp_error.h
@@ -0,0 +1,25 @@
1#ifndef _RTP_ERROR_
2#define _RTP_ERROR_
3
4#define PRINT_FORMAT "Error %d: %s at %s:%d\n"
5#define PRINT_ARGS( _errno ) _errno, t_rtperr(_errno), __FILE__, __LINE__
6
7
8const char* t_rtperr ( int _errno );
9void t_rtperr_register ( int _id, const char* _info );
10
11void t_invoke_error ( int _id );
12void t_rtperr_print ( const char* _val, ... );
13
14
15#ifdef _USE_ERRORS
16#define t_perror( _errno ) t_rtperr_print ( PRINT_FORMAT, PRINT_ARGS ( _errno ) )
17#else
18#define t_perror( _errno )do { } while(0)
19#endif /* _USE_ERRORS */
20
21#ifdef _STDIO_H
22#define t_errexit( _errno ) exit(-_errno)
23#endif /* _STDIO_H */
24
25#endif /* _RTP_ERROR_ */
diff --git a/toxrtp/toxrtp_error_id.h b/toxrtp/toxrtp_error_id.h
new file mode 100644
index 00000000..201aa936
--- /dev/null
+++ b/toxrtp/toxrtp_error_id.h
@@ -0,0 +1,32 @@
1#ifndef _RTP_ERROR_ID_
2#define _RTP_ERROR_ID_
3
4#include "toxrtp_error.h"
5
6typedef enum error_s {
7 RTP_ERROR_PACKET_DROPED = 1,
8 RTP_ERROR_EMPTY_MESSAGE,
9 RTP_ERROR_STD_SEND_FAILURE,
10 RTP_ERROR_NO_EXTERNAL_HEADER,
11 RTP_ERROR_INVALID_EXTERNAL_HEADER,
12 RTP_ERROR_HEADER_PARSING,
13 RTP_ERROR_PAYLOAD_NULL,
14 RTP_ERROR_PAYLOAD_INVALID,
15
16} error_t;
17
18
19/* Only needed to be called once */
20#ifndef REGISTER_RTP_ERRORS
21#define REGISTER_RTP_ERRORS \
22 t_rtperr_register( RTP_ERROR_PACKET_DROPED, "Ivalid sequence number, packet is late" ); \
23 t_rtperr_register( RTP_ERROR_EMPTY_MESSAGE, "Tried to send an empty message" ); \
24 t_rtperr_register( RTP_ERROR_STD_SEND_FAILURE, "Failed call function: sendto" ); \
25 t_rtperr_register( RTP_ERROR_NO_EXTERNAL_HEADER, "While parsing external header" ); \
26 t_rtperr_register( RTP_ERROR_INVALID_EXTERNAL_HEADER, "While parsing external header" ); \
27 t_rtperr_register( RTP_ERROR_HEADER_PARSING, "While parsing header" ); \
28 t_rtperr_register( RTP_ERROR_PAYLOAD_NULL, "Payload is NULL" ); \
29 t_rtperr_register( RTP_ERROR_PAYLOAD_INVALID, "Invalid payload size" );
30#endif /* REGISTER_RTP_ERRORS */
31
32#endif /* _RTP_ERROR_ID_ */
diff --git a/toxrtp/toxrtp_helper.c b/toxrtp/toxrtp_helper.c
new file mode 100644
index 00000000..bb2dc56b
--- /dev/null
+++ b/toxrtp/toxrtp_helper.c
@@ -0,0 +1,209 @@
1/* rtp_helper.c
2*
3* Has some standard functions. !Red!
4*
5*
6* Copyright (C) 2013 Tox project All Rights Reserved.
7*
8* This file is part of Tox.
9*
10* Tox is free software: you can redistribute it and/or modify
11* it under the terms of the GNU General Public License as published by
12* the Free Software Foundation, either version 3 of the License, or
13* (at your option) any later version.
14*
15* Tox is distributed in the hope that it will be useful,
16* but WITHOUT ANY WARRANTY; without even the implied warranty of
17* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18* GNU General Public License for more details.
19*
20* You should have received a copy of the GNU General Public License
21* along with Tox. If not, see <http://www.gnu.org/licenses/>.
22*
23*/
24
25
26
27#ifdef HAVE_CONFIG_H
28#include "config.h"
29#endif /* HAVE_CONFIG_H */
30
31#include "toxrtp_helper.h"
32#include "../toxcore/network.h"
33
34#include <arpa/inet.h> /* Fixes implicit function warning. */
35#include <assert.h>
36
37#ifdef WIN
38#include <windows.h>
39#endif /* WIN */
40
41
42static int _seed = 0; /* Not initiated */
43
44int t_setipport ( const char* _ip, unsigned short _port, void* _dest )
45{
46 assert(_dest);
47
48 IP_Port* _dest_c = ( IP_Port* ) _dest;
49 ip_init(&_dest_c->ip, 0);
50
51 IP_Port _ipv6_garbage;
52
53 if ( !addr_resolve(_ip, &_dest_c->ip, &_ipv6_garbage.ip) )
54 return FAILURE;
55
56 _dest_c->port = htons ( _port );
57
58 return SUCCESS;
59}
60
61uint32_t t_random ( uint32_t _max )
62{
63 if ( !_seed ) {
64 srand ( t_time() );
65 _seed++;
66 }
67
68 if ( _max <= 0 ) {
69 return ( unsigned ) rand();
70 } else {
71 return ( unsigned ) rand() % _max;
72 }
73}
74
75void t_memcpy ( uint8_t* _dest, const uint8_t* _source, size_t _size )
76{
77 /*
78 * Using countdown to zero method
79 * It's faster than for(_it = 0; _it < _size; _it++);
80 */
81 size_t _it = _size;
82
83 do {
84 _it--;
85 _dest[_it] = _source[_it];
86 } while ( _it );
87
88}
89
90uint8_t* t_memset ( uint8_t* _dest, uint8_t _valu, size_t _size )
91{
92 /*
93 * Again using countdown to zero method
94 */
95 size_t _it = _size;
96
97 do {
98 _it--;
99 _dest[_it] = _valu;
100 } while ( _it );
101
102 return _dest;
103}
104
105size_t t_memlen ( const uint8_t* _valu)
106{
107 const uint8_t* _it;
108 size_t _retu = 0;
109
110 for ( _it = _valu; *_it; ++_it ) ++_retu;
111
112 return _retu;
113}
114
115uint8_t* t_strallcpy ( const uint8_t* _source ) /* string alloc and copy */
116{
117 assert(_source);
118
119 size_t _length = t_memlen(_source) + 1; /* make space for null character */
120
121 uint8_t* _dest = calloc( sizeof ( uint8_t ), _length );
122 assert(_dest);
123
124 t_memcpy(_dest, _source, _length);
125
126 return _dest;
127}
128
129size_t t_strfind ( const uint8_t* _str, const uint8_t* _substr )
130{
131 size_t _pos = 0;
132 size_t _it, _delit = 0;
133
134 for ( _it = 0; _str[_it] != '\0'; _it++ ){
135 if ( _str[_it] == _substr[_delit] ){
136 _pos = _it;
137 while ( _str[_it] == _substr[_delit] && _str[_it] != '\0' ){
138 _it ++;
139 _delit++;
140
141 if ( _substr[_delit] == '\0' ){
142 return _pos;
143 }
144 }
145 _delit = 0;
146 _pos = 0;
147 }
148 }
149 return _pos;
150}
151
152#ifdef WIN
153#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
154 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
155#else
156 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
157#endif
158
159struct timezone
160{
161 int tz_minuteswest; /* minutes W of Greenwich */
162 int tz_dsttime; /* type of dst correction */
163};
164
165int gettimeofday(struct timeval *tv, struct timezone *tz)
166{
167 FILETIME ft;
168 unsigned __int64 tmpres = 0;
169 static int tzflag;
170
171 if (NULL != tv)
172 {
173 GetSystemTimeAsFileTime(&ft);
174
175 tmpres |= ft.dwHighDateTime;
176 tmpres <<= 32;
177 tmpres |= ft.dwLowDateTime;
178
179 /*converting file time to unix epoch*/
180 tmpres -= DELTA_EPOCH_IN_MICROSECS;
181 tmpres /= 10; /*convert into microseconds*/
182 tv->tv_sec = (long)(tmpres / 1000000UL);
183 tv->tv_usec = (long)(tmpres % 1000000UL);
184 }
185
186 if (NULL != tz)
187 {
188 if (!tzflag)
189 {
190 _tzset();
191 tzflag++;
192 }
193 tz->tz_minuteswest = _timezone / 60;
194 tz->tz_dsttime = _daylight;
195 }
196
197 return 0;
198}
199#endif /* WIN */
200
201
202uint64_t t_time()
203{
204 struct timeval _tv;
205 gettimeofday(&_tv, NULL);
206 uint64_t _retu_usec = _tv.tv_sec % 1000000; /* get 6 digits an leave space for 3 more */
207 _retu_usec = _retu_usec * 1000 + (_tv.tv_usec / 1000 );
208 return _retu_usec;
209}
diff --git a/toxrtp/toxrtp_helper.h b/toxrtp/toxrtp_helper.h
new file mode 100644
index 00000000..c9bcfcca
--- /dev/null
+++ b/toxrtp/toxrtp_helper.h
@@ -0,0 +1,77 @@
1/* rtp_helper.h
2*
3* Has some standard functions. !Red!
4*
5*
6* Copyright (C) 2013 Tox project All Rights Reserved.
7*
8* This file is part of Tox.
9*
10* Tox is free software: you can redistribute it and/or modify
11* it under the terms of the GNU General Public License as published by
12* the Free Software Foundation, either version 3 of the License, or
13* (at your option) any later version.
14*
15* Tox is distributed in the hope that it will be useful,
16* but WITHOUT ANY WARRANTY; without even the implied warranty of
17* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18* GNU General Public License for more details.
19*
20* You should have received a copy of the GNU General Public License
21* along with Tox. If not, see <http://www.gnu.org/licenses/>.
22*
23*/
24
25#ifndef _RTP__HELPER_H_
26#define _RTP__HELPER_H_
27
28#include <time.h>
29#include <inttypes.h>
30
31/* Current time, unix format */
32/*#define _time ((uint32_t)time(NULL))*/
33
34#define SUCCESS 0
35#define FAILURE -1
36
37#define _USE_ERRORS
38
39#define RUN_IN_THREAD(_func, _thread_id, _arg_ptr) \
40if ( pthread_create ( &_thread_id, NULL, _func, _arg_ptr ) ) { \
41 pthread_detach ( _thread_id ); \
42}
43
44/* Core adaptation helper */
45int t_setipport ( const char* _ip, unsigned short _port, void* _cont );
46uint32_t t_random ( uint32_t _max );
47
48/* It's a bit faster than the memcpy it self and more optimized for using
49 * a uint8_t since memcpy has optimizations when copying "words" i.e. long type.
50 * Otherwise it just copies char's while we need only uint8_t
51 */
52void t_memcpy ( uint8_t* _dest, const uint8_t* _source, size_t _size );
53
54
55/* This is our memset. It's also a bit faster than the memset for it
56 * does not cast _dest to char* and uses faster loop algorithm.
57 */
58uint8_t* t_memset ( uint8_t* _dest, uint8_t _valu, size_t _size );
59
60/* Get null terminated len */
61size_t t_memlen ( const uint8_t* _valu );
62
63/* finds location of substring */
64size_t t_strfind ( const uint8_t* _str, const uint8_t* _substr );
65
66/* string alloc and copy ( ! must be null terminated ) */
67uint8_t* t_strallcpy ( const uint8_t* _source );
68
69/* Get current time in milliseconds */
70uint64_t t_time();
71
72
73#endif /* _RTP__HELPER_H_ */
74
75
76
77
diff --git a/toxrtp/toxrtp_message.c b/toxrtp/toxrtp_message.c
new file mode 100644
index 00000000..e7f1f2c0
--- /dev/null
+++ b/toxrtp/toxrtp_message.c
@@ -0,0 +1,351 @@
1/* rtp_message.c
2 *
3 * Rtp Message handler. It handles message/header parsing.
4 * Refer to RTP: A Transport Protocol for Real-Time Applications ( RFC 3550 ) for more info. !Red!
5 *
6 *
7 * Copyright (C) 2013 Tox project All Rights Reserved.
8 *
9 * This file is part of Tox.
10 *
11 * Tox is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * Tox is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
23 *
24 */
25
26#ifdef HAVE_CONFIG_H
27#include "config.h"
28#endif /* HAVE_CONFIG_H */
29
30#include "toxrtp_message.h"
31#include "toxrtp.h"
32#include <stdio.h>
33
34#ifdef _USE_ERRORS
35#include "toxrtp_error_id.h"
36#endif /* _USE_ERRORS */
37
38#include <assert.h>
39
40/* Some defines */
41
42/* End of defines */
43
44void rtp_header_print (const rtp_header_t* _header)
45{
46 printf("Header: \n"
47 "Version: %d\n"
48 "Padding: %d\n"
49 "Ext: %d\n"
50 "CC: %d\n"
51 "marker: %d\n"
52 "payload typ:%d\n\n"
53 "sequ num: %d\n"
54 "Timestamp: %d\n"
55 "SSrc: %d\n"
56 "CSrc: %d\n"
57 "Lenght: %d\n"
58 ,rtp_header_get_flag_version(_header)
59 ,rtp_header_get_flag_padding(_header)
60 ,rtp_header_get_flag_extension(_header)
61 ,rtp_header_get_flag_CSRC_count(_header)
62 ,rtp_header_get_setting_marker(_header)
63 ,rtp_header_get_setting_payload_type(_header)
64 ,_header->_sequence_number
65 ,_header->_timestamp
66 ,_header->_ssrc
67 ,_header->_csrc[0]
68 ,_header->_length
69 );
70}
71
72rtp_header_t* rtp_extract_header ( const uint8_t* _payload, size_t _bytes )
73{
74 if ( !_payload ) {
75 t_perror ( RTP_ERROR_PAYLOAD_NULL );
76 return NULL;
77 }
78 const uint8_t* _it = _payload;
79
80 rtp_header_t* _retu = calloc(sizeof(rtp_header_t), 1);
81 assert(_retu);
82
83 _retu->_flags = *_it; ++_it;
84
85 /* This indicates if the first 2 bytes are valid.
86 * Now it my happen that this is out of order but
87 * it cuts down chances of parsing some invalid value
88 */
89 if ( rtp_header_get_flag_version(_retu) != RTP_VERSION ){
90 printf("Invalid version: %d\n", rtp_header_get_flag_version(_retu));
91 //assert(rtp_header_get_flag_version(_retu) == RTP_VERSION);
92 /* Deallocate */
93 //DEALLOCATOR(_retu);
94 //return NULL;
95 }
96
97 /*
98 * Added a check for the size of the header little sooner so
99 * I don't need to parse the other stuff if it's bad
100 */
101 uint8_t cc = rtp_header_get_flag_CSRC_count ( _retu );
102 uint32_t _lenght = _MIN_HEADER_LENGTH + ( cc * 4 );
103
104 if ( _bytes < _lenght ) {
105 t_perror ( RTP_ERROR_PAYLOAD_INVALID );
106 return NULL;
107 }
108
109 if ( cc > 0 ) {
110 _retu->_csrc = calloc ( sizeof ( uint32_t ), cc );
111 assert(_retu->_csrc);
112
113 } else { /* But this should not happen ever */
114 t_perror ( RTP_ERROR_HEADER_PARSING );
115 return NULL;
116 }
117
118
119 _retu->_marker_payload_t = *_it; ++_it;
120 _retu->_length = _lenght;
121 _retu->_sequence_number = ( ( uint16_t ) * _it << 8 ) | * ( _it + 1 );
122
123 _it += 2;
124
125 _retu->_timestamp = ( ( uint32_t ) * _it << 24 ) |
126 ( ( uint32_t ) * ( _it + 1 ) << 16 ) |
127 ( ( uint32_t ) * ( _it + 2 ) << 8 ) |
128 ( * ( _it + 3 ) ) ;
129
130 _it += 4;
131
132 _retu->_ssrc = ( ( uint32_t ) * _it << 24 ) |
133 ( ( uint32_t ) * ( _it + 1 ) << 16 ) |
134 ( ( uint32_t ) * ( _it + 2 ) << 8 ) |
135 ( ( uint32_t ) * ( _it + 3 ) ) ;
136
137
138 size_t x;
139 for ( x = 0; x < cc; x++ ) {
140 _it += 4;
141 _retu->_csrc[x] = ( ( uint32_t ) * _it << 24 ) |
142 ( ( uint32_t ) * ( _it + 1 ) << 16 ) |
143 ( ( uint32_t ) * ( _it + 2 ) << 8 ) |
144 ( ( uint32_t ) * ( _it + 3 ) ) ;
145 }
146
147 return _retu;
148}
149
150rtp_ext_header_t* rtp_extract_ext_header ( const uint8_t* _payload, size_t _bytes )
151{
152 if ( !_payload ) {
153 t_perror ( RTP_ERROR_PAYLOAD_NULL );
154 return NULL;
155 }
156
157
158
159 const uint8_t* _it = _payload;
160
161 rtp_ext_header_t* _retu = calloc(sizeof(rtp_ext_header_t), 1);
162 assert(_retu);
163
164 uint16_t _ext_len = ( ( uint16_t ) * _it << 8 ) | * ( _it + 1 ); _it += 2;
165
166 if ( _bytes < ( _ext_len * sizeof(uint32_t) ) ) {
167 t_perror ( RTP_ERROR_PAYLOAD_INVALID );
168 return NULL;
169 }
170
171 _retu->_ext_len = _ext_len;
172 _retu->_ext_type = ( ( uint16_t ) * _it << 8 ) | * ( _it + 1 ); _it -= 2;
173
174 _retu->_hd_ext = calloc(sizeof(uint32_t), _ext_len);
175 assert(_retu->_hd_ext);
176
177 uint32_t* _hd_ext = _retu->_hd_ext;
178 size_t i;
179 for ( i = 0; i < _ext_len; i++ ) {
180 _it += 4;
181 _hd_ext[i] = ( ( uint32_t ) * _it << 24 ) |
182 ( ( uint32_t ) * ( _it + 1 ) << 16 ) |
183 ( ( uint32_t ) * ( _it + 2 ) << 8 ) |
184 ( ( uint32_t ) * ( _it + 3 ) ) ;
185 }
186
187 return _retu;
188}
189
190uint8_t* rtp_add_header ( rtp_header_t* _header, uint8_t* _payload )
191{
192 uint8_t cc = rtp_header_get_flag_CSRC_count ( _header );
193
194 uint8_t* _it = _payload;
195
196 *_it = _header->_flags; ++_it;
197 *_it = _header->_marker_payload_t; ++_it;
198
199 *_it = ( _header->_sequence_number >> 8 ); ++_it;
200 *_it = ( _header->_sequence_number ); ++_it;
201
202 uint32_t _timestamp = _header->_timestamp;
203 *_it = ( _timestamp >> 24 ); ++_it;
204 *_it = ( _timestamp >> 16 ); ++_it;
205 *_it = ( _timestamp >> 8 ); ++_it;
206 *_it = ( _timestamp ); ++_it;
207
208 uint32_t _ssrc = _header->_ssrc;
209 *_it = ( _ssrc >> 24 ); ++_it;
210 *_it = ( _ssrc >> 16 ); ++_it;
211 *_it = ( _ssrc >> 8 ); ++_it;
212 *_it = ( _ssrc );
213
214 uint32_t *_csrc = _header->_csrc;
215 size_t x;
216 for ( x = 0; x < cc; x++ ) {
217 ++_it;
218 *_it = ( _csrc[x] >> 24 ); ++_it;
219 *_it = ( _csrc[x] >> 16 ); ++_it;
220 *_it = ( _csrc[x] >> 8 ); ++_it;
221 *_it = ( _csrc[x] );
222 }
223
224 return _it;
225}
226
227uint8_t* rtp_add_extention_header ( rtp_ext_header_t* _header, uint8_t* _payload )
228{
229 uint8_t* _it = _payload;
230
231 *_it = ( _header->_ext_len >> 8 ); _it++;
232 *_it = ( _header->_ext_len ); _it++;
233
234 *_it = ( _header->_ext_type >> 8 ); ++_it;
235 *_it = ( _header->_ext_type );
236
237 size_t x;
238
239 uint32_t* _hd_ext = _header->_hd_ext;
240 for ( x = 0; x < _header->_ext_len; x++ ) {
241 ++_it;
242 *_it = ( _hd_ext[x] >> 24 ); ++_it;
243 *_it = ( _hd_ext[x] >> 16 ); ++_it;
244 *_it = ( _hd_ext[x] >> 8 ); ++_it;
245 *_it = ( _hd_ext[x] );
246 }
247
248 return _it;
249}
250
251size_t rtp_header_get_size ( const rtp_header_t* _header )
252{
253 return ( 8 + ( rtp_header_get_flag_CSRC_count ( _header ) * 4 ) );
254}
255/* Setting flags */
256
257void rtp_header_add_flag_version ( rtp_header_t* _header, uint32_t value )
258{
259 ( _header->_flags ) &= 0x3F;
260 ( _header->_flags ) |= ( ( ( value ) << 6 ) & 0xC0 );
261}
262
263void rtp_header_add_flag_padding ( rtp_header_t* _header, uint32_t value )
264{
265 if ( value > 0 ) {
266 value = 1; /* It can only be 1 */
267 }
268
269 ( _header->_flags ) &= 0xDF;
270 ( _header->_flags ) |= ( ( ( value ) << 5 ) & 0x20 );
271}
272
273void rtp_header_add_flag_extension ( rtp_header_t* _header, uint32_t value )
274{
275 if ( value > 0 ) {
276 value = 1; /* It can only be 1 */
277 }
278
279 ( _header->_flags ) &= 0xEF;
280 ( _header->_flags ) |= ( ( ( value ) << 4 ) & 0x10 );
281}
282
283void rtp_header_add_flag_CSRC_count ( rtp_header_t* _header, uint32_t value )
284{
285 ( _header->_flags ) &= 0xF0;
286 ( _header->_flags ) |= ( ( value ) & 0x0F );
287}
288
289void rtp_header_add_setting_marker ( rtp_header_t* _header, uint32_t value )
290{
291 if ( value > 1 )
292 value = 1;
293
294 ( _header->_marker_payload_t ) &= 0x7F;
295 ( _header->_marker_payload_t ) |= ( ( ( value ) << 7 ) /*& 0x80 */ );
296}
297
298void rtp_header_add_setting_payload ( rtp_header_t* _header, uint32_t value )
299{
300 if ( value > 127 )
301 value = 127; /* Well set to maximum */
302
303 ( _header->_marker_payload_t ) &= 0x80;
304 ( _header->_marker_payload_t ) |= ( ( value ) /* & 0x7F */ );
305}
306
307/* Getting values from flags */
308uint8_t rtp_header_get_flag_version ( const rtp_header_t* _header )
309{
310 return ( _header->_flags & 0xd0 ) >> 6;
311}
312
313uint8_t rtp_header_get_flag_padding ( const rtp_header_t* _header )
314{
315 return ( _header->_flags & 0x20 ) >> 5;
316}
317
318uint8_t rtp_header_get_flag_extension ( const rtp_header_t* _header )
319{
320 return ( _header->_flags & 0x10 ) >> 4;
321}
322
323uint8_t rtp_header_get_flag_CSRC_count ( const rtp_header_t* _header )
324{
325 return ( _header->_flags & 0x0f );
326}
327uint8_t rtp_header_get_setting_marker ( const rtp_header_t* _header )
328{
329 return ( _header->_marker_payload_t ) >> 7;
330}
331uint8_t rtp_header_get_setting_payload_type ( const rtp_header_t* _header )
332{
333 /*
334 uint8_t _retu;
335
336 if ( _header->_marker_payload_t >> 7 == 1 ) {
337 _header->_marker_payload_t ^= 0x80;
338 _retu = _header->_marker_payload_t;
339 _header->_marker_payload_t ^= 0x80;
340 } else {
341 _retu = _header->_marker_payload_t;
342 }
343 */
344 /* return to start value
345 return _retu; */
346 return _header->_marker_payload_t & 0x7f;
347}
348
349/* */
350
351
diff --git a/toxrtp/toxrtp_message.h b/toxrtp/toxrtp_message.h
new file mode 100644
index 00000000..8feea5d9
--- /dev/null
+++ b/toxrtp/toxrtp_message.h
@@ -0,0 +1,111 @@
1/* rtp_message.h
2 *
3 * Rtp Message handler. It handles message/header parsing.
4 * Refer to RTP: A Transport Protocol for Real-Time Applications ( RFC 3550 ) for more info. !Red!
5 *
6 *
7 * Copyright (C) 2013 Tox project All Rights Reserved.
8 *
9 * This file is part of Tox.
10 *
11 * Tox is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * Tox is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
23 *
24 */
25
26#ifndef _RTP__MESSAGE_H_
27#define _RTP__MESSAGE_H_
28
29#include "../toxcore/network.h"
30#include "toxrtp_helper.h"
31#include "../toxcore/tox.h"
32/* Defines */
33
34#define _MAX_SEQU_NUM 65535
35
36/* Minimum size */
37#define _MIN_HEADER_LENGTH 12
38#define _MIN_EXT_HEADER_LENGTH 4
39
40/* End of defines */
41
42
43typedef struct rtp_dest_list_s {
44 tox_IP_Port _dest;
45 struct rtp_dest_list_s* next;
46
47} rtp_dest_list_t;
48
49typedef struct rtp_header_s {
50 uint8_t _flags; /* Version(2),Padding(1), Ext(1), Cc(4) */
51 uint8_t _marker_payload_t; /* Marker(1), PlayLoad Type(7) */
52 uint16_t _sequence_number; /* Sequence Number */
53 uint32_t _timestamp; /* Timestamp */
54 uint32_t _ssrc; /* SSRC */
55 uint32_t* _csrc; /* CSRC's table */
56
57 uint32_t _length; /* A little something for allocation */
58
59} rtp_header_t;
60
61typedef struct rtp_ext_header_s {
62 uint16_t _ext_type; /* Extension profile */
63 uint16_t _ext_len; /* Number of extensions */
64 uint32_t* _hd_ext; /* Extension's table */
65
66
67} rtp_ext_header_t;
68
69typedef struct rtp_msg_s {
70 struct rtp_header_s* _header;
71 struct rtp_ext_header_s* _ext_header;
72 uint32_t _header_lenght;
73
74 uint8_t* _data;
75 uint32_t _length;
76 tox_IP_Port _from;
77
78 struct rtp_msg_s* _next;
79} rtp_msg_t;
80
81/* Extracts the header from the payload starting at _from */
82rtp_header_t* rtp_extract_header ( const uint8_t* _payload, size_t _bytes );
83rtp_ext_header_t* rtp_extract_ext_header ( const uint8_t* _payload, size_t _bytes );
84
85
86uint8_t* rtp_add_header ( rtp_header_t* _header, uint8_t* _payload );
87uint8_t* rtp_add_extention_header ( rtp_ext_header_t* _header, uint8_t* _payload );
88
89/* Gets the size of the header _header in bytes */
90size_t rtp_header_get_size ( const rtp_header_t* _header );
91
92void rtp_header_print (const rtp_header_t* _header);
93
94/* Adding flags and settings */
95void rtp_header_add_flag_version ( rtp_header_t* _header, uint32_t value );
96void rtp_header_add_flag_padding ( rtp_header_t* _header, uint32_t value );
97void rtp_header_add_flag_extension ( rtp_header_t* _header, uint32_t value );
98void rtp_header_add_flag_CSRC_count ( rtp_header_t* _header, uint32_t value );
99void rtp_header_add_setting_marker ( rtp_header_t* _header, uint32_t value );
100void rtp_header_add_setting_payload ( rtp_header_t* _header, uint32_t value );
101
102
103/* Getting values from flags and settings */
104uint8_t rtp_header_get_flag_version ( const rtp_header_t* _header );
105uint8_t rtp_header_get_flag_padding ( const rtp_header_t* _header );
106uint8_t rtp_header_get_flag_extension ( const rtp_header_t* _header );
107uint8_t rtp_header_get_flag_CSRC_count ( const rtp_header_t* _header );
108uint8_t rtp_header_get_setting_marker ( const rtp_header_t* _header );
109uint8_t rtp_header_get_setting_payload_type ( const rtp_header_t* _header );
110
111#endif /* _RTP__MESSAGE_H_ */