summaryrefslogtreecommitdiff
path: root/toxav/rtp.c
diff options
context:
space:
mode:
authormannol <eniz_vukovic@hotmail.com>2015-04-13 01:45:53 +0200
committermannol <eniz_vukovic@hotmail.com>2015-04-13 01:45:53 +0200
commit2465f486acd90ed8395c8a83a13af09ecd024c98 (patch)
tree4abe53d39eb07a45e5ed4d8894b7ae038e2bb705 /toxav/rtp.c
parentb2d88a4544a81a217db18b60d91a44d85821db3d (diff)
Started custom RTCP
Diffstat (limited to 'toxav/rtp.c')
-rw-r--r--toxav/rtp.c589
1 files changed, 318 insertions, 271 deletions
diff --git a/toxav/rtp.c b/toxav/rtp.c
index e5f45310..77fce056 100644
--- a/toxav/rtp.c
+++ b/toxav/rtp.c
@@ -28,9 +28,9 @@
28 28
29#include "rtp.h" 29#include "rtp.h"
30#include <stdlib.h> 30#include <stdlib.h>
31void queue_message(RTPSession *_session, RTPMessage *_msg);
32 31
33#define size_32 4 32#define size_32 4
33#define RTCP_REPORT_INTERVAL_MS 500
34 34
35#define ADD_FLAG_VERSION(_h, _v) do { ( _h->flags ) &= 0x3F; ( _h->flags ) |= ( ( ( _v ) << 6 ) & 0xC0 ); } while(0) 35#define ADD_FLAG_VERSION(_h, _v) do { ( _h->flags ) &= 0x3F; ( _h->flags ) |= ( ( ( _v ) << 6 ) & 0xC0 ); } while(0)
36#define ADD_FLAG_PADDING(_h, _v) do { if ( _v > 0 ) _v = 1; ( _h->flags ) &= 0xDF; ( _h->flags ) |= ( ( ( _v ) << 5 ) & 0x20 ); } while(0) 36#define ADD_FLAG_PADDING(_h, _v) do { if ( _v > 0 ) _v = 1; ( _h->flags ) &= 0xDF; ( _h->flags ) |= ( ( ( _v ) << 5 ) & 0x20 ); } while(0)
@@ -46,24 +46,236 @@ void queue_message(RTPSession *_session, RTPMessage *_msg);
46#define GET_SETTING_MARKER(_h) (( _h->marker_payloadt ) >> 7) 46#define GET_SETTING_MARKER(_h) (( _h->marker_payloadt ) >> 7)
47#define GET_SETTING_PAYLOAD(_h) ((_h->marker_payloadt) & 0x7f) 47#define GET_SETTING_PAYLOAD(_h) ((_h->marker_payloadt) & 0x7f)
48 48
49/** 49
50 * Checks if message came in late. 50typedef struct {
51 */ 51 uint64_t timestamp; /* in ms */
52static int check_late_message (RTPSession *session, RTPMessage *msg) 52
53 uint32_t packets_missing;
54 uint32_t expected_packets;
55 /* ... other stuff in the future */
56} RTCPReport;
57
58typedef struct RTCPSession_s {
59 uint8_t prefix;
60 uint64_t last_sent_report_ts;
61 uint32_t last_missing_packets;
62 uint32_t last_expected_packets;
63
64 RingBuffer* pl_stats; /* Packet loss stats over time */
65} RTCPSession;
66
67
68
69/* queue_message() is defined in codec.c */
70void queue_message(RTPSession *session, RTPMessage *msg);
71RTPHeader *parse_header_in ( const uint8_t *payload, int length );
72RTPExtHeader *parse_ext_header_in ( const uint8_t *payload, uint16_t length );
73RTPMessage *msg_parse ( const uint8_t *data, int length );
74uint8_t *parse_header_out ( const RTPHeader* header, uint8_t* payload );
75uint8_t *parse_ext_header_out ( const RTPExtHeader* header, uint8_t* payload );
76void build_header ( RTPSession* session, RTPHeader* header );
77void send_rtcp_report ( RTCPSession* session, Messenger* m, int32_t friendnumber );
78int handle_rtp_packet ( Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length, void *object );
79int handle_rtcp_packet ( Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length, void *object );
80
81
82
83
84RTPSession *rtp_new ( int payload_type, Messenger *messenger, int friend_num )
53{ 85{
54 /* 86 RTPSession *retu = calloc(1, sizeof(RTPSession));
55 * Check Sequence number. If this new msg has lesser number then the session->rsequnum 87
56 * it shows that the message came in late. Also check timestamp to be 100% certain. 88 if ( !retu ) {
57 * 89 LOGGER_WARNING("Alloc failed! Program might misbehave!");
58 */ 90 return NULL;
59 return ( msg->header->sequnum < session->rsequnum && msg->header->timestamp < session->timestamp ) ? 0 : -1; 91 }
92
93 retu->version = RTP_VERSION; /* It's always 2 */
94 retu->padding = 0; /* If some additional data is needed about the packet */
95 retu->extension = 0; /* If extension to header is needed */
96 retu->cc = 1; /* Amount of contributors */
97 retu->csrc = NULL; /* Container */
98 retu->ssrc = random_int();
99 retu->marker = 0;
100 retu->payload_type = payload_type % 128;
101
102 retu->m = messenger;
103 retu->dest = friend_num;
104 retu->rsequnum = retu->sequnum = 0;
105 retu->ext_header = NULL; /* When needed allocate */
106
107 if ( !(retu->csrc = calloc(1, sizeof(uint32_t))) ) {
108 LOGGER_WARNING("Alloc failed! Program might misbehave!");
109 free(retu);
110 return NULL;
111 }
112
113 retu->csrc[0] = retu->ssrc; /* Set my ssrc to the list receive */
114
115 /* Also set payload type as prefix */
116 retu->prefix = payload_type;
117
118
119 /* Initialize rtcp session */
120 if (!(retu->rtcp = calloc(1, sizeof(RTCPSession)))) {
121 LOGGER_WARNING("Alloc failed! Program might misbehave!");
122 free(retu->csrc);
123 free(retu);
124 return NULL;
125 }
126
127 retu->rtcp->prefix = 222 + payload_type % 192;
128 retu->rtcp->pl_stats = rb_new(4);
129
130 return retu;
60} 131}
132void rtp_kill ( RTPSession *session )
133{
134 if ( !session ) return;
61 135
136 rtp_stop_receiving (session);
62 137
63/** 138 free ( session->ext_header );
64 * Extracts header from payload. 139 free ( session->csrc );
65 */ 140
66RTPHeader *extract_header ( const uint8_t *payload, int length ) 141 void* t;
142 while (!rb_empty(session->rtcp->pl_stats)) {
143 rb_read(session->rtcp->pl_stats, (void**) &t);
144 free(t);
145 }
146 rb_free(session->rtcp->pl_stats);
147
148 LOGGER_DEBUG("Terminated RTP session: %p", session);
149
150 /* And finally free session */
151 free ( session );
152}
153void rtp_do(RTPSession *session)
154{
155 if (!session || !session->rtcp)
156 return;
157
158 if (current_time_monotonic() - session->rtcp->last_sent_report_ts >= RTCP_REPORT_INTERVAL_MS) {
159 send_rtcp_report(session->rtcp, session->m, session->dest);
160 }
161
162 if (rb_full(session->rtcp->pl_stats)) {
163 RTCPReport* reports[4];
164
165 int i = 0;
166 for (; rb_read(session->rtcp->pl_stats, (void**) reports + i); i++);
167
168 /* Check for timed out reports (> 6 sec) */
169 uint64_t now = current_time_monotonic();
170 for (i = 0; i < 4 && now - reports[i]->timestamp < 6000; i ++);
171 for (; i < 4; i ++) {
172 rb_write(session->rtcp->pl_stats, reports[i]);
173 reports[i] = NULL;
174 }
175 if (!rb_empty(session->rtcp->pl_stats)) {
176 for (i = 0; reports[i] != NULL; i ++)
177 free(reports[i]);
178 return; /* As some reports are timed out, we need more... */
179 }
180
181 /* We have 4 on-time reports so we can proceed */
182 uint32_t quality_loss = 0;
183 for (i = 0; i < 4; i++) {
184 uint32_t idx = reports[i]->packets_missing * 100 / reports[i]->expected_packets;
185 quality_loss += idx;
186 }
187
188 if (quality_loss > 40) {
189 LOGGER_DEBUG("Packet loss detected");
190 }
191 }
192}
193int rtp_start_receiving(RTPSession* session)
194{
195 if (session == NULL)
196 return -1;
197
198 if (custom_lossy_packet_registerhandler(session->m, session->dest, session->prefix,
199 handle_rtp_packet, session) == -1) {
200 LOGGER_WARNING("Failed to register rtp receive handler");
201 return -1;
202 }
203 if (custom_lossy_packet_registerhandler(session->m, session->dest, session->rtcp->prefix,
204 handle_rtcp_packet, session->rtcp) == -1) {
205 LOGGER_WARNING("Failed to register rtcp receive handler");
206 custom_lossy_packet_registerhandler(session->m, session->dest, session->prefix, NULL, NULL);
207 return -1;
208 }
209
210 return 0;
211}
212int rtp_stop_receiving(RTPSession* session)
213{
214 if (session == NULL)
215 return -1;
216
217 custom_lossy_packet_registerhandler(session->m, session->dest, session->prefix, NULL, NULL);
218 custom_lossy_packet_registerhandler(session->m, session->dest, session->rtcp->prefix, NULL, NULL); /* RTCP */
219
220 return 0;
221}
222int rtp_send_msg ( RTPSession *session, const uint8_t *data, uint16_t length )
223{
224 if ( !session ) {
225 LOGGER_WARNING("No session!");
226 return -1;
227 }
228
229 uint8_t parsed[MAX_RTP_SIZE];
230 uint8_t *it;
231
232 RTPHeader header[1];
233 build_header(session, header);
234
235 uint32_t parsed_len = length + header->length + 1;
236
237 parsed[0] = session->prefix;
238
239 it = parse_header_out ( header, parsed + 1 );
240
241 if ( session->ext_header ) {
242 parsed_len += ( 4 /* Minimum ext header len */ + session->ext_header->length * size_32 );
243 it = parse_ext_header_out ( session->ext_header, it );
244 }
245
246 memcpy ( it, data, length );
247
248 if ( -1 == send_custom_lossy_packet(session->m, session->dest, parsed, parsed_len) ) {
249 LOGGER_WARNING("Failed to send full packet (len: %d)! std error: %s", length, strerror(errno));
250 return -1;
251 }
252
253 /* Set sequ number */
254 session->sequnum = session->sequnum >= MAX_SEQU_NUM ? 0 : session->sequnum + 1;
255 return 0;
256}
257void rtp_free_msg ( RTPSession *session, RTPMessage *msg )
258{
259 if ( !session ) {
260 if ( msg->ext_header ) {
261 free ( msg->ext_header->table );
262 free ( msg->ext_header );
263 }
264 } else {
265 if ( msg->ext_header && session->ext_header != msg->ext_header ) {
266 free ( msg->ext_header->table );
267 free ( msg->ext_header );
268 }
269 }
270
271 free ( msg->header );
272 free ( msg );
273}
274
275
276
277
278RTPHeader *parse_header_in ( const uint8_t *payload, int length )
67{ 279{
68 if ( !payload || !length ) { 280 if ( !payload || !length ) {
69 LOGGER_WARNING("No payload to extract!"); 281 LOGGER_WARNING("No payload to extract!");
@@ -111,8 +323,6 @@ RTPHeader *extract_header ( const uint8_t *payload, int length )
111 return NULL; 323 return NULL;
112 } 324 }
113 325
114 memset(retu->csrc, 0, 16 * sizeof (uint32_t));
115
116 retu->marker_payloadt = *it; 326 retu->marker_payloadt = *it;
117 ++it; 327 ++it;
118 retu->length = total; 328 retu->length = total;
@@ -125,7 +335,6 @@ RTPHeader *extract_header ( const uint8_t *payload, int length )
125 retu->ssrc = ntohl(retu->ssrc); 335 retu->ssrc = ntohl(retu->ssrc);
126 336
127 uint8_t x; 337 uint8_t x;
128
129 for ( x = 0; x < cc; x++ ) { 338 for ( x = 0; x < cc; x++ ) {
130 it += 4; 339 it += 4;
131 memcpy(&retu->csrc[x], it, sizeof(retu->csrc[x])); 340 memcpy(&retu->csrc[x], it, sizeof(retu->csrc[x]));
@@ -134,11 +343,7 @@ RTPHeader *extract_header ( const uint8_t *payload, int length )
134 343
135 return retu; 344 return retu;
136} 345}
137 346RTPExtHeader *parse_ext_header_in ( const uint8_t *payload, uint16_t length )
138/**
139 * Extracts external header from payload. Must be called AFTER extract_header()!
140 */
141RTPExtHeader *extract_ext_header ( const uint8_t *payload, uint16_t length )
142{ 347{
143 const uint8_t *it = payload; 348 const uint8_t *it = payload;
144 349
@@ -182,11 +387,47 @@ RTPExtHeader *extract_ext_header ( const uint8_t *payload, uint16_t length )
182 387
183 return retu; 388 return retu;
184} 389}
390RTPMessage *msg_parse ( const uint8_t *data, int length )
391{
392 RTPMessage *retu = calloc(1, sizeof (RTPMessage));
185 393
186/** 394 retu->header = parse_header_in ( data, length ); /* It allocates memory and all */
187 * Adds header to payload. Make sure _payload_ has enough space. 395
188 */ 396 if ( !retu->header ) {
189uint8_t *add_header ( RTPHeader *header, uint8_t *payload ) 397 LOGGER_WARNING("Header failed to extract!");
398 free(retu);
399 return NULL;
400 }
401
402 uint16_t from_pos = retu->header->length;
403 retu->length = length - from_pos;
404
405 if ( GET_FLAG_EXTENSION ( retu->header ) ) {
406 retu->ext_header = parse_ext_header_in ( data + from_pos, length );
407
408 if ( retu->ext_header ) {
409 retu->length -= ( 4 /* Minimum ext header len */ + retu->ext_header->length * size_32 );
410 from_pos += ( 4 /* Minimum ext header len */ + retu->ext_header->length * size_32 );
411 } else { /* Error */
412 LOGGER_WARNING("Ext Header failed to extract!");
413 rtp_free_msg(NULL, retu);
414 return NULL;
415 }
416 } else {
417 retu->ext_header = NULL;
418 }
419
420 if ( length - from_pos <= MAX_RTP_SIZE )
421 memcpy ( retu->data, data + from_pos, length - from_pos );
422 else {
423 LOGGER_WARNING("Invalid length!");
424 rtp_free_msg(NULL, retu);
425 return NULL;
426 }
427
428 return retu;
429}
430uint8_t *parse_header_out ( const RTPHeader *header, uint8_t *payload )
190{ 431{
191 uint8_t cc = GET_FLAG_CSRCC ( header ); 432 uint8_t cc = GET_FLAG_CSRCC ( header );
192 uint8_t *it = payload; 433 uint8_t *it = payload;
@@ -223,11 +464,7 @@ uint8_t *add_header ( RTPHeader *header, uint8_t *payload )
223 464
224 return it + 4; 465 return it + 4;
225} 466}
226 467uint8_t *parse_ext_header_out ( const RTPExtHeader *header, uint8_t *payload )
227/**
228 * Adds extension header to payload. Make sure _payload_ has enough space.
229 */
230uint8_t *add_ext_header ( RTPExtHeader *header, uint8_t *payload )
231{ 468{
232 uint8_t *it = payload; 469 uint8_t *it = payload;
233 uint16_t length; 470 uint16_t length;
@@ -242,9 +479,7 @@ uint8_t *add_ext_header ( RTPExtHeader *header, uint8_t *payload )
242 it -= 2; /* Return to 0 position */ 479 it -= 2; /* Return to 0 position */
243 480
244 if ( header->table ) { 481 if ( header->table ) {
245
246 uint16_t x; 482 uint16_t x;
247
248 for ( x = 0; x < header->length; x++ ) { 483 for ( x = 0; x < header->length; x++ ) {
249 it += 4; 484 it += 4;
250 entry = htonl(header->table[x]); 485 entry = htonl(header->table[x]);
@@ -254,92 +489,45 @@ uint8_t *add_ext_header ( RTPExtHeader *header, uint8_t *payload )
254 489
255 return it + 4; 490 return it + 4;
256} 491}
257 492void build_header ( RTPSession *session, RTPHeader *header )
258/**
259 * Builds header from control session values.
260 */
261RTPHeader *build_header ( RTPSession *session )
262{ 493{
263 RTPHeader *retu = calloc ( 1, sizeof (RTPHeader) ); 494 ADD_FLAG_VERSION ( header, session->version );
264 495 ADD_FLAG_PADDING ( header, session->padding );
265 if ( !retu ) { 496 ADD_FLAG_EXTENSION ( header, session->extension );
266 LOGGER_WARNING("Alloc failed! Program might misbehave!"); 497 ADD_FLAG_CSRCC ( header, session->cc );
267 return NULL; 498 ADD_SETTING_MARKER ( header, session->marker );
268 } 499 ADD_SETTING_PAYLOAD ( header, session->payload_type );
269
270 ADD_FLAG_VERSION ( retu, session->version );
271 ADD_FLAG_PADDING ( retu, session->padding );
272 ADD_FLAG_EXTENSION ( retu, session->extension );
273 ADD_FLAG_CSRCC ( retu, session->cc );
274 ADD_SETTING_MARKER ( retu, session->marker );
275 ADD_SETTING_PAYLOAD ( retu, session->payload_type );
276 500
277 retu->sequnum = session->sequnum; 501 header->sequnum = session->sequnum;
278 retu->timestamp = current_time_monotonic(); /* milliseconds */ 502 header->timestamp = current_time_monotonic(); /* milliseconds */
279 retu->ssrc = session->ssrc; 503 header->ssrc = session->ssrc;
280 504
281 int i; 505 int i;
282
283 for ( i = 0; i < session->cc; i++ ) 506 for ( i = 0; i < session->cc; i++ )
284 retu->csrc[i] = session->csrc[i]; 507 header->csrc[i] = session->csrc[i];
285
286 retu->length = 12 /* Minimum header len */ + ( session->cc * size_32 );
287 508
288 return retu; 509 header->length = 12 /* Minimum header len */ + ( session->cc * size_32 );
289} 510}
290 511void send_rtcp_report(RTCPSession* session, Messenger* m, int32_t friendnumber)
291
292/**
293 * Parses data into RTPMessage struct. Stores headers separately from the payload data
294 * and so the length variable is set accordingly.
295 */
296RTPMessage *msg_parse ( const uint8_t *data, int length )
297{ 512{
298 RTPMessage *retu = calloc(1, sizeof (RTPMessage)); 513 if (session->last_expected_packets == 0)
299 514 return;
300 retu->header = extract_header ( data, length ); /* It allocates memory and all */ 515
301 516 uint8_t parsed[9];
302 if ( !retu->header ) { 517 parsed[0] = session->prefix;
303 LOGGER_WARNING("Header failed to extract!"); 518
304 free(retu); 519 uint32_t packets_missing = htonl(session->last_missing_packets);
305 return NULL; 520 uint32_t expected_packets = htonl(session->last_expected_packets);
306 } 521
307 522 memcpy(parsed + 1, &packets_missing, 4);
308 uint16_t from_pos = retu->header->length; 523 memcpy(parsed + 5, &expected_packets, 4);
309 retu->length = length - from_pos; 524
310 525 if (-1 == send_custom_lossy_packet(m, friendnumber, parsed, sizeof(parsed)))
311 526 LOGGER_WARNING("Failed to send full packet (len: %d)! std error: %s", sizeof(parsed), strerror(errno));
312 527 else
313 if ( GET_FLAG_EXTENSION ( retu->header ) ) { 528 session->last_sent_report_ts = current_time_monotonic();
314 retu->ext_header = extract_ext_header ( data + from_pos, length );
315
316 if ( retu->ext_header ) {
317 retu->length -= ( 4 /* Minimum ext header len */ + retu->ext_header->length * size_32 );
318 from_pos += ( 4 /* Minimum ext header len */ + retu->ext_header->length * size_32 );
319 } else { /* Error */
320 LOGGER_WARNING("Ext Header failed to extract!");
321 rtp_free_msg(NULL, retu);
322 return NULL;
323 }
324 } else {
325 retu->ext_header = NULL;
326 }
327
328 if ( length - from_pos <= MAX_RTP_SIZE )
329 memcpy ( retu->data, data + from_pos, length - from_pos );
330 else {
331 LOGGER_WARNING("Invalid length!");
332 rtp_free_msg(NULL, retu);
333 return NULL;
334 }
335
336 return retu;
337} 529}
338 530int handle_rtp_packet ( Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length, void *object )
339/**
340 * Callback for networking core.
341 */
342int rtp_handle_packet ( Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length, void *object )
343{ 531{
344 RTPSession *session = object; 532 RTPSession *session = object;
345 RTPMessage *msg; 533 RTPMessage *msg;
@@ -357,178 +545,37 @@ int rtp_handle_packet ( Messenger *m, int32_t friendnumber, const uint8_t *data,
357 } 545 }
358 546
359 /* Check if message came in late */ 547 /* Check if message came in late */
360 if ( check_late_message(session, msg) < 0 ) { /* Not late */ 548 if ( msg->header->sequnum > session->rsequnum && msg->header->timestamp > session->rtimestamp ) {
549 /* Not late */
361 session->rsequnum = msg->header->sequnum; 550 session->rsequnum = msg->header->sequnum;
362 session->timestamp = msg->header->timestamp; 551 session->rtimestamp = msg->header->timestamp;
363 } 552 }
364 553
365 queue_message(session, msg); 554 queue_message(session, msg);
366 return 0; 555 return 0;
367} 556}
368 557int handle_rtcp_packet ( Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length, void *object )
369/**
370 * Allocate message and store data there
371 */
372RTPMessage *rtp_new_message ( RTPSession *session, const uint8_t *data, uint32_t length )
373{ 558{
374 if ( !session ) { 559 if (length < 9)
375 LOGGER_WARNING("No session!"); 560 return -1;
376 return NULL;
377 }
378
379 uint8_t *from_pos;
380 RTPMessage *retu = calloc(1, sizeof (RTPMessage));
381
382 if ( !retu ) {
383 LOGGER_WARNING("Alloc failed! Program might misbehave!");
384 return NULL;
385 }
386
387 /* Sets header values and copies the extension header in retu */
388 retu->header = build_header ( session ); /* It allocates memory and all */
389 retu->ext_header = session->ext_header;
390
391
392 uint32_t total_length = length + retu->header->length + 1;
393
394 retu->data[0] = session->prefix;
395
396 if ( retu->ext_header ) {
397 total_length += ( 4 /* Minimum ext header len */ + retu->ext_header->length * size_32 );
398
399 from_pos = add_header ( retu->header, retu->data + 1 );
400 from_pos = add_ext_header ( retu->ext_header, from_pos + 1 );
401 } else {
402 from_pos = add_header ( retu->header, retu->data + 1 );
403 }
404
405 /*
406 * Parses the extension header into the message
407 * Of course if any
408 */
409
410 /* Appends data on to retu->data */
411 memcpy ( from_pos, data, length );
412
413 retu->length = total_length;
414
415 return retu;
416}
417
418
419
420RTPSession *rtp_new ( int payload_type, Messenger *messenger, int friend_num )
421{
422 RTPSession *retu = calloc(1, sizeof(RTPSession));
423
424 if ( !retu ) {
425 LOGGER_WARNING("Alloc failed! Program might misbehave!");
426 return NULL;
427 }
428
429 retu->version = RTP_VERSION; /* It's always 2 */
430 retu->padding = 0; /* If some additional data is needed about the packet */
431 retu->extension = 0; /* If extension to header is needed */
432 retu->cc = 1; /* Amount of contributors */
433 retu->csrc = NULL; /* Container */
434 retu->ssrc = random_int();
435 retu->marker = 0;
436 retu->payload_type = payload_type % 128;
437
438 retu->dest = friend_num;
439
440 retu->rsequnum = retu->sequnum = 0;
441
442 retu->ext_header = NULL; /* When needed allocate */
443
444
445 if ( !(retu->csrc = calloc(1, sizeof (uint32_t))) ) {
446 LOGGER_WARNING("Alloc failed! Program might misbehave!");
447 free(retu);
448 return NULL;
449 }
450
451 retu->csrc[0] = retu->ssrc; /* Set my ssrc to the list receive */
452
453 /* Also set payload type as prefix */
454 retu->prefix = payload_type;
455
456 retu->m = messenger;
457 /*
458 *
459 */
460 return retu;
461}
462
463void rtp_kill ( RTPSession *session )
464{
465 if ( !session ) return;
466
467 rtp_stop_receiving (session);
468
469 free ( session->ext_header );
470 free ( session->csrc );
471
472 LOGGER_DEBUG("Terminated RTP session: %p", session);
473
474 /* And finally free session */
475 free ( session );
476}
477
478int rtp_start_receiving(RTPSession* session)
479{
480 if (session == NULL)
481 return 0;
482 561
483 LOGGER_DEBUG("Registering packet handler: pt: %d; friend: %d", session->prefix, session->dest); 562 RTCPSession* session = object;
484 return custom_lossy_packet_registerhandler(session->m, session->dest, session->prefix, 563 RTCPReport* report = malloc(sizeof(RTCPReport));
485 rtp_handle_packet, session);
486}
487
488int rtp_stop_receiving(RTPSession* session)
489{
490 if (session == NULL)
491 return 0;
492 564
493 LOGGER_DEBUG("Unregistering packet handler: pt: %d; friend: %d", session->prefix, session->dest); 565 memcpy(&report->packets_missing, data + 1, 4);
494 return custom_lossy_packet_registerhandler(session->m, session->dest, session->prefix, 566 memcpy(&report->expected_packets, data + 5, 4);
495 NULL, NULL);
496}
497
498int rtp_send_msg ( RTPSession *session, const uint8_t *data, uint16_t length )
499{
500 RTPMessage *msg = rtp_new_message (session, data, length);
501 567
502 if ( !msg ) return -1; 568 report->packets_missing = ntohl(report->packets_missing);
569 report->expected_packets = ntohl(report->expected_packets);
503 570
504 if ( -1 == send_custom_lossy_packet(session->m, session->dest, msg->data, msg->length) ) { 571 /* This would cause undefined behaviour */
505 LOGGER_WARNING("Failed to send full packet (len: %d)! std error: %s", length, strerror(errno)); 572 if (report->expected_packets == 0) {
506 rtp_free_msg ( session, msg ); 573 free(report);
507 return -1; 574 return 0;
508 } 575 }
509 576
577 report->timestamp = current_time_monotonic();
510 578
511 /* Set sequ number */ 579 free(rb_write(session->pl_stats, report));
512 session->sequnum = session->sequnum >= MAX_SEQU_NUM ? 0 : session->sequnum + 1;
513 rtp_free_msg ( session, msg );
514
515 return 0; 580 return 0;
516} 581} \ No newline at end of file
517
518void rtp_free_msg ( RTPSession *session, RTPMessage *msg )
519{
520 if ( !session ) {
521 if ( msg->ext_header ) {
522 free ( msg->ext_header->table );
523 free ( msg->ext_header );
524 }
525 } else {
526 if ( msg->ext_header && session->ext_header != msg->ext_header ) {
527 free ( msg->ext_header->table );
528 free ( msg->ext_header );
529 }
530 }
531
532 free ( msg->header );
533 free ( msg );
534}