diff options
author | mannol <eniz_vukovic@hotmail.com> | 2015-04-26 00:31:03 +0200 |
---|---|---|
committer | mannol <eniz_vukovic@hotmail.com> | 2015-04-26 00:31:03 +0200 |
commit | 144fc94d6987c8c6f74d8024af5a5c1738fe4678 (patch) | |
tree | bc5ad70ea24dafb8e358911ba118fc599f3f9999 /toxav/rtp.c | |
parent | 1bfd93e64a2a6d3bf9c90a9aa89abd29f3d826a7 (diff) |
Almost done
Diffstat (limited to 'toxav/rtp.c')
-rw-r--r-- | toxav/rtp.c | 276 |
1 files changed, 144 insertions, 132 deletions
diff --git a/toxav/rtp.c b/toxav/rtp.c index 9657da67..a48eba20 100644 --- a/toxav/rtp.c +++ b/toxav/rtp.c | |||
@@ -29,6 +29,7 @@ | |||
29 | 29 | ||
30 | #include "rtp.h" | 30 | #include "rtp.h" |
31 | #include <stdlib.h> | 31 | #include <stdlib.h> |
32 | #include <assert.h> | ||
32 | 33 | ||
33 | #define size_32 4 | 34 | #define size_32 4 |
34 | #define RTCP_REPORT_INTERVAL_MS 500 | 35 | #define RTCP_REPORT_INTERVAL_MS 500 |
@@ -37,8 +38,8 @@ | |||
37 | #define ADD_FLAG_PADDING(_h, _v) do { if ( _v > 0 ) _v = 1; ( _h->flags ) &= 0xDF; ( _h->flags ) |= ( ( ( _v ) << 5 ) & 0x20 ); } while(0) | 38 | #define ADD_FLAG_PADDING(_h, _v) do { if ( _v > 0 ) _v = 1; ( _h->flags ) &= 0xDF; ( _h->flags ) |= ( ( ( _v ) << 5 ) & 0x20 ); } while(0) |
38 | #define ADD_FLAG_EXTENSION(_h, _v) do { if ( _v > 0 ) _v = 1; ( _h->flags ) &= 0xEF;( _h->flags ) |= ( ( ( _v ) << 4 ) & 0x10 ); } while(0) | 39 | #define ADD_FLAG_EXTENSION(_h, _v) do { if ( _v > 0 ) _v = 1; ( _h->flags ) &= 0xEF;( _h->flags ) |= ( ( ( _v ) << 4 ) & 0x10 ); } while(0) |
39 | #define ADD_FLAG_CSRCC(_h, _v) do { ( _h->flags ) &= 0xF0; ( _h->flags ) |= ( ( _v ) & 0x0F ); } while(0) | 40 | #define ADD_FLAG_CSRCC(_h, _v) do { ( _h->flags ) &= 0xF0; ( _h->flags ) |= ( ( _v ) & 0x0F ); } while(0) |
40 | #define ADD_SETTING_MARKER(_h, _v) do { if ( _v > 1 ) _v = 1; ( _h->marker_payloadt ) &= 0x7F; ( _h->marker_payloadt ) |= ( ( ( _v ) << 7 ) /*& 0x80 */ ); } while(0) | 41 | #define ADD_SETTING_MARKER(_h, _v) do { ( _h->marker_payloadt ) &= 0x7F; ( _h->marker_payloadt ) |= ( ( ( _v ) << 7 ) /*& 0x80 */ ); } while(0) |
41 | #define ADD_SETTING_PAYLOAD(_h, _v) do { if ( _v > 127 ) _v = 127; ( _h->marker_payloadt ) &= 0x80; ( _h->marker_payloadt ) |= ( ( _v ) /* & 0x7F */ ); } while(0) | 42 | #define ADD_SETTING_PAYLOAD(_h, _v) do { ( _h->marker_payloadt ) &= 0x80; ( _h->marker_payloadt ) |= ( ( _v ) /* & 0x7F */ ); } while(0) |
42 | 43 | ||
43 | #define GET_FLAG_VERSION(_h) (( _h->flags & 0xd0 ) >> 6) | 44 | #define GET_FLAG_VERSION(_h) (( _h->flags & 0xd0 ) >> 6) |
44 | #define GET_FLAG_PADDING(_h) (( _h->flags & 0x20 ) >> 5) | 45 | #define GET_FLAG_PADDING(_h) (( _h->flags & 0x20 ) >> 5) |
@@ -70,17 +71,19 @@ typedef struct RTCPSession_s { | |||
70 | 71 | ||
71 | RTPHeader *parse_header_in ( const uint8_t *payload, int length ); | 72 | RTPHeader *parse_header_in ( const uint8_t *payload, int length ); |
72 | RTPExtHeader *parse_ext_header_in ( const uint8_t *payload, uint16_t length ); | 73 | RTPExtHeader *parse_ext_header_in ( const uint8_t *payload, uint16_t length ); |
73 | RTPMessage *msg_parse ( const uint8_t *data, int length ); | ||
74 | uint8_t *parse_header_out ( const RTPHeader* header, uint8_t* payload ); | 74 | uint8_t *parse_header_out ( const RTPHeader* header, uint8_t* payload ); |
75 | uint8_t *parse_ext_header_out ( const RTPExtHeader* header, uint8_t* payload ); | 75 | uint8_t *parse_ext_header_out ( const RTPExtHeader* header, uint8_t* payload ); |
76 | void build_header ( RTPSession* session, RTPHeader* header ); | ||
77 | void send_rtcp_report ( RTCPSession* session, Messenger* m, uint32_t friendnumber ); | ||
78 | int handle_rtp_packet ( Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t length, void *object ); | 76 | int handle_rtp_packet ( Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t length, void *object ); |
79 | int handle_rtcp_packet ( Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t length, void *object ); | 77 | int handle_rtcp_packet ( Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t length, void *object ); |
78 | void send_rtcp_report ( RTCPSession* session, Messenger* m, uint32_t friendnumber ); | ||
80 | 79 | ||
81 | 80 | ||
82 | RTPSession *rtp_new ( int payload_type, Messenger *messenger, int friend_num ) | 81 | RTPSession *rtp_new ( int payload_type, Messenger *messenger, int friend_num, void* cs, int (*mcb) (void*, RTPMessage*) ) |
83 | { | 82 | { |
83 | assert(mcb); | ||
84 | assert(cs); | ||
85 | assert(messenger); | ||
86 | |||
84 | RTPSession *retu = calloc(1, sizeof(RTPSession)); | 87 | RTPSession *retu = calloc(1, sizeof(RTPSession)); |
85 | 88 | ||
86 | if ( !retu ) { | 89 | if ( !retu ) { |
@@ -107,6 +110,8 @@ RTPSession *rtp_new ( int payload_type, Messenger *messenger, int friend_num ) | |||
107 | /* Also set payload type as prefix */ | 110 | /* Also set payload type as prefix */ |
108 | retu->prefix = payload_type; | 111 | retu->prefix = payload_type; |
109 | 112 | ||
113 | retu->cs = cs; | ||
114 | retu->mcb = mcb; | ||
110 | 115 | ||
111 | /* Initialize rtcp session */ | 116 | /* Initialize rtcp session */ |
112 | if (!(retu->rtcp_session = calloc(1, sizeof(RTCPSession)))) { | 117 | if (!(retu->rtcp_session = calloc(1, sizeof(RTCPSession)))) { |
@@ -120,6 +125,14 @@ RTPSession *rtp_new ( int payload_type, Messenger *messenger, int friend_num ) | |||
120 | retu->rtcp_session->pl_stats = rb_new(4); | 125 | retu->rtcp_session->pl_stats = rb_new(4); |
121 | retu->rtcp_session->rtp_session = retu; | 126 | retu->rtcp_session->rtp_session = retu; |
122 | 127 | ||
128 | if (-1 == rtp_start_receiving(retu)) { | ||
129 | LOGGER_WARNING("Failed to start rtp receiving mode"); | ||
130 | free(retu->rtcp_session); | ||
131 | free(retu->csrc); | ||
132 | free(retu); | ||
133 | return NULL; | ||
134 | } | ||
135 | |||
123 | return retu; | 136 | return retu; |
124 | } | 137 | } |
125 | void rtp_kill ( RTPSession *session ) | 138 | void rtp_kill ( RTPSession *session ) |
@@ -156,11 +169,12 @@ void rtp_do(RTPSession *session) | |||
156 | RTCPReport* reports[4]; | 169 | RTCPReport* reports[4]; |
157 | 170 | ||
158 | int i = 0; | 171 | int i = 0; |
159 | for (; rb_read(session->rtcp_session->pl_stats, (void**) reports + i); i++); | 172 | for (; i < 4; i++) |
173 | rb_read(session->rtcp_session->pl_stats, (void**) reports + i); | ||
160 | 174 | ||
161 | /* Check for timed out reports (> 6 sec) */ | 175 | /* Check for timed out reports (> 6 sec) */ |
162 | uint64_t now = current_time_monotonic(); | 176 | uint64_t now = current_time_monotonic(); |
163 | for (i = 0; i < 4 && now - reports[i]->timestamp < 6000; i ++); | 177 | for (i = 0; i < 4 && (now - reports[i]->timestamp) < 6000; i ++); |
164 | for (; i < 4; i ++) { | 178 | for (; i < 4; i ++) { |
165 | rb_write(session->rtcp_session->pl_stats, reports[i]); | 179 | rb_write(session->rtcp_session->pl_stats, reports[i]); |
166 | reports[i] = NULL; | 180 | reports[i] = NULL; |
@@ -168,18 +182,18 @@ void rtp_do(RTPSession *session) | |||
168 | if (!rb_empty(session->rtcp_session->pl_stats)) { | 182 | if (!rb_empty(session->rtcp_session->pl_stats)) { |
169 | for (i = 0; reports[i] != NULL; i ++) | 183 | for (i = 0; reports[i] != NULL; i ++) |
170 | free(reports[i]); | 184 | free(reports[i]); |
171 | return; /* As some reports are timed out, we need more... */ | 185 | return; /* As some reports are timed out, we need more */ |
172 | } | 186 | } |
173 | 187 | ||
174 | /* We have 4 on-time reports so we can proceed */ | 188 | /* We have 4 on-time reports so we can proceed */ |
175 | uint32_t quality = 100; | 189 | uint32_t quality = 100; |
176 | for (i = 0; i < 4; i++) { | 190 | for (i = 0; i < 4; i++) { |
177 | uint32_t idx = reports[i]->received_packets * 100 / reports[i]->expected_packets; | 191 | uint32_t current = reports[i]->received_packets * 100 / reports[i]->expected_packets; |
178 | quality = MIN(quality, idx); | 192 | quality = MIN(quality, current); |
179 | free(reports[i]); | 193 | free(reports[i]); |
180 | } | 194 | } |
181 | 195 | ||
182 | if (quality <= 70) { | 196 | if (quality <= 90) { |
183 | session->tstate = rtp_StateBad; | 197 | session->tstate = rtp_StateBad; |
184 | LOGGER_WARNING("Stream quality: BAD"); | 198 | LOGGER_WARNING("Stream quality: BAD"); |
185 | } else if (quality >= 99) { | 199 | } else if (quality >= 99) { |
@@ -220,7 +234,7 @@ int rtp_stop_receiving(RTPSession* session) | |||
220 | 234 | ||
221 | return 0; | 235 | return 0; |
222 | } | 236 | } |
223 | int rtp_send_msg ( RTPSession *session, const uint8_t *data, uint16_t length ) | 237 | int rtp_send_data ( RTPSession *session, const uint8_t *data, uint16_t length, bool dummy ) |
224 | { | 238 | { |
225 | if ( !session ) { | 239 | if ( !session ) { |
226 | LOGGER_WARNING("No session!"); | 240 | LOGGER_WARNING("No session!"); |
@@ -231,12 +245,31 @@ int rtp_send_msg ( RTPSession *session, const uint8_t *data, uint16_t length ) | |||
231 | uint8_t *it; | 245 | uint8_t *it; |
232 | 246 | ||
233 | RTPHeader header[1]; | 247 | RTPHeader header[1]; |
234 | build_header(session, header); | 248 | ADD_FLAG_VERSION ( header, session->version ); |
249 | ADD_FLAG_PADDING ( header, session->padding ); | ||
250 | ADD_FLAG_EXTENSION ( header, session->extension ); | ||
251 | ADD_FLAG_CSRCC ( header, session->cc ); | ||
252 | ADD_SETTING_MARKER ( header, session->marker ); | ||
253 | |||
254 | if (dummy) | ||
255 | ADD_SETTING_PAYLOAD ( header, (session->payload_type + 2) % 128 ); | ||
256 | else | ||
257 | ADD_SETTING_PAYLOAD ( header, session->payload_type ); | ||
235 | 258 | ||
259 | header->sequnum = session->sequnum; | ||
260 | header->timestamp = current_time_monotonic(); | ||
261 | header->ssrc = session->ssrc; | ||
262 | |||
263 | int i; | ||
264 | for ( i = 0; i < session->cc; i++ ) | ||
265 | header->csrc[i] = session->csrc[i]; | ||
266 | |||
267 | header->length = 12 /* Minimum header len */ + ( session->cc * size_32 ); | ||
268 | |||
236 | uint32_t parsed_len = length + header->length + 1; | 269 | uint32_t parsed_len = length + header->length + 1; |
270 | assert(parsed_len + (session->ext_header ? session->ext_header->length * size_32 : 0) > MAX_RTP_SIZE ); | ||
237 | 271 | ||
238 | parsed[0] = session->prefix; | 272 | parsed[0] = session->prefix; |
239 | |||
240 | it = parse_header_out ( header, parsed + 1 ); | 273 | it = parse_header_out ( header, parsed + 1 ); |
241 | 274 | ||
242 | if ( session->ext_header ) { | 275 | if ( session->ext_header ) { |
@@ -244,8 +277,7 @@ int rtp_send_msg ( RTPSession *session, const uint8_t *data, uint16_t length ) | |||
244 | it = parse_ext_header_out ( session->ext_header, it ); | 277 | it = parse_ext_header_out ( session->ext_header, it ); |
245 | } | 278 | } |
246 | 279 | ||
247 | memcpy ( it, data, length ); | 280 | memcpy(it, data, length); |
248 | |||
249 | 281 | ||
250 | if ( -1 == send_custom_lossy_packet(session->m, session->friend_id, parsed, parsed_len) ) { | 282 | if ( -1 == send_custom_lossy_packet(session->m, session->friend_id, parsed, parsed_len) ) { |
251 | LOGGER_WARNING("Failed to send full packet (len: %d)! std error: %s", length, strerror(errno)); | 283 | LOGGER_WARNING("Failed to send full packet (len: %d)! std error: %s", length, strerror(errno)); |
@@ -256,18 +288,11 @@ int rtp_send_msg ( RTPSession *session, const uint8_t *data, uint16_t length ) | |||
256 | session->sequnum = session->sequnum >= MAX_SEQU_NUM ? 0 : session->sequnum + 1; | 288 | session->sequnum = session->sequnum >= MAX_SEQU_NUM ? 0 : session->sequnum + 1; |
257 | return 0; | 289 | return 0; |
258 | } | 290 | } |
259 | void rtp_free_msg ( RTPSession *session, RTPMessage *msg ) | 291 | void rtp_free_msg ( RTPMessage *msg ) |
260 | { | 292 | { |
261 | if ( !session ) { | 293 | if ( msg->ext_header ) { |
262 | if ( msg->ext_header ) { | 294 | free ( msg->ext_header->table ); |
263 | free ( msg->ext_header->table ); | 295 | free ( msg->ext_header ); |
264 | free ( msg->ext_header ); | ||
265 | } | ||
266 | } else { | ||
267 | if ( msg->ext_header && session->ext_header != msg->ext_header ) { | ||
268 | free ( msg->ext_header->table ); | ||
269 | free ( msg->ext_header ); | ||
270 | } | ||
271 | } | 296 | } |
272 | 297 | ||
273 | free ( msg->header ); | 298 | free ( msg->header ); |
@@ -389,50 +414,6 @@ RTPExtHeader *parse_ext_header_in ( const uint8_t *payload, uint16_t length ) | |||
389 | 414 | ||
390 | return retu; | 415 | return retu; |
391 | } | 416 | } |
392 | RTPMessage *msg_parse ( const uint8_t *data, int length ) | ||
393 | { | ||
394 | /* TODO: data dynamic, [0] | ||
395 | * TODO: dummy payload type | ||
396 | * TODO: parse header before allocating message | ||
397 | */ | ||
398 | RTPMessage *retu = calloc(1, sizeof (RTPMessage)); | ||
399 | |||
400 | retu->header = parse_header_in ( data, length ); /* It allocates memory and all */ | ||
401 | |||
402 | if ( !retu->header ) { | ||
403 | LOGGER_WARNING("Header failed to extract!"); | ||
404 | free(retu); | ||
405 | return NULL; | ||
406 | } | ||
407 | |||
408 | uint16_t from_pos = retu->header->length; | ||
409 | retu->length = length - from_pos; | ||
410 | |||
411 | if ( GET_FLAG_EXTENSION ( retu->header ) ) { | ||
412 | retu->ext_header = parse_ext_header_in ( data + from_pos, length ); | ||
413 | |||
414 | if ( retu->ext_header ) { | ||
415 | retu->length -= ( 4 /* Minimum ext header len */ + retu->ext_header->length * size_32 ); | ||
416 | from_pos += ( 4 /* Minimum ext header len */ + retu->ext_header->length * size_32 ); | ||
417 | } else { /* Error */ | ||
418 | LOGGER_WARNING("Ext Header failed to extract!"); | ||
419 | rtp_free_msg(NULL, retu); | ||
420 | return NULL; | ||
421 | } | ||
422 | } else { | ||
423 | retu->ext_header = NULL; | ||
424 | } | ||
425 | |||
426 | if ( length - from_pos <= MAX_RTP_SIZE ) | ||
427 | memcpy ( retu->data, data + from_pos, length - from_pos ); | ||
428 | else { | ||
429 | LOGGER_WARNING("Invalid length!"); | ||
430 | rtp_free_msg(NULL, retu); | ||
431 | return NULL; | ||
432 | } | ||
433 | |||
434 | return retu; | ||
435 | } | ||
436 | uint8_t *parse_header_out ( const RTPHeader *header, uint8_t *payload ) | 417 | uint8_t *parse_header_out ( const RTPHeader *header, uint8_t *payload ) |
437 | { | 418 | { |
438 | uint8_t cc = GET_FLAG_CSRCC ( header ); | 419 | uint8_t cc = GET_FLAG_CSRCC ( header ); |
@@ -495,88 +476,95 @@ uint8_t *parse_ext_header_out ( const RTPExtHeader *header, uint8_t *payload ) | |||
495 | 476 | ||
496 | return it + 4; | 477 | return it + 4; |
497 | } | 478 | } |
498 | void build_header ( RTPSession *session, RTPHeader *header ) | ||
499 | { | ||
500 | ADD_FLAG_VERSION ( header, session->version ); | ||
501 | ADD_FLAG_PADDING ( header, session->padding ); | ||
502 | ADD_FLAG_EXTENSION ( header, session->extension ); | ||
503 | ADD_FLAG_CSRCC ( header, session->cc ); | ||
504 | ADD_SETTING_MARKER ( header, session->marker ); | ||
505 | ADD_SETTING_PAYLOAD ( header, session->payload_type ); | ||
506 | |||
507 | header->sequnum = session->sequnum; | ||
508 | header->timestamp = current_time_monotonic(); /* milliseconds */ | ||
509 | header->ssrc = session->ssrc; | ||
510 | |||
511 | int i; | ||
512 | for ( i = 0; i < session->cc; i++ ) | ||
513 | header->csrc[i] = session->csrc[i]; | ||
514 | |||
515 | header->length = 12 /* Minimum header len */ + ( session->cc * size_32 ); | ||
516 | } | ||
517 | void send_rtcp_report(RTCPSession* session, Messenger* m, uint32_t friendnumber) | ||
518 | { | ||
519 | if (session->last_expected_packets == 0) | ||
520 | return; | ||
521 | |||
522 | uint8_t parsed[9]; | ||
523 | parsed[0] = session->prefix; | ||
524 | |||
525 | uint32_t received_packets = htonl(session->last_received_packets); | ||
526 | uint32_t expected_packets = htonl(session->last_expected_packets); | ||
527 | |||
528 | memcpy(parsed + 1, &received_packets, 4); | ||
529 | memcpy(parsed + 5, &expected_packets, 4); | ||
530 | |||
531 | if (-1 == send_custom_lossy_packet(m, friendnumber, parsed, sizeof(parsed))) | ||
532 | LOGGER_WARNING("Failed to send full packet (len: %d)! std error: %s", sizeof(parsed), strerror(errno)); | ||
533 | else { | ||
534 | LOGGER_DEBUG("Sent rtcp report: ex: %d rc: %d", session->last_expected_packets, session->last_received_packets); | ||
535 | |||
536 | session->last_received_packets = 0; | ||
537 | session->last_expected_packets = 0; | ||
538 | session->last_sent_report_ts = current_time_monotonic(); | ||
539 | } | ||
540 | } | ||
541 | int handle_rtp_packet ( Messenger* m, uint32_t friendnumber, const uint8_t* data, uint16_t length, void* object ) | 479 | int handle_rtp_packet ( Messenger* m, uint32_t friendnumber, const uint8_t* data, uint16_t length, void* object ) |
542 | { | 480 | { |
543 | RTPSession *session = object; | 481 | RTPSession *session = object; |
544 | RTPMessage *msg; | ||
545 | 482 | ||
546 | if ( !session || length < 13 ) { /* 12 is the minimum length for rtp + desc. byte */ | 483 | if ( !session || length < 13 || length > MAX_RTP_SIZE ) { |
547 | LOGGER_WARNING("No session or invalid length of received buffer!"); | 484 | LOGGER_WARNING("No session or invalid length of received buffer!"); |
548 | return -1; | 485 | return -1; |
549 | } | 486 | } |
487 | |||
488 | RTPHeader* header = parse_header_in ( data, length ); | ||
550 | 489 | ||
551 | msg = msg_parse ( data + 1, length - 1 ); | 490 | if ( !header ) { |
552 | 491 | LOGGER_WARNING("Could not parse message: Header failed to extract!"); | |
553 | if ( !msg ) { | ||
554 | LOGGER_WARNING("Could not parse message!"); | ||
555 | return -1; | 492 | return -1; |
556 | } | 493 | } |
494 | |||
495 | RTPExtHeader* ext_header = NULL; | ||
496 | |||
497 | uint16_t from_pos = header->length; | ||
498 | uint16_t msg_length = length - from_pos; | ||
557 | 499 | ||
500 | if ( GET_FLAG_EXTENSION ( header ) ) { | ||
501 | ext_header = parse_ext_header_in ( data + from_pos, length ); | ||
502 | |||
503 | if ( ext_header ) { | ||
504 | msg_length -= ( 4 /* Minimum ext header len */ + ext_header->length * size_32 ); | ||
505 | from_pos += ( 4 /* Minimum ext header len */ + ext_header->length * size_32 ); | ||
506 | } else { /* Error */ | ||
507 | LOGGER_WARNING("Could not parse message: Ext Header failed to extract!"); | ||
508 | free(header); | ||
509 | return -1; | ||
510 | } | ||
511 | } | ||
512 | |||
513 | if (msg_length > MAX_RTP_SIZE) { | ||
514 | LOGGER_WARNING("Could not parse message: Invalid length!"); | ||
515 | free(header); | ||
516 | free(ext_header); | ||
517 | return -1; | ||
518 | } | ||
519 | |||
558 | /* Check if message came in late */ | 520 | /* Check if message came in late */ |
559 | if ( msg->header->sequnum > session->rsequnum || msg->header->timestamp > session->rtimestamp ) { | 521 | if ( header->sequnum > session->rsequnum || header->timestamp > session->rtimestamp ) { |
560 | /* Not late */ | 522 | /* Not late */ |
561 | if (msg->header->sequnum > session->rsequnum) | 523 | if (header->sequnum > session->rsequnum) |
562 | session->rtcp_session->last_expected_packets += msg->header->sequnum - session->rsequnum; | 524 | session->rtcp_session->last_expected_packets += header->sequnum - session->rsequnum; |
563 | else if (msg->header->sequnum < session->rsequnum) | 525 | else if (header->sequnum < session->rsequnum) |
564 | session->rtcp_session->last_expected_packets += (msg->header->sequnum + 65535) - session->rsequnum; | 526 | session->rtcp_session->last_expected_packets += (header->sequnum + 65535) - session->rsequnum; |
565 | else /* Usual case when transmission starts */ | 527 | else /* Usual case when transmission starts */ |
566 | session->rtcp_session->last_expected_packets ++; | 528 | session->rtcp_session->last_expected_packets ++; |
567 | 529 | ||
568 | session->rsequnum = msg->header->sequnum; | 530 | session->rsequnum = header->sequnum; |
569 | session->rtimestamp = msg->header->timestamp; | 531 | session->rtimestamp = header->timestamp; |
570 | } | 532 | } |
571 | 533 | ||
572 | session->rtcp_session->last_received_packets ++; | 534 | session->rtcp_session->last_received_packets ++; |
573 | 535 | ||
574 | if (session->mcb) | 536 | /* Check if the message is dummy. We don't keep dummy messages */ |
575 | return session->mcb (session->cs, msg); | 537 | if (GET_SETTING_PAYLOAD(header) == (session->payload_type + 2) % 128) { |
576 | else { | 538 | LOGGER_DEBUG("Received dummy rtp message"); |
577 | rtp_free_msg(session, msg); | 539 | free(header); |
540 | free(ext_header); | ||
541 | return 0; | ||
542 | } | ||
543 | |||
544 | /* Otherwise we will store the message if we have an appropriate handler */ | ||
545 | if (!session->mcb) { | ||
546 | LOGGER_DEBUG("No handler for the message of %d payload", GET_SETTING_PAYLOAD(header)); | ||
547 | free(header); | ||
548 | free(ext_header); | ||
578 | return 0; | 549 | return 0; |
579 | } | 550 | } |
551 | |||
552 | RTPMessage *msg = calloc(1, sizeof (RTPMessage) + msg_length); | ||
553 | |||
554 | if ( !msg ) { | ||
555 | LOGGER_WARNING("Could not parse message: Allocation failed!"); | ||
556 | free(header); | ||
557 | free(ext_header); | ||
558 | return -1; | ||
559 | } | ||
560 | |||
561 | msg->header = header; | ||
562 | msg->ext_header = ext_header; | ||
563 | msg->length = msg_length; | ||
564 | |||
565 | memcpy ( msg->data, data + from_pos, msg_length ); | ||
566 | |||
567 | return session->mcb (session->cs, msg); | ||
580 | } | 568 | } |
581 | int handle_rtcp_packet ( Messenger* m, uint32_t friendnumber, const uint8_t* data, uint16_t length, void* object ) | 569 | int handle_rtcp_packet ( Messenger* m, uint32_t friendnumber, const uint8_t* data, uint16_t length, void* object ) |
582 | { | 570 | { |
@@ -605,4 +593,28 @@ int handle_rtcp_packet ( Messenger* m, uint32_t friendnumber, const uint8_t* dat | |||
605 | 593 | ||
606 | LOGGER_DEBUG("Got rtcp report: ex: %d rc: %d", report->expected_packets, report->received_packets); | 594 | LOGGER_DEBUG("Got rtcp report: ex: %d rc: %d", report->expected_packets, report->received_packets); |
607 | return 0; | 595 | return 0; |
596 | } | ||
597 | void send_rtcp_report(RTCPSession* session, Messenger* m, uint32_t friendnumber) | ||
598 | { | ||
599 | if (session->last_expected_packets == 0) | ||
600 | return; | ||
601 | |||
602 | uint8_t parsed[9]; | ||
603 | parsed[0] = session->prefix; | ||
604 | |||
605 | uint32_t received_packets = htonl(session->last_received_packets); | ||
606 | uint32_t expected_packets = htonl(session->last_expected_packets); | ||
607 | |||
608 | memcpy(parsed + 1, &received_packets, 4); | ||
609 | memcpy(parsed + 5, &expected_packets, 4); | ||
610 | |||
611 | if (-1 == send_custom_lossy_packet(m, friendnumber, parsed, sizeof(parsed))) | ||
612 | LOGGER_WARNING("Failed to send full packet (len: %d)! std error: %s", sizeof(parsed), strerror(errno)); | ||
613 | else { | ||
614 | LOGGER_DEBUG("Sent rtcp report: ex: %d rc: %d", session->last_expected_packets, session->last_received_packets); | ||
615 | |||
616 | session->last_received_packets = 0; | ||
617 | session->last_expected_packets = 0; | ||
618 | session->last_sent_report_ts = current_time_monotonic(); | ||
619 | } | ||
608 | } \ No newline at end of file | 620 | } \ No newline at end of file |