From 50dfb4359619563012997bc3ddafb7667741066c Mon Sep 17 00:00:00 2001 From: Mamadou DIOP Date: Tue, 23 Feb 2016 22:00:35 +0100 Subject: Add new QoS implementation Code formatting --- tinyRTP/include/tinyrtp.h | 6 +- tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_header.h | 25 +- tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_packet.h | 30 +- tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_rblock.h | 27 +- tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report.h | 6 +- .../include/tinyrtp/rtcp/trtp_rtcp_report_bye.h | 15 +- tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report_fb.h | 163 +- tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report_rr.h | 19 +- .../include/tinyrtp/rtcp/trtp_rtcp_report_sdes.h | 13 +- tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report_sr.h | 35 +- tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report_xr.h | 6 +- .../include/tinyrtp/rtcp/trtp_rtcp_sdes_chunck.h | 15 +- tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_sdes_item.h | 36 +- tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_session.h | 8 +- tinyRTP/include/tinyrtp/rtp/trtp_rtp_header.h | 63 +- tinyRTP/include/tinyrtp/rtp/trtp_rtp_packet.h | 35 +- tinyRTP/include/tinyrtp/rtp/trtp_rtp_session.h | 6 +- tinyRTP/include/tinyrtp/trtp.h | 6 +- tinyRTP/include/tinyrtp/trtp_manager.h | 256 +- tinyRTP/include/tinyrtp/trtp_srtp.h | 78 +- tinyRTP/include/tinyrtp_config.h | 12 +- tinyRTP/src/rtcp/trtp_rtcp_header.c | 133 +- tinyRTP/src/rtcp/trtp_rtcp_packet.c | 379 +-- tinyRTP/src/rtcp/trtp_rtcp_rblock.c | 167 +- tinyRTP/src/rtcp/trtp_rtcp_report.c | 6 +- tinyRTP/src/rtcp/trtp_rtcp_report_bye.c | 319 ++- tinyRTP/src/rtcp/trtp_rtcp_report_fb.c | 1101 ++++---- tinyRTP/src/rtcp/trtp_rtcp_report_rr.c | 337 ++- tinyRTP/src/rtcp/trtp_rtcp_report_sdes.c | 271 +- tinyRTP/src/rtcp/trtp_rtcp_report_sr.c | 407 ++- tinyRTP/src/rtcp/trtp_rtcp_report_xr.c | 6 +- tinyRTP/src/rtcp/trtp_rtcp_sdes_chunck.c | 224 +- tinyRTP/src/rtcp/trtp_rtcp_sdes_item.c | 171 +- tinyRTP/src/rtcp/trtp_rtcp_session.c | 2421 ++++++++-------- tinyRTP/src/rtp/trtp_rtp_header.c | 353 ++- tinyRTP/src/rtp/trtp_rtp_packet.c | 339 +-- tinyRTP/src/rtp/trtp_rtp_session.c | 6 +- tinyRTP/src/trtp.c | 6 +- tinyRTP/src/trtp_manager.c | 2932 ++++++++++---------- tinyRTP/src/trtp_srtp.c | 208 +- tinyRTP/test/test.c | 26 +- tinyRTP/test/test_manager.h | 70 +- tinyRTP/test/test_parser.h | 529 ++-- 43 files changed, 5718 insertions(+), 5553 deletions(-) (limited to 'tinyRTP') diff --git a/tinyRTP/include/tinyrtp.h b/tinyRTP/include/tinyrtp.h index 8707f81..f12217a 100755 --- a/tinyRTP/include/tinyrtp.h +++ b/tinyRTP/include/tinyrtp.h @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * diff --git a/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_header.h b/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_header.h index 9cf6a1a..354c082 100755 --- a/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_header.h +++ b/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_header.h @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -33,16 +33,15 @@ TRTP_BEGIN_DECLS -typedef struct trtp_rtcp_header_s -{ - TSK_DECLARE_OBJECT; - - unsigned version:2; - unsigned padding:1; - unsigned rc:5; - trtp_rtcp_packet_type_t type; /**< Packet Type on 8bits */ - uint16_t length_in_words_minus1; /**< The length of this RTCP packet in 32-bit words minus one */ - uint32_t length_in_bytes; +typedef struct trtp_rtcp_header_s { + TSK_DECLARE_OBJECT; + + unsigned version:2; + unsigned padding:1; + unsigned rc:5; + trtp_rtcp_packet_type_t type; /**< Packet Type on 8bits */ + uint16_t length_in_words_minus1; /**< The length of this RTCP packet in 32-bit words minus one */ + uint32_t length_in_bytes; } trtp_rtcp_header_t; diff --git a/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_packet.h b/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_packet.h index 9045be7..00867f5 100755 --- a/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_packet.h +++ b/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_packet.h @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -35,23 +35,21 @@ TRTP_BEGIN_DECLS // RFC 3550 12.1 RTCP Packet Types // RFC 4585 // RFC 5104 (FIXME: not supported yet!) -typedef enum trtp_rtcp_packet_type_e -{ - trtp_rtcp_packet_type_sr = 200, - trtp_rtcp_packet_type_rr = 201, - trtp_rtcp_packet_type_sdes = 202, - trtp_rtcp_packet_type_bye = 203, - trtp_rtcp_packet_type_app = 204, - trtp_rtcp_packet_type_rtpfb = 205, - trtp_rtcp_packet_type_psfb = 206 +typedef enum trtp_rtcp_packet_type_e { + trtp_rtcp_packet_type_sr = 200, + trtp_rtcp_packet_type_rr = 201, + trtp_rtcp_packet_type_sdes = 202, + trtp_rtcp_packet_type_bye = 203, + trtp_rtcp_packet_type_app = 204, + trtp_rtcp_packet_type_rtpfb = 205, + trtp_rtcp_packet_type_psfb = 206 } trtp_rtcp_packet_type_t; -typedef struct trtp_rtcp_packet_s -{ - TSK_DECLARE_OBJECT; +typedef struct trtp_rtcp_packet_s { + TSK_DECLARE_OBJECT; - struct trtp_rtcp_header_s *header; + struct trtp_rtcp_header_s *header; } trtp_rtcp_packet_t; diff --git a/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_rblock.h b/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_rblock.h index 5ea54e6..cc5285d 100755 --- a/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_rblock.h +++ b/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_rblock.h @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -33,17 +33,16 @@ TRTP_BEGIN_DECLS #define TRTP_RTCP_RBLOCK(self) ((trtp_rtcp_rblock_t*)(self)) // RFC 3550 6.4.1 SR: Sender Report RTCP Packet => Report block part -typedef struct trtp_rtcp_rblock_s -{ - TSK_DECLARE_OBJECT; - - uint32_t ssrc; /* data source being reported */ - unsigned int fraction:8; /* fraction lost since last SR/RR */ - int cumulative_no_lost:24; /* cumul. no. pkts lost (signed!) */ - uint32_t last_seq; /* extended last seq. no. received */ - uint32_t jitter; /* interarrival jitter */ - uint32_t lsr; /* last SR packet from this source */ - uint32_t dlsr; /* delay since last SR packet */ +typedef struct trtp_rtcp_rblock_s { + TSK_DECLARE_OBJECT; + + uint32_t ssrc; /* data source being reported */ + unsigned int fraction:8; /* fraction lost since last SR/RR */ + int cumulative_no_lost:24; /* cumul. no. pkts lost (signed!) */ + uint32_t last_seq; /* extended last seq. no. received */ + uint32_t jitter; /* interarrival jitter */ + uint32_t lsr; /* last SR packet from this source */ + uint32_t dlsr; /* delay since last SR packet */ } trtp_rtcp_rblock_t; diff --git a/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report.h b/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report.h index c30351f..34031a5 100755 --- a/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report.h +++ b/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report.h @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * diff --git a/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report_bye.h b/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report_bye.h index 796e9fc..dac4e6c 100755 --- a/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report_bye.h +++ b/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report_bye.h @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -26,12 +26,11 @@ #include "tinyrtp/rtcp/trtp_rtcp_packet.h" -typedef struct trtp_rtcp_report_bye_s -{ - TRTP_DECLARE_RTCP_PACKET; +typedef struct trtp_rtcp_report_bye_s { + TRTP_DECLARE_RTCP_PACKET; - uint32_t *ssrc_list; - trtp_rtcp_packets_L_t* packets; + uint32_t *ssrc_list; + trtp_rtcp_packets_L_t* packets; } trtp_rtcp_report_bye_t; diff --git a/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report_fb.h b/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report_fb.h index 1ad30b4..a1bf9fe 100755 --- a/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report_fb.h +++ b/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report_fb.h @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -30,42 +30,39 @@ #define TRTP_DECLARE_RTCP_FB_PACKET trtp_rtcp_report_fb_t __packet_fb__ // RFC 4585 6.1. Common Packet Format for Feedback Messages -typedef struct trtp_rtcp_report_fb_s -{ - TRTP_DECLARE_RTCP_PACKET; +typedef struct trtp_rtcp_report_fb_s { + TRTP_DECLARE_RTCP_PACKET; - uint32_t ssrc_sender; /* SSRC of packet sender */ - uint32_t ssrc_media; /* SSRC of media source */ + uint32_t ssrc_sender; /* SSRC of packet sender */ + uint32_t ssrc_media; /* SSRC of media source */ } trtp_rtcp_report_fb_t; -typedef enum trtp_rtcp_rtpfb_fci_type_e -{ - trtp_rtcp_rtpfb_fci_type_nack = 1, // RFC 4585 - trtp_rtcp_rtpfb_fci_type_tmmbn = 4, // RFC 5104 +typedef enum trtp_rtcp_rtpfb_fci_type_e { + trtp_rtcp_rtpfb_fci_type_nack = 1, // RFC 4585 + trtp_rtcp_rtpfb_fci_type_tmmbn = 4, // RFC 5104 } trtp_rtcp_rtpfb_fci_type_t; // Transport layer FB message -typedef struct trtp_rtcp_report_rtpfb_s -{ - TRTP_DECLARE_RTCP_FB_PACKET; - - trtp_rtcp_rtpfb_fci_type_t fci_type; - union{ - struct{ - tsk_size_t count; // not part of the specification - uint16_t* pid; // 16 bits - uint16_t* blp; // 16 bits - }nack; - struct{ - tsk_size_t count; // not part of the specification - uint32_t* ssrc; // 32 bits - uint8_t* MxTBR_Exp; // 6 bits - uint32_t* MxTBR_Mantissa; // 17 bits - uint16_t* MeasuredOverhead; // 9 bits - }tmmbn; - }; +typedef struct trtp_rtcp_report_rtpfb_s { + TRTP_DECLARE_RTCP_FB_PACKET; + + trtp_rtcp_rtpfb_fci_type_t fci_type; + union { + struct { + tsk_size_t count; // not part of the specification + uint16_t* pid; // 16 bits + uint16_t* blp; // 16 bits + } nack; + struct { + tsk_size_t count; // not part of the specification + uint32_t* ssrc; // 32 bits + uint8_t* MxTBR_Exp; // 6 bits + uint32_t* MxTBR_Mantissa; // 17 bits + uint16_t* MeasuredOverhead; // 9 bits + } tmmbn; + }; } trtp_rtcp_report_rtpfb_t; @@ -78,64 +75,67 @@ int trtp_rtcp_report_rtpfb_serialize_to(const trtp_rtcp_report_rtpfb_t* self, vo tsk_size_t trtp_rtcp_report_rtpfb_get_size(const trtp_rtcp_report_rtpfb_t* self); -typedef enum trtp_rtcp_psfb_fci_type_e -{ - trtp_rtcp_psfb_fci_type_pli = 1, /* rfc 4585: Picture Loss Indication (PLI) */ - trtp_rtcp_psfb_fci_type_sli = 2, /* rfc 4585: Slice Loss Indication (SLI) */ - trtp_rtcp_psfb_fci_type_rpsi = 3, /* rfc 4585: Reference Picture Selection Indication (RPSI) */ - trtp_rtcp_psfb_fci_type_fir = 4, /* rfc 5104: Full Intra Request (FIR) Command*/ - trtp_rtcp_psfb_fci_type_afb = 15, /* rfc 4585: Application layer FB (AFB) message */ +typedef enum trtp_rtcp_psfb_fci_type_e { + trtp_rtcp_psfb_fci_type_pli = 1, /* rfc 4585: Picture Loss Indication (PLI) */ + trtp_rtcp_psfb_fci_type_sli = 2, /* rfc 4585: Slice Loss Indication (SLI) */ + trtp_rtcp_psfb_fci_type_rpsi = 3, /* rfc 4585: Reference Picture Selection Indication (RPSI) */ + trtp_rtcp_psfb_fci_type_fir = 4, /* rfc 5104: Full Intra Request (FIR) Command*/ + trtp_rtcp_psfb_fci_type_afb = 15, /* rfc 4585: Application layer FB (AFB) message */ } trtp_rtcp_psfb_fci_type_t; /* rfc 4585: Application layer FB (AFB) message */ -typedef enum trtp_rtcp_psfb_afb_type_e -{ - trtp_rtcp_psfb_afb_type_none, - trtp_rtcp_psfb_afb_type_remb // draft-alvestrand-rmcat-remb-02 +typedef enum trtp_rtcp_psfb_afb_type_e { + trtp_rtcp_psfb_afb_type_none, + trtp_rtcp_psfb_afb_type_remb, // draft-alvestrand-rmcat-remb-02 + trtp_rtcp_psfb_afb_type_jcng, // doubango congestion control estimation } trtp_rtcp_psfb_afb_type_t; // Payload-specific FB message -typedef struct trtp_rtcp_report_psfb_s -{ - TRTP_DECLARE_RTCP_FB_PACKET; - - trtp_rtcp_psfb_fci_type_t fci_type; - union{ - // struct{ //rfc 4585: 6.3.1.2 - // } pli; - struct{ // rfc 4585: 6.3.2.2 - uint16_t* first; - uint16_t* number; - uint8_t* pic_id; - } sli; - struct{ // rfc 4585: 6.3.3.2 - unsigned pb:8; - unsigned pt:7; - uint8_t* bytes; - } rpsi; - struct{// rfc 5104: 4.3.1.1 - tsk_size_t count; - uint32_t* ssrc; // 32 bits - uint8_t* seq_num; // 8 bits - }fir; - struct{ // rfc 4585: 6.4 - trtp_rtcp_psfb_afb_type_t type; - union{ - struct{ // draft-alvestrand-rmcat-remb-02: 2.2 - // MxTBR = mantissa * 2^exp = (mantissa << exp) bps - uint8_t num_ssrc; - uint8_t exp; // 6bits - uint32_t mantissa; // 18bits - uint32_t* ssrc_feedbacks; // 'num_ssrc'nth SSRC entries - }remb; - struct{ - uint8_t* bytes; // store bytes to allow reconstruction - }none; // unknown type - }; - }afb; - }; +typedef struct trtp_rtcp_report_psfb_s { + TRTP_DECLARE_RTCP_FB_PACKET; + + trtp_rtcp_psfb_fci_type_t fci_type; + union { + // struct{ //rfc 4585: 6.3.1.2 + // } pli; + struct { // rfc 4585: 6.3.2.2 + uint16_t* first; + uint16_t* number; + uint8_t* pic_id; + } sli; + struct { // rfc 4585: 6.3.3.2 + unsigned pb:8; + unsigned pt:7; + uint8_t* bytes; + } rpsi; + struct { // rfc 5104: 4.3.1.1 + tsk_size_t count; + uint32_t* ssrc; // 32 bits + uint8_t* seq_num; // 8 bits + } fir; + struct { // rfc 4585: 6.4 + trtp_rtcp_psfb_afb_type_t type; + union { + struct { // draft-alvestrand-rmcat-remb-02: 2.2 + // MxTBR = mantissa * 2^exp = (mantissa << exp) bps + uint8_t num_ssrc; + uint8_t exp; // 6bits + uint32_t mantissa; // 18bits + uint32_t* ssrc_feedbacks; // 'num_ssrc'nth SSRC entries + } remb; + struct { // jitter buffer congestion estimation: doubango + uint8_t num_ssrc; + uint8_t q; // 8bits + uint32_t* ssrc_feedbacks; // 'num_ssrc'nth SSRC entries + } jcng; + struct { + uint8_t* bytes; // store bytes to allow reconstruction + } none; // unknown type + }; + } afb; + }; } trtp_rtcp_report_psfb_t; @@ -145,6 +145,7 @@ trtp_rtcp_report_psfb_t* trtp_rtcp_report_psfb_create_2(trtp_rtcp_psfb_fci_type_ trtp_rtcp_report_psfb_t* trtp_rtcp_report_psfb_create_pli(uint32_t ssrc_sender, uint32_t ssrc_media_src); trtp_rtcp_report_psfb_t* trtp_rtcp_report_psfb_create_fir(uint8_t seq_num, uint32_t ssrc_sender, uint32_t ssrc_media_src); trtp_rtcp_report_psfb_t* trtp_rtcp_report_psfb_create_afb_remb(uint32_t ssrc_sender, const uint32_t* ssrc_media_src_list, uint32_t ssrc_media_src_list_count, uint32_t bitrate/*in bps*/); +trtp_rtcp_report_psfb_t* trtp_rtcp_report_psfb_create_afb_jcng(uint32_t ssrc_sender, const uint32_t* ssrc_media_src_list, uint32_t ssrc_media_src_list_count, float jcng_q/*in quality metric*/); trtp_rtcp_report_psfb_t* trtp_rtcp_report_psfb_deserialize(const void* data, tsk_size_t size); int trtp_rtcp_report_psfb_serialize_to(const trtp_rtcp_report_psfb_t* self, void* data, tsk_size_t size); tsk_size_t trtp_rtcp_report_psfb_get_size(const trtp_rtcp_report_psfb_t* self); diff --git a/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report_rr.h b/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report_rr.h index 2f25779..6a417d3 100755 --- a/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report_rr.h +++ b/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report_rr.h @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -32,13 +32,12 @@ TRTP_BEGIN_DECLS #define TRTP_RTCP_REPORT_RR(self) ((trtp_rtcp_report_rr_t*)(self)) // RFC 3550 6.4.2 RR: Receiver Report RTCP Packet -typedef struct trtp_rtcp_report_rr_s -{ - TRTP_DECLARE_RTCP_PACKET; - - uint32_t ssrc; - trtp_rtcp_rblocks_L_t* blocks; - trtp_rtcp_packets_L_t* packets; +typedef struct trtp_rtcp_report_rr_s { + TRTP_DECLARE_RTCP_PACKET; + + uint32_t ssrc; + trtp_rtcp_rblocks_L_t* blocks; + trtp_rtcp_packets_L_t* packets; } trtp_rtcp_report_rr_t; diff --git a/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report_sdes.h b/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report_sdes.h index 04efb5c..b8df1e5 100755 --- a/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report_sdes.h +++ b/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report_sdes.h @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -32,10 +32,9 @@ TRTP_BEGIN_DECLS #define TRTP_RTCP_REPORT_SDES(self) ((trtp_rtcp_report_sdes_t*)(self)) /* RFC 3550 6.5 SDES: Source Description RTCP Packet */ -typedef struct trtp_rtcp_report_sdes_s -{ - TRTP_DECLARE_RTCP_PACKET; - trtp_rtcp_sdes_chuncks_L_t* chuncks; +typedef struct trtp_rtcp_report_sdes_s { + TRTP_DECLARE_RTCP_PACKET; + trtp_rtcp_sdes_chuncks_L_t* chuncks; } trtp_rtcp_report_sdes_t; diff --git a/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report_sr.h b/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report_sr.h index 09d442f..73de26e 100755 --- a/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report_sr.h +++ b/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report_sr.h @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -32,21 +32,20 @@ TRTP_BEGIN_DECLS #define TRTP_RTCP_REPORT_SR(self) ((trtp_rtcp_report_sr_t*)(self)) // RFC 3550 6.4.1 SR: Sender Report RTCP Packet -typedef struct trtp_rtcp_report_sr_s -{ - TRTP_DECLARE_RTCP_PACKET; - - uint32_t ssrc; - struct{ - uint32_t ntp_msw; /**< NTP timestamp, most significant word */ - uint32_t ntp_lsw; /**< NTP timestamp, least significant word */ - uint32_t rtp_timestamp;/**< RTP timestamp */ - uint32_t sender_pcount; /**< sender's packet count */ - uint32_t sender_ocount; /**< sender's octet count */ - } sender_info; - - trtp_rtcp_rblocks_L_t* blocks; - trtp_rtcp_packets_L_t* packets; +typedef struct trtp_rtcp_report_sr_s { + TRTP_DECLARE_RTCP_PACKET; + + uint32_t ssrc; + struct { + uint32_t ntp_msw; /**< NTP timestamp, most significant word */ + uint32_t ntp_lsw; /**< NTP timestamp, least significant word */ + uint32_t rtp_timestamp;/**< RTP timestamp */ + uint32_t sender_pcount; /**< sender's packet count */ + uint32_t sender_ocount; /**< sender's octet count */ + } sender_info; + + trtp_rtcp_rblocks_L_t* blocks; + trtp_rtcp_packets_L_t* packets; } trtp_rtcp_report_sr_t; diff --git a/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report_xr.h b/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report_xr.h index b08e096..dda4dcc 100755 --- a/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report_xr.h +++ b/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_report_xr.h @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * diff --git a/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_sdes_chunck.h b/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_sdes_chunck.h index ec3a8d8..bf47f53 100755 --- a/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_sdes_chunck.h +++ b/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_sdes_chunck.h @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -33,12 +33,11 @@ TRTP_BEGIN_DECLS -typedef struct trtp_rtcp_sdes_chunck_s -{ - TSK_DECLARE_OBJECT; +typedef struct trtp_rtcp_sdes_chunck_s { + TSK_DECLARE_OBJECT; - uint32_t ssrc; - trtp_rtcp_sdes_items_L_t* items; + uint32_t ssrc; + trtp_rtcp_sdes_items_L_t* items; } trtp_rtcp_sdes_chunck_t; diff --git a/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_sdes_item.h b/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_sdes_item.h index 8356a74..f485e24 100755 --- a/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_sdes_item.h +++ b/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_sdes_item.h @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -34,26 +34,24 @@ TRTP_BEGIN_DECLS // RFC 3550 12.2 SDES Types -typedef enum trtp_rtcp_sdes_item_type_e -{ - trtp_rtcp_sdes_item_type_end = 0, /**< end of SDES list */ - trtp_rtcp_sdes_item_type_cname = 1, /**< canonical name*/ - trtp_rtcp_sdes_item_type_name = 2, /**< user name */ - trtp_rtcp_sdes_item_type_email = 3, /**< user's electronic mail address*/ - trtp_rtcp_sdes_item_type_phone = 4, /**< user's phone number */ - trtp_rtcp_sdes_item_type_loc = 5, /**< geographic user location*/ - trtp_rtcp_sdes_item_type_tool = 6, /**< name of application or tool*/ - trtp_rtcp_sdes_item_type_note = 7, /**< notice about the source*/ - trtp_rtcp_sdes_item_type_priv = 8, /**< private extensions*/ +typedef enum trtp_rtcp_sdes_item_type_e { + trtp_rtcp_sdes_item_type_end = 0, /**< end of SDES list */ + trtp_rtcp_sdes_item_type_cname = 1, /**< canonical name*/ + trtp_rtcp_sdes_item_type_name = 2, /**< user name */ + trtp_rtcp_sdes_item_type_email = 3, /**< user's electronic mail address*/ + trtp_rtcp_sdes_item_type_phone = 4, /**< user's phone number */ + trtp_rtcp_sdes_item_type_loc = 5, /**< geographic user location*/ + trtp_rtcp_sdes_item_type_tool = 6, /**< name of application or tool*/ + trtp_rtcp_sdes_item_type_note = 7, /**< notice about the source*/ + trtp_rtcp_sdes_item_type_priv = 8, /**< private extensions*/ } trtp_rtcp_sdes_item_type_t; -typedef struct trtp_rtcp_sdes_item_s -{ - TSK_DECLARE_OBJECT; +typedef struct trtp_rtcp_sdes_item_s { + TSK_DECLARE_OBJECT; - trtp_rtcp_sdes_item_type_t type; - tsk_buffer_t *data; + trtp_rtcp_sdes_item_type_t type; + tsk_buffer_t *data; } trtp_rtcp_sdes_item_t; diff --git a/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_session.h b/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_session.h index 34ddbbc..4ea08e0 100755 --- a/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_session.h +++ b/tinyRTP/include/tinyrtp/rtcp/trtp_rtcp_session.h @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -51,7 +51,7 @@ int trtp_rtcp_session_set_callback(struct trtp_rtcp_session_s* self, trtp_rtcp_c #if HAVE_SRTP int trtp_rtcp_session_set_srtp_sess(struct trtp_rtcp_session_s* self, const srtp_t* session); #endif -int trtp_rtcp_session_set_app_bandwidth_max(struct trtp_rtcp_session_s* self, int32_t bw_upload_kbps, int32_t bw_download_kbps); +int trtp_rtcp_session_set_app_bw_and_jcng(struct trtp_rtcp_session_s* self, int32_t bw_upload_kbps, int32_t bw_download_kbps, float jcng_q); int trtp_rtcp_session_start(struct trtp_rtcp_session_s* self, tnet_fd_t local_fd, const struct sockaddr* remote_addr); int trtp_rtcp_session_stop(struct trtp_rtcp_session_s* self); int trtp_rtcp_session_process_rtp_out(struct trtp_rtcp_session_s* self, const struct trtp_rtp_packet_s* packet_rtp, tsk_size_t size); diff --git a/tinyRTP/include/tinyrtp/rtp/trtp_rtp_header.h b/tinyRTP/include/tinyrtp/rtp/trtp_rtp_header.h index 15d177c..8b8a3b3 100755 --- a/tinyRTP/include/tinyrtp/rtp/trtp_rtp_header.h +++ b/tinyRTP/include/tinyrtp/rtp/trtp_rtp_header.h @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -37,36 +37,35 @@ TRTP_BEGIN_DECLS #define TRTP_RTP_HEADER_MIN_SIZE 12 #define TRTP_RTP_HEADER(self) ((trtp_rtp_header_t*)(self)) -typedef struct trtp_rtp_header_s -{ - TSK_DECLARE_OBJECT; - /* RFC 3550 section 5.1 - RTP Fixed Header Fields - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |V=2|P|X| CC |M| PT | sequence number | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | timestamp | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | synchronization source (SSRC) identifier | - +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ - | contributing source (CSRC) identifiers | - | .... | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - unsigned version:2; - unsigned padding:1; - unsigned extension:1; - unsigned csrc_count:4; - unsigned marker:1; - unsigned payload_type:7; - uint16_t seq_num; - uint32_t timestamp; - uint32_t ssrc; - uint32_t csrc[15]; +typedef struct trtp_rtp_header_s { + TSK_DECLARE_OBJECT; + /* RFC 3550 section 5.1 - RTP Fixed Header Fields + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |V=2|P|X| CC |M| PT | sequence number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | timestamp | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | synchronization source (SSRC) identifier | + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + | contributing source (CSRC) identifiers | + | .... | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + unsigned version:2; + unsigned padding:1; + unsigned extension:1; + unsigned csrc_count:4; + unsigned marker:1; + unsigned payload_type:7; + uint16_t seq_num; + uint32_t timestamp; + uint32_t ssrc; + uint32_t csrc[15]; - // for internal use - enum tmedia_codec_id_e codec_id; + // for internal use + enum tmedia_codec_id_e codec_id; } trtp_rtp_header_t; diff --git a/tinyRTP/include/tinyrtp/rtp/trtp_rtp_packet.h b/tinyRTP/include/tinyrtp/rtp/trtp_rtp_packet.h index c7f8cf3..b9d81b3 100755 --- a/tinyRTP/include/tinyrtp/rtp/trtp_rtp_packet.h +++ b/tinyRTP/include/tinyrtp/rtp/trtp_rtp_packet.h @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -37,23 +37,22 @@ TRTP_BEGIN_DECLS -typedef struct trtp_rtp_packet_s -{ - TSK_DECLARE_OBJECT; +typedef struct trtp_rtp_packet_s { + TSK_DECLARE_OBJECT; + + trtp_rtp_header_t* header; - trtp_rtp_header_t* header; + struct { + void* data; + const void* data_const; // never free()d. an alternative to "data" + tsk_size_t size; + } payload; - struct{ - void* data; - const void* data_const; // never free()d. an alternative to "data" - tsk_size_t size; - } payload; - - /* extension header as per RFC 3550 section 5.3.1 */ - struct{ - void* data; - tsk_size_t size; /* contains the first two 16-bit fields */ - } extension; + /* extension header as per RFC 3550 section 5.3.1 */ + struct { + void* data; + tsk_size_t size; /* contains the first two 16-bit fields */ + } extension; } trtp_rtp_packet_t; typedef tsk_list_t trtp_rtp_packets_L_t; diff --git a/tinyRTP/include/tinyrtp/rtp/trtp_rtp_session.h b/tinyRTP/include/tinyrtp/rtp/trtp_rtp_session.h index 475502a..f5d8770 100755 --- a/tinyRTP/include/tinyrtp/rtp/trtp_rtp_session.h +++ b/tinyRTP/include/tinyrtp/rtp/trtp_rtp_session.h @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * diff --git a/tinyRTP/include/tinyrtp/trtp.h b/tinyRTP/include/tinyrtp/trtp.h index 3359a70..ea72491 100755 --- a/tinyRTP/include/tinyrtp/trtp.h +++ b/tinyRTP/include/tinyrtp/trtp.h @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * diff --git a/tinyRTP/include/tinyrtp/trtp_manager.h b/tinyRTP/include/tinyrtp/trtp_manager.h index 1594f9c..e409c7b 100755 --- a/tinyRTP/include/tinyrtp/trtp_manager.h +++ b/tinyRTP/include/tinyrtp/trtp_manager.h @@ -1,19 +1,19 @@ /* * Copyright (C) 2012 Mamadou Diop * Copyright (C) 2012-2013 Doubango Telecom -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -40,140 +40,140 @@ struct trtp_rtp_packet_s; struct tnet_proxyinfo_s; /** RTP/RTCP manager */ -typedef struct trtp_manager_s -{ - TSK_DECLARE_OBJECT; - - char* local_ip; - tsk_bool_t use_ipv6; - tsk_bool_t is_started; - tsk_bool_t use_rtcp; - tsk_bool_t use_rtcpmux; - tsk_bool_t is_socket_disabled; - tsk_bool_t is_ice_neg_ok; - tsk_bool_t is_ice_turn_active; - tsk_bool_t is_force_symetric_rtp; - tsk_bool_t is_symetric_rtp_checked; - tsk_bool_t is_symetric_rtcp_checked; - int32_t app_bw_max_upload; // application specific (kbps) - int32_t app_bw_max_download; // application specific (kbps) - - tnet_transport_t* transport; - - struct tnet_ice_ctx_s* ice_ctx; - - tsk_timer_manager_handle_t* timer_mgr_global; - - struct{ - tmedia_rtcweb_type_t local; - tmedia_rtcweb_type_t remote; - } rtcweb_type; - +typedef struct trtp_manager_s { + TSK_DECLARE_OBJECT; + + char* local_ip; + tsk_bool_t use_ipv6; + tsk_bool_t is_started; + tsk_bool_t use_rtcp; + tsk_bool_t use_rtcpmux; + tsk_bool_t is_socket_disabled; + tsk_bool_t is_ice_neg_ok; + tsk_bool_t is_ice_turn_active; + tsk_bool_t is_force_symetric_rtp; + tsk_bool_t is_symetric_rtp_checked; + tsk_bool_t is_symetric_rtcp_checked; + int32_t app_bw_max_upload; // application specific (kbps) + int32_t app_bw_max_download; // application specific (kbps) + float app_jitter_cng; // application specific jitter buffer congestion estimation (quality in ]0, 1], 1f meaning no congestion) + + tnet_transport_t* transport; + + struct tnet_ice_ctx_s* ice_ctx; + + tsk_timer_manager_handle_t* timer_mgr_global; + + struct { + tmedia_rtcweb_type_t local; + tmedia_rtcweb_type_t remote; + } rtcweb_type; + struct { tsk_bool_t auto_detect; struct tnet_proxyinfo_s* info; } proxy; - struct{ - uint16_t start; - uint16_t stop; - } port_range; + struct { + uint16_t start; + uint16_t stop; + } port_range; - struct{ - uint16_t seq_num; - uint32_t timestamp; - uint8_t payload_type; + struct { + uint16_t seq_num; + uint32_t timestamp; + uint8_t payload_type; int32_t dscp; - char* remote_ip; - tnet_port_t remote_port; - struct sockaddr_storage remote_addr; - - char* public_ip; - tnet_port_t public_port; - - struct{ - uint32_t local; - uint32_t remote; - } ssrc; - - struct{ - const void* usrdata; - trtp_rtp_cb_f fun; - } cb; - - struct{ - void* ptr; - tsk_size_t size; + char* remote_ip; + tnet_port_t remote_port; + struct sockaddr_storage remote_addr; + + char* public_ip; + tnet_port_t public_port; + + struct { + uint32_t local; + uint32_t remote; + } ssrc; + + struct { + const void* usrdata; + trtp_rtp_cb_f fun; + } cb; + + struct { + void* ptr; + tsk_size_t size; tsk_size_t index; - } serial_buffer; - } rtp; - - struct{ - char* cname; - char* remote_ip; - tnet_port_t remote_port; - struct sockaddr_storage remote_addr; - tnet_socket_t* local_socket; - - char* public_ip; - tnet_port_t public_port; - - struct{ - const void* usrdata; - trtp_rtcp_cb_f fun; - } cb; - - struct trtp_rtcp_session_s* session; - } rtcp; - - TSK_DECLARE_SAFEOBJ; - -#if HAVE_SRTP - enum tmedia_srtp_type_e srtp_type; - enum tmedia_srtp_mode_e srtp_mode; - trtp_srtp_state_t srtp_state; - trtp_srtp_ctx_xt srtp_contexts[2/*LINE_IDX*/][2/*CRYPTO_TYPE*/]; - const struct trtp_srtp_ctx_xs* srtp_ctx_neg_local; - const struct trtp_srtp_ctx_xs* srtp_ctx_neg_remote; - - struct{ - char* file_ca; - char* file_pbk; - char* file_pvk; - tsk_bool_t cert_verif; - - trtp_srtp_state_t state; - // enable() could be postponed if net transport not ready yet (e.g. when ICE is ON) - tsk_bool_t enable_postponed; - - tsk_bool_t srtp_connected; - tsk_bool_t srtcp_connected; - tsk_bool_t srtp_handshake_succeed; - tsk_bool_t srtcp_handshake_succeed; - - trtp_srtp_crypto_type_t crypto_selected; - - struct{ - uint64_t timeout; - tsk_timer_id_t id; - } timer_hanshaking; - - struct{ - const void* usrdata; - trtp_srtp_dtls_cb_f fun; - } cb; - - struct{ - tnet_fingerprint_t fp; - tnet_dtls_hash_type_t fp_hash; - } remote; - struct{ - tnet_dtls_setup_t setup; - tsk_bool_t connection_new; - }local; - } dtls; + } serial_buffer; + } rtp; + + struct { + char* cname; + char* remote_ip; + tnet_port_t remote_port; + struct sockaddr_storage remote_addr; + tnet_socket_t* local_socket; + + char* public_ip; + tnet_port_t public_port; + + struct { + const void* usrdata; + trtp_rtcp_cb_f fun; + } cb; + + struct trtp_rtcp_session_s* session; + } rtcp; + + TSK_DECLARE_SAFEOBJ; + +#if HAVE_SRTP + enum tmedia_srtp_type_e srtp_type; + enum tmedia_srtp_mode_e srtp_mode; + trtp_srtp_state_t srtp_state; + trtp_srtp_ctx_xt srtp_contexts[2/*LINE_IDX*/][2/*CRYPTO_TYPE*/]; + const struct trtp_srtp_ctx_xs* srtp_ctx_neg_local; + const struct trtp_srtp_ctx_xs* srtp_ctx_neg_remote; + + struct { + char* file_ca; + char* file_pbk; + char* file_pvk; + tsk_bool_t cert_verif; + + trtp_srtp_state_t state; + // enable() could be postponed if net transport not ready yet (e.g. when ICE is ON) + tsk_bool_t enable_postponed; + + tsk_bool_t srtp_connected; + tsk_bool_t srtcp_connected; + tsk_bool_t srtp_handshake_succeed; + tsk_bool_t srtcp_handshake_succeed; + + trtp_srtp_crypto_type_t crypto_selected; + + struct { + uint64_t timeout; + tsk_timer_id_t id; + } timer_hanshaking; + + struct { + const void* usrdata; + trtp_srtp_dtls_cb_f fun; + } cb; + + struct { + tnet_fingerprint_t fp; + tnet_dtls_hash_type_t fp_hash; + } remote; + struct { + tnet_dtls_setup_t setup; + tsk_bool_t connection_new; + } local; + } dtls; #endif } trtp_manager_t; @@ -214,7 +214,7 @@ TINYRTP_API tsk_size_t trtp_manager_send_rtp(trtp_manager_t* self, const void* d TINYRTP_API tsk_size_t trtp_manager_send_rtp_packet(trtp_manager_t* self, const struct trtp_rtp_packet_s* packet, tsk_bool_t bypass_encrypt); TINYRTP_API int trtp_manager_get_bytes_count(trtp_manager_t* self, uint64_t* bytes_in, uint64_t* bytes_out); TINYRTP_API tsk_size_t trtp_manager_send_rtp_raw(trtp_manager_t* self, const void* data, tsk_size_t size); -TINYRTP_API int trtp_manager_set_app_bandwidth_max(trtp_manager_t* self, int32_t bw_upload_kbps, int32_t bw_download_kbps); +TINYRTP_API int trtp_manager_set_app_bw_and_jcng(trtp_manager_t* self, int32_t bw_upload_kbps, int32_t bw_download_kbps, float jcng_q); TINYRTP_API int trtp_manager_signal_pkt_loss(trtp_manager_t* self, uint32_t ssrc_media, const uint16_t* seq_nums, tsk_size_t count); TINYRTP_API int trtp_manager_signal_frame_corrupted(trtp_manager_t* self, uint32_t ssrc_media); TINYRTP_API int trtp_manager_signal_jb_error(trtp_manager_t* self, uint32_t ssrc_media); diff --git a/tinyRTP/include/tinyrtp/trtp_srtp.h b/tinyRTP/include/tinyrtp/trtp_srtp.h index 9992bbb..2b3ac13 100755 --- a/tinyRTP/include/tinyrtp/trtp_srtp.h +++ b/tinyRTP/include/tinyrtp/trtp_srtp.h @@ -1,19 +1,19 @@ /* * Copyright (C) 2012 Mamadou Diop * Copyright (C) 2012-2013 Doubango Telecom -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -26,48 +26,45 @@ #include "tinyrtp_config.h" #if HAVE_SRTP -# include "tsk_common.h" +# include "tsk_common.h" # include struct trtp_manager_s; -typedef enum trtp_srtp_dtls_event_type_e -{ - trtp_srtp_dtls_event_type_handshake_failed, - trtp_srtp_dtls_event_type_handshake_succeed, - trtp_srtp_dtls_event_type_fatal_error, - trtp_srtp_dtls_event_type_started +typedef enum trtp_srtp_dtls_event_type_e { + trtp_srtp_dtls_event_type_handshake_failed, + trtp_srtp_dtls_event_type_handshake_succeed, + trtp_srtp_dtls_event_type_fatal_error, + trtp_srtp_dtls_event_type_started } trtp_srtp_dtls_event_type_t; -typedef enum trtp_srtp_crypto_type_e -{ - NONE = -1, - HMAC_SHA1_80, - HMAC_SHA1_32, +typedef enum trtp_srtp_crypto_type_e { + NONE = -1, + HMAC_SHA1_80, + HMAC_SHA1_32, - SRTP_CRYPTO_TYPES_MAX + SRTP_CRYPTO_TYPES_MAX } trtp_srtp_crypto_type_t; -typedef enum trtp_srtp_state_e -{ - trtp_srtp_state_none, - /* at this state we're able to generated DTLS "fingerprints" and SDES "crypro" attributes +typedef enum trtp_srtp_state_e { + trtp_srtp_state_none, + /* at this state we're able to generated DTLS "fingerprints" and SDES "crypro" attributes but neither encrypt() nor decrypt() is possible. it's possible to move backward and disable SRTP (e.g. because of negotiation error) it's required to move to this state in order to be able to negotiate SRTP when mode is "optional" or "mandatory" */ - trtp_srtp_state_enabled, - /* at this state both required parameters (e.g. "crypto" attributes) have been successfuly proceeded + trtp_srtp_state_enabled, + /* at this state both required parameters (e.g. "crypto" attributes) have been successfuly proceeded it's not possible to move backward and disable SRTP if type="SDES": start()ing the engine means we'll be imediately able to encrypt()/decrypt() data if type="DTLS": start()ing the engine doesn't mean we will be able to encrypt()/decrypt() data unless handshaking process successfuly completed */ - trtp_srtp_state_activated, - /* at this state we're able to encrypt()/decrypt() SRTP data + trtp_srtp_state_activated, + /* at this state we're able to encrypt()/decrypt() SRTP data */ - trtp_srtp_state_started + trtp_srtp_state_started } trtp_srtp_state_t; @@ -79,31 +76,28 @@ typedef int (*trtp_srtp_dtls_cb_f)(const void* usrdata, enum trtp_srtp_dtls_eve #define TRTP_SRTP_LINE_IDX_LOCAL 0 #define TRTP_SRTP_LINE_IDX_REMOTE 1 -static const char* trtp_srtp_crypto_type_strings[2] = -{ - TRTP_SRTP_AES_CM_128_HMAC_SHA1_80, TRTP_SRTP_AES_CM_128_HMAC_SHA1_32 +static const char* trtp_srtp_crypto_type_strings[2] = { + TRTP_SRTP_AES_CM_128_HMAC_SHA1_80, TRTP_SRTP_AES_CM_128_HMAC_SHA1_32 }; -typedef struct trtp_srtp_ctx_internal_xs -{ - int32_t tag; - trtp_srtp_crypto_type_t crypto_type; - char key_str[SRTP_MAX_KEY_LEN]; - char key_bin[SRTP_MASTER_KEY_LEN]; +typedef struct trtp_srtp_ctx_internal_xs { + int32_t tag; + trtp_srtp_crypto_type_t crypto_type; + char key_str[SRTP_MAX_KEY_LEN]; + char key_bin[SRTP_MASTER_KEY_LEN]; tsk_bool_t have_valid_key; - srtp_t session; - srtp_policy_t policy; - tsk_bool_t initialized; + srtp_t session; + srtp_policy_t policy; + tsk_bool_t initialized; } trtp_srtp_ctx_internal_xt; -typedef struct trtp_srtp_ctx_xs -{ - // (rtp == rtcp) for SDES but different for DTLS - struct trtp_srtp_ctx_internal_xs rtp; - struct trtp_srtp_ctx_internal_xs rtcp; +typedef struct trtp_srtp_ctx_xs { + // (rtp == rtcp) for SDES but different for DTLS + struct trtp_srtp_ctx_internal_xs rtp; + struct trtp_srtp_ctx_internal_xs rtcp; } trtp_srtp_ctx_xt; diff --git a/tinyRTP/include/tinyrtp_config.h b/tinyRTP/include/tinyrtp_config.h index 422b68f..cb1faed 100755 --- a/tinyRTP/include/tinyrtp_config.h +++ b/tinyRTP/include/tinyrtp_config.h @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -49,13 +49,13 @@ # define TINYRTP_GEXTERN extern #endif -/* Guards against C++ name mangling +/* Guards against C++ name mangling */ #ifdef __cplusplus # define TRTP_BEGIN_DECLS extern "C" { # define TRTP_END_DECLS } #else -# define TRTP_BEGIN_DECLS +# define TRTP_BEGIN_DECLS # define TRTP_END_DECLS #endif @@ -86,7 +86,7 @@ #endif #if HAVE_CONFIG_H - #include +#include #endif #endif // TINYRTP_CONFIG_H diff --git a/tinyRTP/src/rtcp/trtp_rtcp_header.c b/tinyRTP/src/rtcp/trtp_rtcp_header.c index e93772a..d11d32f 100755 --- a/tinyRTP/src/rtcp/trtp_rtcp_header.c +++ b/tinyRTP/src/rtcp/trtp_rtcp_header.c @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -35,73 +35,73 @@ header |V=2|P| RC | PT=SR=200 | length | trtp_rtcp_header_t* trtp_rtcp_header_create_null() { - return tsk_object_new(trtp_rtcp_header_def_t); + return tsk_object_new(trtp_rtcp_header_def_t); } trtp_rtcp_header_t* trtp_rtcp_header_create(uint8_t version, uint8_t padding, uint8_t rc, trtp_rtcp_packet_type_t type, uint16_t length_in_bytes) { - trtp_rtcp_header_t* header; - if((header = trtp_rtcp_header_create_null())){ - header->version = version; - header->padding = padding; - header->rc = rc; - header->type = type; - header->length_in_words_minus1 = ((length_in_bytes >> 2) - 1); - header->length_in_bytes = length_in_bytes; - } + trtp_rtcp_header_t* header; + if((header = trtp_rtcp_header_create_null())) { + header->version = version; + header->padding = padding; + header->rc = rc; + header->type = type; + header->length_in_words_minus1 = ((length_in_bytes >> 2) - 1); + header->length_in_bytes = length_in_bytes; + } - return header; + return header; } int trtp_rtcp_header_serialize_to(const trtp_rtcp_header_t *self, void* data, tsk_size_t size) { - uint8_t* pdata = (uint8_t*)data; - if(!self || !data || size < TRTP_RTCP_HEADER_SIZE){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - // Octet-0: version(2), Padding(1), RC(5) - pdata[0] = ((uint8_t)self->version)<<6 | - ((uint8_t)self->padding)<<5 | - ((uint8_t)self->rc); - // Octet-1: PT(8) - pdata[1] = self->type; - // Octet-2 and Octet3: length (16) - pdata[2] = self->length_in_words_minus1 >> 8; - pdata[3] = self->length_in_words_minus1 & 0xFF; - return 0; + uint8_t* pdata = (uint8_t*)data; + if(!self || !data || size < TRTP_RTCP_HEADER_SIZE) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + // Octet-0: version(2), Padding(1), RC(5) + pdata[0] = ((uint8_t)self->version)<<6 | + ((uint8_t)self->padding)<<5 | + ((uint8_t)self->rc); + // Octet-1: PT(8) + pdata[1] = self->type; + // Octet-2 and Octet3: length (16) + pdata[2] = self->length_in_words_minus1 >> 8; + pdata[3] = self->length_in_words_minus1 & 0xFF; + return 0; } trtp_rtcp_header_t* trtp_rtcp_header_deserialize(const void *data, tsk_size_t size) { - trtp_rtcp_header_t* header = tsk_null; - if(trtp_rtcp_header_deserialize_to(&header, data, size) != 0){ - TSK_DEBUG_ERROR("Failed to deserialize the rtcp header"); - TSK_OBJECT_SAFE_FREE(header); - } - return header; + trtp_rtcp_header_t* header = tsk_null; + if(trtp_rtcp_header_deserialize_to(&header, data, size) != 0) { + TSK_DEBUG_ERROR("Failed to deserialize the rtcp header"); + TSK_OBJECT_SAFE_FREE(header); + } + return header; } int trtp_rtcp_header_deserialize_to(trtp_rtcp_header_t** self, const void *data, tsk_size_t size) { - const uint8_t* pdata = (uint8_t*)data; - if(!self || !data || size < TRTP_RTCP_HEADER_SIZE){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - if(!*self && !(*self = trtp_rtcp_header_create_null())){ - TSK_DEBUG_ERROR("Failed to create new rtcp header"); - return -3; - } - (*self)->version = pdata[0] >> 6; - (*self)->padding = (pdata[0] >> 5) & 0x01; - (*self)->rc = (pdata[0] & 0x1f); - (*self)->type = (enum trtp_rtcp_packet_type_e)pdata[1]; - (*self)->length_in_words_minus1 = tnet_ntohs_2(&pdata[2]); - (*self)->length_in_bytes = ((*self)->length_in_words_minus1 + 1) << 2; + const uint8_t* pdata = (uint8_t*)data; + if(!self || !data || size < TRTP_RTCP_HEADER_SIZE) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - return 0; + if(!*self && !(*self = trtp_rtcp_header_create_null())) { + TSK_DEBUG_ERROR("Failed to create new rtcp header"); + return -3; + } + (*self)->version = pdata[0] >> 6; + (*self)->padding = (pdata[0] >> 5) & 0x01; + (*self)->rc = (pdata[0] & 0x1f); + (*self)->type = (enum trtp_rtcp_packet_type_e)pdata[1]; + (*self)->length_in_words_minus1 = tnet_ntohs_2(&pdata[2]); + (*self)->length_in_bytes = ((*self)->length_in_words_minus1 + 1) << 2; + + return 0; } //================================================================================================= @@ -109,26 +109,25 @@ int trtp_rtcp_header_deserialize_to(trtp_rtcp_header_t** self, const void *data, // static tsk_object_t* trtp_rtcp_header_ctor(tsk_object_t * self, va_list * app) { - trtp_rtcp_header_t *header = self; - if(header){ - } - return self; + trtp_rtcp_header_t *header = self; + if(header) { + } + return self; } static tsk_object_t* trtp_rtcp_header_dtor(tsk_object_t * self) -{ - trtp_rtcp_header_t *header = self; - if(header){ - } +{ + trtp_rtcp_header_t *header = self; + if(header) { + } - return self; + return self; } -static const tsk_object_def_t trtp_rtcp_header_def_s = -{ - sizeof(trtp_rtcp_header_t), - trtp_rtcp_header_ctor, - trtp_rtcp_header_dtor, - tsk_null, +static const tsk_object_def_t trtp_rtcp_header_def_s = { + sizeof(trtp_rtcp_header_t), + trtp_rtcp_header_ctor, + trtp_rtcp_header_dtor, + tsk_null, }; const tsk_object_def_t *trtp_rtcp_header_def_t = &trtp_rtcp_header_def_s; diff --git a/tinyRTP/src/rtcp/trtp_rtcp_packet.c b/tinyRTP/src/rtcp/trtp_rtcp_packet.c index d2ec856..d5614b8 100755 --- a/tinyRTP/src/rtcp/trtp_rtcp_packet.c +++ b/tinyRTP/src/rtcp/trtp_rtcp_packet.c @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -32,224 +32,255 @@ static tsk_object_t* trtp_rtcp_packet_ctor(tsk_object_t * self, va_list * app) { - trtp_rtcp_packet_t *packet = self; - if(packet){ - } - return self; + trtp_rtcp_packet_t *packet = self; + if(packet) { + } + return self; } static tsk_object_t* trtp_rtcp_packet_dtor(tsk_object_t * self) -{ - trtp_rtcp_packet_t *packet = self; - if(packet){ +{ + trtp_rtcp_packet_t *packet = self; + if(packet) { - } + } - return self; + return self; } -static const tsk_object_def_t trtp_rtcp_packet_def_s = -{ - sizeof(trtp_rtcp_packet_t), - trtp_rtcp_packet_ctor, - trtp_rtcp_packet_dtor, - tsk_null, +static const tsk_object_def_t trtp_rtcp_packet_def_s = { + sizeof(trtp_rtcp_packet_t), + trtp_rtcp_packet_ctor, + trtp_rtcp_packet_dtor, + tsk_null, }; const tsk_object_def_t *trtp_rtcp_packet_def_t = &trtp_rtcp_packet_def_s; trtp_rtcp_packet_t* trtp_rtcp_packet_create(struct trtp_rtcp_header_s* header) { - trtp_rtcp_packet_t* packet; - if((packet = tsk_object_new(trtp_rtcp_packet_def_t)) && header){ - packet->header = tsk_object_ref(header); - } - return packet; + trtp_rtcp_packet_t* packet; + if((packet = tsk_object_new(trtp_rtcp_packet_def_t)) && header) { + packet->header = tsk_object_ref(header); + } + return packet; } int trtp_rtcp_packet_init(trtp_rtcp_packet_t* self, uint8_t version, uint8_t padding, uint8_t rc, trtp_rtcp_packet_type_t type, uint16_t length_in_bytes) { - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if(!self->header){ - self->header = trtp_rtcp_header_create(version, padding, rc, type, length_in_bytes); - } - else{ - self->header->version = version; - self->header->padding = padding; - self->header->rc = rc; - self->header->type = type; - self->header->length_in_bytes = length_in_bytes; - self->header->length_in_words_minus1 = ((length_in_bytes >> 2) - 1); - } - return 0; + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if(!self->header) { + self->header = trtp_rtcp_header_create(version, padding, rc, type, length_in_bytes); + } + else { + self->header->version = version; + self->header->padding = padding; + self->header->rc = rc; + self->header->type = type; + self->header->length_in_bytes = length_in_bytes; + self->header->length_in_words_minus1 = ((length_in_bytes >> 2) - 1); + } + return 0; } trtp_rtcp_packet_t* trtp_rtcp_packet_deserialize(const void* data, tsk_size_t size) { - trtp_rtcp_packet_type_t type; - - if(!data || size < TRTP_RTCP_HEADER_SIZE){ - TSK_DEBUG_ERROR("Invalid parameter"); - return tsk_null; - } - - type = (trtp_rtcp_packet_type_t)((const uint8_t*)data)[1]; - - switch(type){ - case trtp_rtcp_packet_type_rr: return (trtp_rtcp_packet_t*)trtp_rtcp_report_rr_deserialize(data, size); - case trtp_rtcp_packet_type_sr: return (trtp_rtcp_packet_t*)trtp_rtcp_report_sr_deserialize(data, size); - case trtp_rtcp_packet_type_sdes: return (trtp_rtcp_packet_t*)trtp_rtcp_report_sdes_deserialize(data, size); - case trtp_rtcp_packet_type_bye: return (trtp_rtcp_packet_t*)trtp_rtcp_report_bye_deserialize(data, size); - case trtp_rtcp_packet_type_rtpfb: return (trtp_rtcp_packet_t*)trtp_rtcp_report_rtpfb_deserialize(data, size); - case trtp_rtcp_packet_type_psfb: return (trtp_rtcp_packet_t*)trtp_rtcp_report_psfb_deserialize(data, size); - default: - { - // returns abstract RTCP packet - trtp_rtcp_header_t* header; - TSK_DEBUG_ERROR("%d not recognized as valid RTCP packet type", (int)type); - if((header = trtp_rtcp_header_deserialize(data, size))){ - trtp_rtcp_packet_t* packet = trtp_rtcp_packet_create(header); - TSK_OBJECT_SAFE_FREE(header); - return packet; - } - break; - } - } - - return tsk_null; + trtp_rtcp_packet_type_t type; + + if(!data || size < TRTP_RTCP_HEADER_SIZE) { + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_null; + } + + type = (trtp_rtcp_packet_type_t)((const uint8_t*)data)[1]; + + switch(type) { + case trtp_rtcp_packet_type_rr: + return (trtp_rtcp_packet_t*)trtp_rtcp_report_rr_deserialize(data, size); + case trtp_rtcp_packet_type_sr: + return (trtp_rtcp_packet_t*)trtp_rtcp_report_sr_deserialize(data, size); + case trtp_rtcp_packet_type_sdes: + return (trtp_rtcp_packet_t*)trtp_rtcp_report_sdes_deserialize(data, size); + case trtp_rtcp_packet_type_bye: + return (trtp_rtcp_packet_t*)trtp_rtcp_report_bye_deserialize(data, size); + case trtp_rtcp_packet_type_rtpfb: + return (trtp_rtcp_packet_t*)trtp_rtcp_report_rtpfb_deserialize(data, size); + case trtp_rtcp_packet_type_psfb: + return (trtp_rtcp_packet_t*)trtp_rtcp_report_psfb_deserialize(data, size); + default: { + // returns abstract RTCP packet + trtp_rtcp_header_t* header; + TSK_DEBUG_ERROR("%d not recognized as valid RTCP packet type", (int)type); + if((header = trtp_rtcp_header_deserialize(data, size))) { + trtp_rtcp_packet_t* packet = trtp_rtcp_packet_create(header); + TSK_OBJECT_SAFE_FREE(header); + return packet; + } + break; + } + } + + return tsk_null; } int trtp_rtcp_packet_serialize_to(const trtp_rtcp_packet_t* self, void* data, tsk_size_t size) { - if(!self || !self->header || !data || !size){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - switch(self->header->type){ - case trtp_rtcp_packet_type_rr: return trtp_rtcp_report_rr_serialize_to((const trtp_rtcp_report_rr_t*)self, data, size); - case trtp_rtcp_packet_type_sr: return trtp_rtcp_report_sr_serialize_to((const trtp_rtcp_report_sr_t*)self, data, size); - case trtp_rtcp_packet_type_sdes: return trtp_rtcp_report_sdes_serialize_to((const trtp_rtcp_report_sdes_t*)self, data, size); - case trtp_rtcp_packet_type_bye: return trtp_rtcp_report_bye_serialize_to((const trtp_rtcp_report_bye_t*)self, data, size); - case trtp_rtcp_packet_type_psfb: return trtp_rtcp_report_psfb_serialize_to((const trtp_rtcp_report_psfb_t*)self, data, size); - case trtp_rtcp_packet_type_rtpfb: return trtp_rtcp_report_rtpfb_serialize_to((const trtp_rtcp_report_rtpfb_t*)self, data, size); - default: - { - TSK_DEBUG_ERROR("%d not recognized as valid RTCP packet type", (int)self->header->type); - return -2; - } - } + if(!self || !self->header || !data || !size) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + switch(self->header->type) { + case trtp_rtcp_packet_type_rr: + return trtp_rtcp_report_rr_serialize_to((const trtp_rtcp_report_rr_t*)self, data, size); + case trtp_rtcp_packet_type_sr: + return trtp_rtcp_report_sr_serialize_to((const trtp_rtcp_report_sr_t*)self, data, size); + case trtp_rtcp_packet_type_sdes: + return trtp_rtcp_report_sdes_serialize_to((const trtp_rtcp_report_sdes_t*)self, data, size); + case trtp_rtcp_packet_type_bye: + return trtp_rtcp_report_bye_serialize_to((const trtp_rtcp_report_bye_t*)self, data, size); + case trtp_rtcp_packet_type_psfb: + return trtp_rtcp_report_psfb_serialize_to((const trtp_rtcp_report_psfb_t*)self, data, size); + case trtp_rtcp_packet_type_rtpfb: + return trtp_rtcp_report_rtpfb_serialize_to((const trtp_rtcp_report_rtpfb_t*)self, data, size); + default: { + TSK_DEBUG_ERROR("%d not recognized as valid RTCP packet type", (int)self->header->type); + return -2; + } + } } tsk_buffer_t* trtp_rtcp_packet_serialize(const trtp_rtcp_packet_t* self, tsk_size_t num_bytes_pad) { - tsk_size_t size = trtp_rtcp_packet_get_size(self); - if(self && size){ - tsk_buffer_t* buffer; - const tsk_size_t _size = (size + num_bytes_pad); - if((buffer = tsk_buffer_create(tsk_null, _size))){ - if(trtp_rtcp_packet_serialize_to(self, buffer->data, size) != 0){ - TSK_OBJECT_SAFE_FREE(buffer); - } - else buffer->size = size; - return buffer; - } - } - return tsk_null; + tsk_size_t size = trtp_rtcp_packet_get_size(self); + if(self && size) { + tsk_buffer_t* buffer; + const tsk_size_t _size = (size + num_bytes_pad); + if((buffer = tsk_buffer_create(tsk_null, _size))) { + if(trtp_rtcp_packet_serialize_to(self, buffer->data, size) != 0) { + TSK_OBJECT_SAFE_FREE(buffer); + } + else { + buffer->size = size; + } + return buffer; + } + } + return tsk_null; } int trtp_rtcp_packet_add_packet(trtp_rtcp_packet_t* self, trtp_rtcp_packet_t* packet, tsk_bool_t front) { - trtp_rtcp_packets_L_t* packets = tsk_null; - if(!self || !self->header || !packet){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - switch(self->header->type){ - case trtp_rtcp_packet_type_rr: packets = ((trtp_rtcp_report_rr_t*)self)->packets; break; - case trtp_rtcp_packet_type_sr: packets = ((trtp_rtcp_report_sr_t*)self)->packets; break; - case trtp_rtcp_packet_type_bye: packets = ((trtp_rtcp_report_bye_t*)self)->packets; break; - default: TSK_DEBUG_ERROR("not valid operation for packet type %d", (int)self->header->type); return -2; - } - - if(packets){ - //tsk_size_t packet_size = trtp_rtcp_packet_get_size(packet); - packet = tsk_object_ref(packet); - // self->header->length_in_bytes += packet_size; - // self->header->length_in_words_minus1 = ((self->header->length_in_bytes >> 2) - 1) + - // ((self->header->length_in_bytes & 0x03) ? 1 : 0); - tsk_list_push_data(packets, (void**)&packet, !front); - } - - return 0; + trtp_rtcp_packets_L_t* packets = tsk_null; + if(!self || !self->header || !packet) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + switch(self->header->type) { + case trtp_rtcp_packet_type_rr: + packets = ((trtp_rtcp_report_rr_t*)self)->packets; + break; + case trtp_rtcp_packet_type_sr: + packets = ((trtp_rtcp_report_sr_t*)self)->packets; + break; + case trtp_rtcp_packet_type_bye: + packets = ((trtp_rtcp_report_bye_t*)self)->packets; + break; + default: + TSK_DEBUG_ERROR("not valid operation for packet type %d", (int)self->header->type); + return -2; + } + + if(packets) { + //tsk_size_t packet_size = trtp_rtcp_packet_get_size(packet); + packet = tsk_object_ref(packet); + // self->header->length_in_bytes += packet_size; + // self->header->length_in_words_minus1 = ((self->header->length_in_bytes >> 2) - 1) + + // ((self->header->length_in_bytes & 0x03) ? 1 : 0); + tsk_list_push_data(packets, (void**)&packet, !front); + } + + return 0; } const trtp_rtcp_packet_t* trtp_rtcp_packet_get_at(const trtp_rtcp_packet_t* self, trtp_rtcp_packet_type_t type, tsk_size_t index) { - const tsk_list_item_t *item; - const trtp_rtcp_packets_L_t* packets = tsk_null; - tsk_size_t i; - - if(!self || !self->header){ - TSK_DEBUG_ERROR("Invalid parameter"); - return tsk_null; - } - if(self->header->type == type && index == 0){ - return self; - } - switch(self->header->type){ - case trtp_rtcp_packet_type_rr: packets = ((const trtp_rtcp_report_rr_t*)self)->packets; break; - case trtp_rtcp_packet_type_sr: packets = ((const trtp_rtcp_report_sr_t*)self)->packets; break; - case trtp_rtcp_packet_type_bye: packets = ((const trtp_rtcp_report_bye_t*)self)->packets; break; - default: break; - } - - i = 0; - tsk_list_foreach(item, packets){ - if(TRTP_RTCP_PACKET(item->data)->header->type == type && i++ >= index){ - return TRTP_RTCP_PACKET(item->data); - } - } - return tsk_null; + const tsk_list_item_t *item; + const trtp_rtcp_packets_L_t* packets = tsk_null; + tsk_size_t i; + + if(!self || !self->header) { + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_null; + } + if(self->header->type == type && index == 0) { + return self; + } + switch(self->header->type) { + case trtp_rtcp_packet_type_rr: + packets = ((const trtp_rtcp_report_rr_t*)self)->packets; + break; + case trtp_rtcp_packet_type_sr: + packets = ((const trtp_rtcp_report_sr_t*)self)->packets; + break; + case trtp_rtcp_packet_type_bye: + packets = ((const trtp_rtcp_report_bye_t*)self)->packets; + break; + default: + break; + } + + i = 0; + tsk_list_foreach(item, packets) { + if(TRTP_RTCP_PACKET(item->data)->header->type == type && i++ >= index) { + return TRTP_RTCP_PACKET(item->data); + } + } + return tsk_null; } const trtp_rtcp_packet_t* trtp_rtcp_packet_get(const trtp_rtcp_packet_t* self, trtp_rtcp_packet_type_t type) { - return trtp_rtcp_packet_get_at(self, type, 0); + return trtp_rtcp_packet_get_at(self, type, 0); } tsk_size_t trtp_rtcp_packet_get_size(const trtp_rtcp_packet_t* self) { - if(!self || !self->header){ - TSK_DEBUG_ERROR("Invalid parameter"); - return 0; - } - - switch(self->header->type){ - case trtp_rtcp_packet_type_rr: return trtp_rtcp_report_rr_get_size((const trtp_rtcp_report_rr_t*)self); - case trtp_rtcp_packet_type_sr: return trtp_rtcp_report_sr_get_size((const trtp_rtcp_report_sr_t*)self); - case trtp_rtcp_packet_type_sdes: return trtp_rtcp_report_sdes_get_size((const trtp_rtcp_report_sdes_t*)self); - case trtp_rtcp_packet_type_bye: return trtp_rtcp_report_bye_get_size((const trtp_rtcp_report_bye_t*)self); - case trtp_rtcp_packet_type_rtpfb: return trtp_rtcp_report_rtpfb_get_size((const trtp_rtcp_report_rtpfb_t*)self); - case trtp_rtcp_packet_type_psfb: return trtp_rtcp_report_psfb_get_size((const trtp_rtcp_report_psfb_t*)self); - default: - { - TSK_DEBUG_ERROR("%d not recognized as valid RTCP packet type", (int)self->header->type); - return self->header->length_in_bytes; - } - } + if(!self || !self->header) { + TSK_DEBUG_ERROR("Invalid parameter"); + return 0; + } + + switch(self->header->type) { + case trtp_rtcp_packet_type_rr: + return trtp_rtcp_report_rr_get_size((const trtp_rtcp_report_rr_t*)self); + case trtp_rtcp_packet_type_sr: + return trtp_rtcp_report_sr_get_size((const trtp_rtcp_report_sr_t*)self); + case trtp_rtcp_packet_type_sdes: + return trtp_rtcp_report_sdes_get_size((const trtp_rtcp_report_sdes_t*)self); + case trtp_rtcp_packet_type_bye: + return trtp_rtcp_report_bye_get_size((const trtp_rtcp_report_bye_t*)self); + case trtp_rtcp_packet_type_rtpfb: + return trtp_rtcp_report_rtpfb_get_size((const trtp_rtcp_report_rtpfb_t*)self); + case trtp_rtcp_packet_type_psfb: + return trtp_rtcp_report_psfb_get_size((const trtp_rtcp_report_psfb_t*)self); + default: { + TSK_DEBUG_ERROR("%d not recognized as valid RTCP packet type", (int)self->header->type); + return self->header->length_in_bytes; + } + } } int trtp_rtcp_packet_deinit(trtp_rtcp_packet_t* self) { - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - TSK_OBJECT_SAFE_FREE(self->header); - return 0; + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + TSK_OBJECT_SAFE_FREE(self->header); + return 0; } diff --git a/tinyRTP/src/rtcp/trtp_rtcp_rblock.c b/tinyRTP/src/rtcp/trtp_rtcp_rblock.c index 9a85b4b..3c9bc51 100755 --- a/tinyRTP/src/rtcp/trtp_rtcp_rblock.c +++ b/tinyRTP/src/rtcp/trtp_rtcp_rblock.c @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -42,112 +42,111 @@ block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ static tsk_object_t* trtp_rtcp_rblock_ctor(tsk_object_t * self, va_list * app) { - trtp_rtcp_rblock_t *block = self; - if(block){ - } - return self; + trtp_rtcp_rblock_t *block = self; + if(block) { + } + return self; } static tsk_object_t* trtp_rtcp_rblock_dtor(tsk_object_t * self) -{ - trtp_rtcp_rblock_t *block = self; - if(block){ - } +{ + trtp_rtcp_rblock_t *block = self; + if(block) { + } - return self; + return self; } -static const tsk_object_def_t trtp_rtcp_rblock_def_s = -{ - sizeof(trtp_rtcp_rblock_t), - trtp_rtcp_rblock_ctor, - trtp_rtcp_rblock_dtor, - tsk_null, +static const tsk_object_def_t trtp_rtcp_rblock_def_s = { + sizeof(trtp_rtcp_rblock_t), + trtp_rtcp_rblock_ctor, + trtp_rtcp_rblock_dtor, + tsk_null, }; const tsk_object_def_t *trtp_rtcp_rblock_def_t = &trtp_rtcp_rblock_def_s; trtp_rtcp_rblock_t* trtp_rtcp_rblock_create_null() { - return tsk_object_new(trtp_rtcp_rblock_def_t); + return tsk_object_new(trtp_rtcp_rblock_def_t); } trtp_rtcp_rblock_t* trtp_rtcp_rblock_deserialize(const void* data, tsk_size_t size) { - trtp_rtcp_rblock_t* rblock = tsk_null; - const uint8_t* pdata = (const uint8_t*)data; - if(!data || size < TRTP_RTCP_RBLOCK_SIZE){ - TSK_DEBUG_ERROR("Invalid parameter"); - return tsk_null; - } - if((rblock = trtp_rtcp_rblock_create_null())){ - rblock->ssrc = (uint32_t)tnet_ntohl_2(pdata); - rblock->fraction = pdata[4]; - rblock->cumulative_no_lost = (tnet_ntohl_2(&pdata[5]) >> 8) & 0xFFFFFF; - rblock->last_seq = (uint32_t)tnet_ntohl_2(&pdata[8]); - rblock->jitter = (uint32_t)tnet_ntohl_2(&pdata[12]); - rblock->lsr = (uint32_t)tnet_ntohl_2(&pdata[16]); - rblock->dlsr = (uint32_t)tnet_ntohl_2(&pdata[20]); - } - else{ - TSK_DEBUG_ERROR("Failed to create report block object"); - } + trtp_rtcp_rblock_t* rblock = tsk_null; + const uint8_t* pdata = (const uint8_t*)data; + if(!data || size < TRTP_RTCP_RBLOCK_SIZE) { + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_null; + } + if((rblock = trtp_rtcp_rblock_create_null())) { + rblock->ssrc = (uint32_t)tnet_ntohl_2(pdata); + rblock->fraction = pdata[4]; + rblock->cumulative_no_lost = (tnet_ntohl_2(&pdata[5]) >> 8) & 0xFFFFFF; + rblock->last_seq = (uint32_t)tnet_ntohl_2(&pdata[8]); + rblock->jitter = (uint32_t)tnet_ntohl_2(&pdata[12]); + rblock->lsr = (uint32_t)tnet_ntohl_2(&pdata[16]); + rblock->dlsr = (uint32_t)tnet_ntohl_2(&pdata[20]); + } + else { + TSK_DEBUG_ERROR("Failed to create report block object"); + } - return rblock; + return rblock; } // Up to the int trtp_rtcp_rblock_deserialize_list(const void* data, tsk_size_t _size, trtp_rtcp_rblocks_L_t* dest_list) { - int32_t size = (int32_t)_size; - const uint8_t* pdata = (const uint8_t*)data; - trtp_rtcp_rblock_t* rblock; + int32_t size = (int32_t)_size; + const uint8_t* pdata = (const uint8_t*)data; + trtp_rtcp_rblock_t* rblock; - if(!data || !size || !dest_list){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if(!data || !size || !dest_list) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - while(size >= TRTP_RTCP_RBLOCK_SIZE){ - if((rblock = trtp_rtcp_rblock_deserialize(pdata, size))){ - tsk_list_push_back_data(dest_list, (void**)&rblock); - } - if((size -= TRTP_RTCP_RBLOCK_SIZE) > 0){ - pdata += TRTP_RTCP_RBLOCK_SIZE; - } - } - return 0; + while(size >= TRTP_RTCP_RBLOCK_SIZE) { + if((rblock = trtp_rtcp_rblock_deserialize(pdata, size))) { + tsk_list_push_back_data(dest_list, (void**)&rblock); + } + if((size -= TRTP_RTCP_RBLOCK_SIZE) > 0) { + pdata += TRTP_RTCP_RBLOCK_SIZE; + } + } + return 0; } int trtp_rtcp_rblock_serialize_to(const trtp_rtcp_rblock_t* self, void* data, tsk_size_t size) { - uint8_t* pdata = (uint8_t*)data; - if(!self || !data || size < TRTP_RTCP_RBLOCK_SIZE){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + uint8_t* pdata = (uint8_t*)data; + if(!self || !data || size < TRTP_RTCP_RBLOCK_SIZE) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - pdata[0] = self->ssrc >> 24; - pdata[1] = (self->ssrc >> 16) & 0xFF; - pdata[2] = (self->ssrc >> 8) & 0xFF; - pdata[3] = (self->ssrc & 0xFF); - pdata[4] = self->fraction; - pdata[5] = (self->cumulative_no_lost >> 16) & 0xFF; - pdata[6] = (self->cumulative_no_lost >> 8) & 0xFF; - pdata[7] = (self->cumulative_no_lost & 0xFF); - pdata[8] = self->last_seq >> 24; - pdata[9] = (self->last_seq >> 16) & 0xFF; - pdata[10] = (self->last_seq >> 8) & 0xFF; - pdata[11] = (self->last_seq & 0xFF); - pdata[12] = self->jitter >> 24; - pdata[13] = (self->jitter >> 16) & 0xFF; - pdata[14] = (self->jitter >> 8) & 0xFF; - pdata[15] = (self->jitter & 0xFF); - pdata[16] = self->lsr >> 24; - pdata[17] = (self->lsr >> 16) & 0xFF; - pdata[18] = (self->lsr >> 8) & 0xFF; - pdata[19] = (self->lsr & 0xFF); - pdata[20] = self->dlsr >> 24; - pdata[21] = (self->dlsr >> 16) & 0xFF; - pdata[22] = (self->dlsr >> 8) & 0xFF; - pdata[23] = (self->dlsr & 0xFF); + pdata[0] = self->ssrc >> 24; + pdata[1] = (self->ssrc >> 16) & 0xFF; + pdata[2] = (self->ssrc >> 8) & 0xFF; + pdata[3] = (self->ssrc & 0xFF); + pdata[4] = self->fraction; + pdata[5] = (self->cumulative_no_lost >> 16) & 0xFF; + pdata[6] = (self->cumulative_no_lost >> 8) & 0xFF; + pdata[7] = (self->cumulative_no_lost & 0xFF); + pdata[8] = self->last_seq >> 24; + pdata[9] = (self->last_seq >> 16) & 0xFF; + pdata[10] = (self->last_seq >> 8) & 0xFF; + pdata[11] = (self->last_seq & 0xFF); + pdata[12] = self->jitter >> 24; + pdata[13] = (self->jitter >> 16) & 0xFF; + pdata[14] = (self->jitter >> 8) & 0xFF; + pdata[15] = (self->jitter & 0xFF); + pdata[16] = self->lsr >> 24; + pdata[17] = (self->lsr >> 16) & 0xFF; + pdata[18] = (self->lsr >> 8) & 0xFF; + pdata[19] = (self->lsr & 0xFF); + pdata[20] = self->dlsr >> 24; + pdata[21] = (self->dlsr >> 16) & 0xFF; + pdata[22] = (self->dlsr >> 8) & 0xFF; + pdata[23] = (self->dlsr & 0xFF); - return 0; + return 0; } \ No newline at end of file diff --git a/tinyRTP/src/rtcp/trtp_rtcp_report.c b/tinyRTP/src/rtcp/trtp_rtcp_report.c index 5fb2697..41e177b 100755 --- a/tinyRTP/src/rtcp/trtp_rtcp_report.c +++ b/tinyRTP/src/rtcp/trtp_rtcp_report.c @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * diff --git a/tinyRTP/src/rtcp/trtp_rtcp_report_bye.c b/tinyRTP/src/rtcp/trtp_rtcp_report_bye.c index 0f44608..9085160 100755 --- a/tinyRTP/src/rtcp/trtp_rtcp_report_bye.c +++ b/tinyRTP/src/rtcp/trtp_rtcp_report_bye.c @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -31,195 +31,194 @@ static tsk_object_t* trtp_rtcp_report_bye_ctor(tsk_object_t * self, va_list * app) { - trtp_rtcp_report_bye_t *bye = self; - if(bye){ - bye->packets = tsk_list_create(); - } - return self; + trtp_rtcp_report_bye_t *bye = self; + if(bye) { + bye->packets = tsk_list_create(); + } + return self; } static tsk_object_t* trtp_rtcp_report_bye_dtor(tsk_object_t * self) -{ - trtp_rtcp_report_bye_t *bye = self; - if(bye){ - // deinit self - TSK_OBJECT_SAFE_FREE(bye->packets); - TSK_FREE(bye->ssrc_list); - // deinit base - trtp_rtcp_packet_deinit(TRTP_RTCP_PACKET(bye)); - } - - return self; +{ + trtp_rtcp_report_bye_t *bye = self; + if(bye) { + // deinit self + TSK_OBJECT_SAFE_FREE(bye->packets); + TSK_FREE(bye->ssrc_list); + // deinit base + trtp_rtcp_packet_deinit(TRTP_RTCP_PACKET(bye)); + } + + return self; } -static const tsk_object_def_t trtp_rtcp_report_bye_def_s = -{ - sizeof(trtp_rtcp_report_bye_t), - trtp_rtcp_report_bye_ctor, - trtp_rtcp_report_bye_dtor, - tsk_null, +static const tsk_object_def_t trtp_rtcp_report_bye_def_s = { + sizeof(trtp_rtcp_report_bye_t), + trtp_rtcp_report_bye_ctor, + trtp_rtcp_report_bye_dtor, + tsk_null, }; const tsk_object_def_t *trtp_rtcp_report_bye_def_t = &trtp_rtcp_report_bye_def_s; trtp_rtcp_report_bye_t* trtp_rtcp_report_bye_create_null() { - trtp_rtcp_report_bye_t* bye; - if((bye = (trtp_rtcp_report_bye_t*)tsk_object_new(trtp_rtcp_report_bye_def_t))){ - trtp_rtcp_packet_init(TRTP_RTCP_PACKET(bye), TRTP_RTCP_HEADER_VERSION_DEFAULT, 0, 0, trtp_rtcp_packet_type_bye, TRTP_RTCP_HEADER_SIZE); - } - return bye; + trtp_rtcp_report_bye_t* bye; + if((bye = (trtp_rtcp_report_bye_t*)tsk_object_new(trtp_rtcp_report_bye_def_t))) { + trtp_rtcp_packet_init(TRTP_RTCP_PACKET(bye), TRTP_RTCP_HEADER_VERSION_DEFAULT, 0, 0, trtp_rtcp_packet_type_bye, TRTP_RTCP_HEADER_SIZE); + } + return bye; } trtp_rtcp_report_bye_t* trtp_rtcp_report_bye_create(struct trtp_rtcp_header_s* header) { - trtp_rtcp_report_bye_t* bye; - if((bye = (trtp_rtcp_report_bye_t*)tsk_object_new(trtp_rtcp_report_bye_def_t))){ - TRTP_RTCP_PACKET(bye)->header = tsk_object_ref(header); - } - return bye; + trtp_rtcp_report_bye_t* bye; + if((bye = (trtp_rtcp_report_bye_t*)tsk_object_new(trtp_rtcp_report_bye_def_t))) { + TRTP_RTCP_PACKET(bye)->header = tsk_object_ref(header); + } + return bye; } trtp_rtcp_report_bye_t* trtp_rtcp_report_bye_create_2(uint32_t ssrc) { - uint32_t* ssrc_list = tsk_malloc(sizeof(uint32_t)); - if(ssrc_list){ - trtp_rtcp_report_bye_t* bye; - if((bye = (trtp_rtcp_report_bye_t*)tsk_object_new(trtp_rtcp_report_bye_def_t))){ - trtp_rtcp_packet_init(TRTP_RTCP_PACKET(bye), TRTP_RTCP_HEADER_VERSION_DEFAULT, 0, 0, trtp_rtcp_packet_type_bye, (TRTP_RTCP_HEADER_SIZE + 4)); - TRTP_RTCP_PACKET(bye)->header->rc = 1; - *ssrc_list = ssrc, bye->ssrc_list = ssrc_list, ssrc_list = tsk_null; - } - TSK_FREE(ssrc_list); - return bye; - } - return tsk_null; + uint32_t* ssrc_list = tsk_malloc(sizeof(uint32_t)); + if(ssrc_list) { + trtp_rtcp_report_bye_t* bye; + if((bye = (trtp_rtcp_report_bye_t*)tsk_object_new(trtp_rtcp_report_bye_def_t))) { + trtp_rtcp_packet_init(TRTP_RTCP_PACKET(bye), TRTP_RTCP_HEADER_VERSION_DEFAULT, 0, 0, trtp_rtcp_packet_type_bye, (TRTP_RTCP_HEADER_SIZE + 4)); + TRTP_RTCP_PACKET(bye)->header->rc = 1; + *ssrc_list = ssrc, bye->ssrc_list = ssrc_list, ssrc_list = tsk_null; + } + TSK_FREE(ssrc_list); + return bye; + } + return tsk_null; } trtp_rtcp_report_bye_t* trtp_rtcp_report_bye_deserialize(const void* data, tsk_size_t _size) { - trtp_rtcp_report_bye_t* bye = tsk_null; - trtp_rtcp_header_t* header = tsk_null; - const uint8_t* pdata = (const uint8_t*)data; - int32_t size = (int32_t)_size; - - if(!data || size < TRTP_RTCP_PACKET_BYE_MIN_SIZE){ - TSK_DEBUG_ERROR("Invalid parameter"); - return tsk_null; - } - - if(!(header = trtp_rtcp_header_deserialize(pdata, size))){ - TSK_DEBUG_ERROR("Failed to deserialize the header"); - goto bail; - } - if(header->length_in_bytes < TRTP_RTCP_PACKET_BYE_MIN_SIZE){ - TSK_DEBUG_ERROR("Too short"); - goto bail; - } - - if(!(bye = trtp_rtcp_report_bye_create(header))){ - TSK_DEBUG_ERROR("Failed to create object"); - goto bail; - } - - pdata += (TRTP_RTCP_HEADER_SIZE); - size -= (TRTP_RTCP_HEADER_SIZE); - - // SSRCs - if(header->rc > 0){ - tsk_size_t i; - if((int32_t)(header->rc * sizeof(uint32_t)) > size){ - TSK_DEBUG_ERROR("Too short"); - goto bail; - } - if(!(bye->ssrc_list = tsk_calloc(header->rc, sizeof(uint32_t)))){ - goto bail; - } - for(i = 0; i < header->rc; ++i){ - bye->ssrc_list[i] = (uint32_t)tnet_ntohl_2(&pdata[0]); - pdata += sizeof(uint32_t); - size -= sizeof(uint32_t); - } - } - - // Other Packets - while(size > TRTP_RTCP_HEADER_SIZE){ - trtp_rtcp_packet_t* packet; - - if((packet = trtp_rtcp_packet_deserialize(pdata, size))){ - if((size -= packet->header->length_in_bytes) > 0){ - pdata += packet->header->length_in_bytes; - } - tsk_list_push_back_data(bye->packets, (void**)&packet); - continue; - } - break; - } + trtp_rtcp_report_bye_t* bye = tsk_null; + trtp_rtcp_header_t* header = tsk_null; + const uint8_t* pdata = (const uint8_t*)data; + int32_t size = (int32_t)_size; + + if(!data || size < TRTP_RTCP_PACKET_BYE_MIN_SIZE) { + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_null; + } + + if(!(header = trtp_rtcp_header_deserialize(pdata, size))) { + TSK_DEBUG_ERROR("Failed to deserialize the header"); + goto bail; + } + if(header->length_in_bytes < TRTP_RTCP_PACKET_BYE_MIN_SIZE) { + TSK_DEBUG_ERROR("Too short"); + goto bail; + } + + if(!(bye = trtp_rtcp_report_bye_create(header))) { + TSK_DEBUG_ERROR("Failed to create object"); + goto bail; + } + + pdata += (TRTP_RTCP_HEADER_SIZE); + size -= (TRTP_RTCP_HEADER_SIZE); + + // SSRCs + if(header->rc > 0) { + tsk_size_t i; + if((int32_t)(header->rc * sizeof(uint32_t)) > size) { + TSK_DEBUG_ERROR("Too short"); + goto bail; + } + if(!(bye->ssrc_list = tsk_calloc(header->rc, sizeof(uint32_t)))) { + goto bail; + } + for(i = 0; i < header->rc; ++i) { + bye->ssrc_list[i] = (uint32_t)tnet_ntohl_2(&pdata[0]); + pdata += sizeof(uint32_t); + size -= sizeof(uint32_t); + } + } + + // Other Packets + while(size > TRTP_RTCP_HEADER_SIZE) { + trtp_rtcp_packet_t* packet; + + if((packet = trtp_rtcp_packet_deserialize(pdata, size))) { + if((size -= packet->header->length_in_bytes) > 0) { + pdata += packet->header->length_in_bytes; + } + tsk_list_push_back_data(bye->packets, (void**)&packet); + continue; + } + break; + } bail: - TSK_OBJECT_SAFE_FREE(header); - return bye; + TSK_OBJECT_SAFE_FREE(header); + return bye; } int trtp_rtcp_report_bye_serialize_to(const trtp_rtcp_report_bye_t* self, void* data, tsk_size_t size) { - int ret; - tsk_size_t i; - uint8_t* pdata = (uint8_t*)data; - const tsk_list_item_t* item; - - if(!self || !data || size < trtp_rtcp_report_bye_get_size(self)){ - return -1; - } - - if((ret = trtp_rtcp_header_serialize_to(TRTP_RTCP_PACKET(self)->header, pdata, size))){ - TSK_DEBUG_ERROR("Failed to serialize the header"); - return ret; - } - - pdata += (TRTP_RTCP_HEADER_SIZE); - size -= (TRTP_RTCP_HEADER_SIZE); - - for(i = 0; i < TRTP_RTCP_PACKET(self)->header->rc; ++i){ - pdata[0] = self->ssrc_list[i] >> 24; - pdata[1] = (self->ssrc_list[i] >> 16) & 0xFF; - pdata[2] = (self->ssrc_list[i] >> 8) & 0xFF; - pdata[3] = (self->ssrc_list[i] & 0xFF); - pdata += 4; - size -= 4; - } - - tsk_list_foreach(item, self->packets){ - if(!item->data){ - continue; - } - if((ret = trtp_rtcp_packet_serialize_to(TRTP_RTCP_PACKET(item->data), pdata, size))){ - TSK_DEBUG_ERROR("Failed to serialize packet"); - goto bail; - } - pdata += TRTP_RTCP_PACKET(item->data)->header->length_in_bytes; - size -= TRTP_RTCP_PACKET(item->data)->header->length_in_bytes; - } + int ret; + tsk_size_t i; + uint8_t* pdata = (uint8_t*)data; + const tsk_list_item_t* item; + + if(!self || !data || size < trtp_rtcp_report_bye_get_size(self)) { + return -1; + } + + if((ret = trtp_rtcp_header_serialize_to(TRTP_RTCP_PACKET(self)->header, pdata, size))) { + TSK_DEBUG_ERROR("Failed to serialize the header"); + return ret; + } + + pdata += (TRTP_RTCP_HEADER_SIZE); + size -= (TRTP_RTCP_HEADER_SIZE); + + for(i = 0; i < TRTP_RTCP_PACKET(self)->header->rc; ++i) { + pdata[0] = self->ssrc_list[i] >> 24; + pdata[1] = (self->ssrc_list[i] >> 16) & 0xFF; + pdata[2] = (self->ssrc_list[i] >> 8) & 0xFF; + pdata[3] = (self->ssrc_list[i] & 0xFF); + pdata += 4; + size -= 4; + } + + tsk_list_foreach(item, self->packets) { + if(!item->data) { + continue; + } + if((ret = trtp_rtcp_packet_serialize_to(TRTP_RTCP_PACKET(item->data), pdata, size))) { + TSK_DEBUG_ERROR("Failed to serialize packet"); + goto bail; + } + pdata += TRTP_RTCP_PACKET(item->data)->header->length_in_bytes; + size -= TRTP_RTCP_PACKET(item->data)->header->length_in_bytes; + } bail: - return ret; + return ret; } tsk_size_t trtp_rtcp_report_bye_get_size(const trtp_rtcp_report_bye_t* self) { - tsk_size_t size; - const tsk_list_item_t* item; - - if(!self || !TRTP_RTCP_PACKET(self)->header){ - TSK_DEBUG_ERROR("Invalid parameter"); - return 0; - } - - size = TRTP_RTCP_PACKET(self)->header->length_in_bytes; - tsk_list_foreach(item, self->packets){ - if(item->data && TRTP_RTCP_PACKET(item->data)->header){ - size += TRTP_RTCP_PACKET(item->data)->header->length_in_bytes; - } - } - - return size; + tsk_size_t size; + const tsk_list_item_t* item; + + if(!self || !TRTP_RTCP_PACKET(self)->header) { + TSK_DEBUG_ERROR("Invalid parameter"); + return 0; + } + + size = TRTP_RTCP_PACKET(self)->header->length_in_bytes; + tsk_list_foreach(item, self->packets) { + if(item->data && TRTP_RTCP_PACKET(item->data)->header) { + size += TRTP_RTCP_PACKET(item->data)->header->length_in_bytes; + } + } + + return size; } diff --git a/tinyRTP/src/rtcp/trtp_rtcp_report_fb.c b/tinyRTP/src/rtcp/trtp_rtcp_report_fb.c index bbc80b1..bb6690e 100755 --- a/tinyRTP/src/rtcp/trtp_rtcp_report_fb.c +++ b/tinyRTP/src/rtcp/trtp_rtcp_report_fb.c @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WArtpfbANTY; without even the implied wartpfbanty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -35,270 +35,274 @@ static int _trtp_rtcp_report_fb_deserialize(const void* data, tsk_size_t _size, trtp_rtcp_header_t** header, uint32_t* ssrc_sender, uint32_t* ssrc_media_src) { - const uint8_t* pdata = data; - if(!data || !header || _size < TRTP_RTCP_PACKET_FB_MIN_SIZE || (_size & 0x03)){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - if(!(*header = trtp_rtcp_header_deserialize(pdata, _size))){ - TSK_DEBUG_ERROR("Failed to deserialize the header"); - return -3; - } - if((*header)->length_in_bytes < TRTP_RTCP_PACKET_FB_MIN_SIZE){ - TSK_DEBUG_ERROR("Too short"); - return -4; - } - else if((*header)->length_in_bytes > _size){ - TSK_DEBUG_ERROR("Too long"); - return -5; - } - - *ssrc_sender = (uint32_t)tnet_ntohl_2(&pdata[4]); - *ssrc_media_src = (uint32_t)tnet_ntohl_2(&pdata[8]); - return 0; + const uint8_t* pdata = data; + if(!data || !header || _size < TRTP_RTCP_PACKET_FB_MIN_SIZE || (_size & 0x03)) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + if(!(*header = trtp_rtcp_header_deserialize(pdata, _size))) { + TSK_DEBUG_ERROR("Failed to deserialize the header"); + return -3; + } + if((*header)->length_in_bytes < TRTP_RTCP_PACKET_FB_MIN_SIZE) { + TSK_DEBUG_ERROR("Too short"); + return -4; + } + else if((*header)->length_in_bytes > _size) { + TSK_DEBUG_ERROR("Too long"); + return -5; + } + + *ssrc_sender = (uint32_t)tnet_ntohl_2(&pdata[4]); + *ssrc_media_src = (uint32_t)tnet_ntohl_2(&pdata[8]); + return 0; } static int _trtp_rtcp_report_fb_serialize_to(const trtp_rtcp_report_fb_t* self, void* data, tsk_size_t size) { - int ret; - uint8_t* pdata = (uint8_t*)data; - - if(!self || !data || size < TRTP_RTCP_PACKET_FB_MIN_SIZE){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if((ret = trtp_rtcp_header_serialize_to(TRTP_RTCP_PACKET(self)->header, pdata, size))){ - TSK_DEBUG_ERROR("Failed to serialize the header"); - return ret; - } - - pdata[TRTP_RTCP_HEADER_SIZE] = self->ssrc_sender >> 24; - pdata[TRTP_RTCP_HEADER_SIZE + 1] = (self->ssrc_sender >> 16) & 0xFF; - pdata[TRTP_RTCP_HEADER_SIZE + 2] = (self->ssrc_sender >> 8) & 0xFF; - pdata[TRTP_RTCP_HEADER_SIZE + 3] = (self->ssrc_sender & 0xFF); - pdata[TRTP_RTCP_HEADER_SIZE + 4] = self->ssrc_media >> 24; - pdata[TRTP_RTCP_HEADER_SIZE + 5] = (self->ssrc_media >> 16) & 0xFF; - pdata[TRTP_RTCP_HEADER_SIZE + 6] = (self->ssrc_media >> 8) & 0xFF; - pdata[TRTP_RTCP_HEADER_SIZE + 7] = (self->ssrc_media & 0xFF); - - return 0; + int ret; + uint8_t* pdata = (uint8_t*)data; + + if(!self || !data || size < TRTP_RTCP_PACKET_FB_MIN_SIZE) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if((ret = trtp_rtcp_header_serialize_to(TRTP_RTCP_PACKET(self)->header, pdata, size))) { + TSK_DEBUG_ERROR("Failed to serialize the header"); + return ret; + } + + pdata[TRTP_RTCP_HEADER_SIZE] = self->ssrc_sender >> 24; + pdata[TRTP_RTCP_HEADER_SIZE + 1] = (self->ssrc_sender >> 16) & 0xFF; + pdata[TRTP_RTCP_HEADER_SIZE + 2] = (self->ssrc_sender >> 8) & 0xFF; + pdata[TRTP_RTCP_HEADER_SIZE + 3] = (self->ssrc_sender & 0xFF); + pdata[TRTP_RTCP_HEADER_SIZE + 4] = self->ssrc_media >> 24; + pdata[TRTP_RTCP_HEADER_SIZE + 5] = (self->ssrc_media >> 16) & 0xFF; + pdata[TRTP_RTCP_HEADER_SIZE + 6] = (self->ssrc_media >> 8) & 0xFF; + pdata[TRTP_RTCP_HEADER_SIZE + 7] = (self->ssrc_media & 0xFF); + + return 0; } static tsk_object_t* trtp_rtcp_report_rtpfb_ctor(tsk_object_t * self, va_list * app) { - trtp_rtcp_report_rtpfb_t *rtpfb = self; - if(rtpfb){ - - } - return self; + trtp_rtcp_report_rtpfb_t *rtpfb = self; + if(rtpfb) { + + } + return self; } static tsk_object_t* trtp_rtcp_report_rtpfb_dtor(tsk_object_t * self) -{ - trtp_rtcp_report_rtpfb_t *rtpfb = self; - if(rtpfb){ - // deinit self - switch(rtpfb->fci_type){ - case trtp_rtcp_rtpfb_fci_type_nack: - { - TSK_FREE(rtpfb->nack.pid); - TSK_FREE(rtpfb->nack.blp); - break; - } - case trtp_rtcp_rtpfb_fci_type_tmmbn: - { - TSK_FREE(rtpfb->tmmbn.ssrc); - TSK_FREE(rtpfb->tmmbn.MxTBR_Exp); - TSK_FREE(rtpfb->tmmbn.MxTBR_Mantissa); - TSK_FREE(rtpfb->tmmbn.MeasuredOverhead); - break; - } - } - // deinit base - trtp_rtcp_packet_deinit(TRTP_RTCP_PACKET(rtpfb)); - } - - return self; -} -static const tsk_object_def_t trtp_rtcp_report_rtpfb_def_s = { - sizeof(trtp_rtcp_report_rtpfb_t), - trtp_rtcp_report_rtpfb_ctor, - trtp_rtcp_report_rtpfb_dtor, - tsk_null, + trtp_rtcp_report_rtpfb_t *rtpfb = self; + if(rtpfb) { + // deinit self + switch(rtpfb->fci_type) { + case trtp_rtcp_rtpfb_fci_type_nack: { + TSK_FREE(rtpfb->nack.pid); + TSK_FREE(rtpfb->nack.blp); + break; + } + case trtp_rtcp_rtpfb_fci_type_tmmbn: { + TSK_FREE(rtpfb->tmmbn.ssrc); + TSK_FREE(rtpfb->tmmbn.MxTBR_Exp); + TSK_FREE(rtpfb->tmmbn.MxTBR_Mantissa); + TSK_FREE(rtpfb->tmmbn.MeasuredOverhead); + break; + } + } + // deinit base + trtp_rtcp_packet_deinit(TRTP_RTCP_PACKET(rtpfb)); + } + + return self; +} +static const tsk_object_def_t trtp_rtcp_report_rtpfb_def_s = { + sizeof(trtp_rtcp_report_rtpfb_t), + trtp_rtcp_report_rtpfb_ctor, + trtp_rtcp_report_rtpfb_dtor, + tsk_null, }; const tsk_object_def_t *trtp_rtcp_report_rtpfb_def_t = &trtp_rtcp_report_rtpfb_def_s; trtp_rtcp_report_rtpfb_t* trtp_rtcp_report_rtpfb_create_null() { - trtp_rtcp_report_rtpfb_t* rtpfb; - if((rtpfb = (trtp_rtcp_report_rtpfb_t*)tsk_object_new(trtp_rtcp_report_rtpfb_def_t))){ - trtp_rtcp_packet_init(TRTP_RTCP_PACKET(rtpfb), TRTP_RTCP_HEADER_VERSION_DEFAULT, 0, 0, trtp_rtcp_packet_type_rtpfb, TRTP_RTCP_PACKET_FB_MIN_SIZE); - } - return rtpfb; + trtp_rtcp_report_rtpfb_t* rtpfb; + if((rtpfb = (trtp_rtcp_report_rtpfb_t*)tsk_object_new(trtp_rtcp_report_rtpfb_def_t))) { + trtp_rtcp_packet_init(TRTP_RTCP_PACKET(rtpfb), TRTP_RTCP_HEADER_VERSION_DEFAULT, 0, 0, trtp_rtcp_packet_type_rtpfb, TRTP_RTCP_PACKET_FB_MIN_SIZE); + } + return rtpfb; } trtp_rtcp_report_rtpfb_t* trtp_rtcp_report_rtpfb_create(trtp_rtcp_header_t* header) { - trtp_rtcp_report_rtpfb_t* rtpfb; - if((rtpfb = (trtp_rtcp_report_rtpfb_t*)tsk_object_new(trtp_rtcp_report_rtpfb_def_t))){ - TRTP_RTCP_PACKET(rtpfb)->header = tsk_object_ref(header); - } - return rtpfb; + trtp_rtcp_report_rtpfb_t* rtpfb; + if((rtpfb = (trtp_rtcp_report_rtpfb_t*)tsk_object_new(trtp_rtcp_report_rtpfb_def_t))) { + TRTP_RTCP_PACKET(rtpfb)->header = tsk_object_ref(header); + } + return rtpfb; } trtp_rtcp_report_rtpfb_t* trtp_rtcp_report_rtpfb_create_2(trtp_rtcp_rtpfb_fci_type_t fci_type, uint32_t ssrc_sender, uint32_t ssrc_media_src) { - trtp_rtcp_report_rtpfb_t* rtpfb; - if((rtpfb = trtp_rtcp_report_rtpfb_create_null())){ - rtpfb->fci_type = TRTP_RTCP_PACKET(rtpfb)->header->rc = fci_type; - TRTP_RTCP_REPORT_FB(rtpfb)->ssrc_sender = ssrc_sender; - TRTP_RTCP_REPORT_FB(rtpfb)->ssrc_media = ssrc_media_src; - } - return rtpfb; + trtp_rtcp_report_rtpfb_t* rtpfb; + if((rtpfb = trtp_rtcp_report_rtpfb_create_null())) { + rtpfb->fci_type = TRTP_RTCP_PACKET(rtpfb)->header->rc = fci_type; + TRTP_RTCP_REPORT_FB(rtpfb)->ssrc_sender = ssrc_sender; + TRTP_RTCP_REPORT_FB(rtpfb)->ssrc_media = ssrc_media_src; + } + return rtpfb; } // seq_nums[n] must be in [seq_nums[0], seq_nums[0] + 16] and > seq_nums[n - 1] trtp_rtcp_report_rtpfb_t* trtp_rtcp_report_rtpfb_create_nack(uint32_t ssrc_sender, uint32_t ssrc_media_src, const uint16_t* seq_nums, tsk_size_t count) { - trtp_rtcp_report_rtpfb_t* rtpfb; - if(!seq_nums || !count){ - TSK_DEBUG_ERROR("Invalid parameter"); - return tsk_null; - } - if((rtpfb = trtp_rtcp_report_rtpfb_create_2(trtp_rtcp_rtpfb_fci_type_nack, ssrc_sender, ssrc_media_src))){ - tsk_size_t i, j; - rtpfb->nack.count = 1; // max = 16 - rtpfb->nack.blp = tsk_malloc(sizeof(uint16_t)); - rtpfb->nack.pid = tsk_malloc(sizeof(uint16_t)); - if(!rtpfb->nack.blp || !rtpfb->nack.pid){ - TSK_OBJECT_SAFE_FREE(rtpfb); - return tsk_null; - } - rtpfb->nack.pid[0] = seq_nums[0]; - rtpfb->nack.blp[0] = 0; - for(i = 1; i <= 16 && i < count; ++i){ - j = seq_nums[i] - rtpfb->nack.pid[0]; - rtpfb->nack.blp[0] |= (1 << (j - 1)); - } - - TRTP_RTCP_PACKET(rtpfb)->header->length_in_bytes += (uint32_t)(rtpfb->nack.count << 2); - TRTP_RTCP_PACKET(rtpfb)->header->length_in_words_minus1 = ((TRTP_RTCP_PACKET(rtpfb)->header->length_in_bytes >> 2) - 1); - } - return rtpfb; + trtp_rtcp_report_rtpfb_t* rtpfb; + if(!seq_nums || !count) { + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_null; + } + if((rtpfb = trtp_rtcp_report_rtpfb_create_2(trtp_rtcp_rtpfb_fci_type_nack, ssrc_sender, ssrc_media_src))) { + tsk_size_t i, j; + rtpfb->nack.count = 1; // max = 16 + rtpfb->nack.blp = tsk_malloc(sizeof(uint16_t)); + rtpfb->nack.pid = tsk_malloc(sizeof(uint16_t)); + if(!rtpfb->nack.blp || !rtpfb->nack.pid) { + TSK_OBJECT_SAFE_FREE(rtpfb); + return tsk_null; + } + rtpfb->nack.pid[0] = seq_nums[0]; + rtpfb->nack.blp[0] = 0; + for(i = 1; i <= 16 && i < count; ++i) { + j = seq_nums[i] - rtpfb->nack.pid[0]; + rtpfb->nack.blp[0] |= (1 << (j - 1)); + } + + TRTP_RTCP_PACKET(rtpfb)->header->length_in_bytes += (uint32_t)(rtpfb->nack.count << 2); + TRTP_RTCP_PACKET(rtpfb)->header->length_in_words_minus1 = ((TRTP_RTCP_PACKET(rtpfb)->header->length_in_bytes >> 2) - 1); + } + return rtpfb; } trtp_rtcp_report_rtpfb_t* trtp_rtcp_report_rtpfb_deserialize(const void* data, tsk_size_t _size) { - trtp_rtcp_report_rtpfb_t* rtpfb = tsk_null; - trtp_rtcp_header_t* header = tsk_null; - uint32_t ssrc_sender, ssrc_media_src; - - if(_trtp_rtcp_report_fb_deserialize(data, _size, &header, &ssrc_sender, &ssrc_media_src) == 0){ - if((rtpfb = trtp_rtcp_report_rtpfb_create(header))){ - const uint8_t* pdata = ((const uint8_t*)data) + TRTP_RTCP_PACKET_FB_MIN_SIZE; - tsk_size_t size = (header->length_in_bytes - TRTP_RTCP_PACKET_FB_MIN_SIZE), i; - - TRTP_RTCP_REPORT_FB(rtpfb)->ssrc_sender = ssrc_sender; - TRTP_RTCP_REPORT_FB(rtpfb)->ssrc_media = ssrc_media_src; - - switch(rtpfb->fci_type = (trtp_rtcp_rtpfb_fci_type_t)header->rc){ - case trtp_rtcp_rtpfb_fci_type_nack: - { - if((rtpfb->nack.count = (size >> 2)) > 0){ - rtpfb->nack.pid = tsk_realloc(rtpfb->nack.pid, (rtpfb->nack.count * sizeof(uint16_t))); - rtpfb->nack.blp = tsk_realloc(rtpfb->nack.blp, (rtpfb->nack.count * sizeof(uint16_t))); - for(i = 0; i < rtpfb->nack.count; ++i){ - if(rtpfb->nack.pid) rtpfb->nack.pid[i] = tnet_ntohs_2(&pdata[0]); - if(rtpfb->nack.blp) rtpfb->nack.blp[i] = tnet_ntohs_2(&pdata[2]); - pdata += 4; - } - } - break; - } - case trtp_rtcp_rtpfb_fci_type_tmmbn: - { - TSK_DEBUG_INFO("TMMBN"); - if((rtpfb->tmmbn.count = (size >> 3)) > 0){ - uint32_t u32; - rtpfb->tmmbn.ssrc = tsk_realloc(rtpfb->tmmbn.ssrc, (rtpfb->tmmbn.count * sizeof(uint32_t))); - rtpfb->tmmbn.MxTBR_Exp = tsk_realloc(rtpfb->tmmbn.MxTBR_Exp, (rtpfb->tmmbn.count * sizeof(uint16_t))); - rtpfb->tmmbn.MxTBR_Mantissa = tsk_realloc(rtpfb->tmmbn.MxTBR_Mantissa, (rtpfb->tmmbn.count * sizeof(uint32_t))); - rtpfb->tmmbn.MeasuredOverhead = tsk_realloc(rtpfb->tmmbn.MeasuredOverhead, (rtpfb->tmmbn.count * sizeof(uint16_t))); - for(i = 0; i < rtpfb->tmmbn.count; ++i){ - if(rtpfb->tmmbn.ssrc) rtpfb->tmmbn.ssrc[i] = (uint32_t)tnet_ntohl_2(&pdata[0]); - u32 = (uint32_t)tnet_ntohl_2(&pdata[4]); - if(rtpfb->tmmbn.MxTBR_Exp) rtpfb->tmmbn.MxTBR_Exp[i] = (u32 >> 26); - if(rtpfb->tmmbn.MxTBR_Mantissa) rtpfb->tmmbn.MxTBR_Mantissa[i] = ((u32 >> 9) & 0x1FFFF); - if(rtpfb->tmmbn.MeasuredOverhead) rtpfb->tmmbn.MeasuredOverhead[i] = (u32 & 0x1FF); - pdata += 8; - } - } - break; - } - - default: - { - TSK_DEBUG_ERROR("Unsupported Feedback message type %d", (int)rtpfb->fci_type); - break; - } - } - } - } - - TSK_OBJECT_SAFE_FREE(header); - return rtpfb; + trtp_rtcp_report_rtpfb_t* rtpfb = tsk_null; + trtp_rtcp_header_t* header = tsk_null; + uint32_t ssrc_sender, ssrc_media_src; + + if(_trtp_rtcp_report_fb_deserialize(data, _size, &header, &ssrc_sender, &ssrc_media_src) == 0) { + if((rtpfb = trtp_rtcp_report_rtpfb_create(header))) { + const uint8_t* pdata = ((const uint8_t*)data) + TRTP_RTCP_PACKET_FB_MIN_SIZE; + tsk_size_t size = (header->length_in_bytes - TRTP_RTCP_PACKET_FB_MIN_SIZE), i; + + TRTP_RTCP_REPORT_FB(rtpfb)->ssrc_sender = ssrc_sender; + TRTP_RTCP_REPORT_FB(rtpfb)->ssrc_media = ssrc_media_src; + + switch(rtpfb->fci_type = (trtp_rtcp_rtpfb_fci_type_t)header->rc) { + case trtp_rtcp_rtpfb_fci_type_nack: { + if((rtpfb->nack.count = (size >> 2)) > 0) { + rtpfb->nack.pid = tsk_realloc(rtpfb->nack.pid, (rtpfb->nack.count * sizeof(uint16_t))); + rtpfb->nack.blp = tsk_realloc(rtpfb->nack.blp, (rtpfb->nack.count * sizeof(uint16_t))); + for(i = 0; i < rtpfb->nack.count; ++i) { + if(rtpfb->nack.pid) { + rtpfb->nack.pid[i] = tnet_ntohs_2(&pdata[0]); + } + if(rtpfb->nack.blp) { + rtpfb->nack.blp[i] = tnet_ntohs_2(&pdata[2]); + } + pdata += 4; + } + } + break; + } + case trtp_rtcp_rtpfb_fci_type_tmmbn: { + TSK_DEBUG_INFO("TMMBN"); + if((rtpfb->tmmbn.count = (size >> 3)) > 0) { + uint32_t u32; + rtpfb->tmmbn.ssrc = tsk_realloc(rtpfb->tmmbn.ssrc, (rtpfb->tmmbn.count * sizeof(uint32_t))); + rtpfb->tmmbn.MxTBR_Exp = tsk_realloc(rtpfb->tmmbn.MxTBR_Exp, (rtpfb->tmmbn.count * sizeof(uint16_t))); + rtpfb->tmmbn.MxTBR_Mantissa = tsk_realloc(rtpfb->tmmbn.MxTBR_Mantissa, (rtpfb->tmmbn.count * sizeof(uint32_t))); + rtpfb->tmmbn.MeasuredOverhead = tsk_realloc(rtpfb->tmmbn.MeasuredOverhead, (rtpfb->tmmbn.count * sizeof(uint16_t))); + for(i = 0; i < rtpfb->tmmbn.count; ++i) { + if(rtpfb->tmmbn.ssrc) { + rtpfb->tmmbn.ssrc[i] = (uint32_t)tnet_ntohl_2(&pdata[0]); + } + u32 = (uint32_t)tnet_ntohl_2(&pdata[4]); + if(rtpfb->tmmbn.MxTBR_Exp) { + rtpfb->tmmbn.MxTBR_Exp[i] = (u32 >> 26); + } + if(rtpfb->tmmbn.MxTBR_Mantissa) { + rtpfb->tmmbn.MxTBR_Mantissa[i] = ((u32 >> 9) & 0x1FFFF); + } + if(rtpfb->tmmbn.MeasuredOverhead) { + rtpfb->tmmbn.MeasuredOverhead[i] = (u32 & 0x1FF); + } + pdata += 8; + } + } + break; + } + + default: { + TSK_DEBUG_ERROR("Unsupported Feedback message type %d", (int)rtpfb->fci_type); + break; + } + } + } + } + + TSK_OBJECT_SAFE_FREE(header); + return rtpfb; } int trtp_rtcp_report_rtpfb_serialize_to(const trtp_rtcp_report_rtpfb_t* self, void* data, tsk_size_t size) { - int ret; - uint8_t* pdata = (uint8_t*)data; - - if(!self || !data || size < trtp_rtcp_report_rtpfb_get_size(self)){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if((ret = _trtp_rtcp_report_fb_serialize_to(TRTP_RTCP_REPORT_FB(self), pdata, size))){ - TSK_DEBUG_ERROR("Failed to serialize FB message"); - return ret; - } - pdata += TRTP_RTCP_PACKET_FB_MIN_SIZE; - size -= TRTP_RTCP_PACKET_FB_MIN_SIZE; - - switch(self->fci_type){ - case trtp_rtcp_rtpfb_fci_type_nack: - { - tsk_size_t i; - for(i = 0; i < self->nack.count; ++i){ - pdata[0] = self->nack.pid[i] >> 8; - pdata[1] = (self->nack.pid[i] & 0xFF); - pdata[2] = self->nack.blp[i] >> 8; - pdata[3] = (self->nack.blp[i] & 0xFF); - pdata += 4; - } - break; - } - default: - { - TSK_DEBUG_ERROR("Not implemented"); - return -2; - } - } - return 0; + int ret; + uint8_t* pdata = (uint8_t*)data; + + if(!self || !data || size < trtp_rtcp_report_rtpfb_get_size(self)) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if((ret = _trtp_rtcp_report_fb_serialize_to(TRTP_RTCP_REPORT_FB(self), pdata, size))) { + TSK_DEBUG_ERROR("Failed to serialize FB message"); + return ret; + } + pdata += TRTP_RTCP_PACKET_FB_MIN_SIZE; + size -= TRTP_RTCP_PACKET_FB_MIN_SIZE; + + switch(self->fci_type) { + case trtp_rtcp_rtpfb_fci_type_nack: { + tsk_size_t i; + for(i = 0; i < self->nack.count; ++i) { + pdata[0] = self->nack.pid[i] >> 8; + pdata[1] = (self->nack.pid[i] & 0xFF); + pdata[2] = self->nack.blp[i] >> 8; + pdata[3] = (self->nack.blp[i] & 0xFF); + pdata += 4; + } + break; + } + default: { + TSK_DEBUG_ERROR("Not implemented"); + return -2; + } + } + return 0; } tsk_size_t trtp_rtcp_report_rtpfb_get_size(const trtp_rtcp_report_rtpfb_t* self) { - if(!self || !TRTP_RTCP_PACKET(self)->header){ - TSK_DEBUG_ERROR("Invalid parameter"); - return 0; - } - return TRTP_RTCP_PACKET(self)->header->length_in_bytes; + if(!self || !TRTP_RTCP_PACKET(self)->header) { + TSK_DEBUG_ERROR("Invalid parameter"); + return 0; + } + return TRTP_RTCP_PACKET(self)->header->length_in_bytes; } @@ -311,341 +315,406 @@ tsk_size_t trtp_rtcp_report_rtpfb_get_size(const trtp_rtcp_report_rtpfb_t* self) static tsk_object_t* trtp_rtcp_report_psfb_ctor(tsk_object_t * self, va_list * app) { - trtp_rtcp_report_psfb_t *psfb = self; - if(psfb){ - - } - return self; + trtp_rtcp_report_psfb_t *psfb = self; + if(psfb) { + + } + return self; } static tsk_object_t* trtp_rtcp_report_psfb_dtor(tsk_object_t * self) -{ - trtp_rtcp_report_psfb_t *psfb = self; - if(psfb){ - // deinit self - switch(psfb->fci_type){ - case trtp_rtcp_psfb_fci_type_pli: - break; - case trtp_rtcp_psfb_fci_type_sli: - TSK_FREE(psfb->sli.first); - TSK_FREE(psfb->sli.number); - TSK_FREE(psfb->sli.pic_id); - break; - case trtp_rtcp_psfb_fci_type_rpsi: - TSK_FREE(psfb->rpsi.bytes); - break; - case trtp_rtcp_psfb_fci_type_fir: - TSK_FREE(psfb->fir.ssrc); - TSK_FREE(psfb->fir.seq_num); - break; - case trtp_rtcp_psfb_fci_type_afb: - switch(psfb->afb.type){ - case trtp_rtcp_psfb_afb_type_none: - TSK_FREE(psfb->afb.none.bytes); - break; - case trtp_rtcp_psfb_afb_type_remb: - TSK_FREE(psfb->afb.remb.ssrc_feedbacks); - break; - } - break; - } - // deinit base - trtp_rtcp_packet_deinit(TRTP_RTCP_PACKET(psfb)); - } - - return self; -} -static const tsk_object_def_t trtp_rtcp_report_psfb_def_s = { - sizeof(trtp_rtcp_report_psfb_t), - trtp_rtcp_report_psfb_ctor, - trtp_rtcp_report_psfb_dtor, - tsk_null, + trtp_rtcp_report_psfb_t *psfb = self; + if(psfb) { + // deinit self + switch(psfb->fci_type) { + case trtp_rtcp_psfb_fci_type_pli: + break; + case trtp_rtcp_psfb_fci_type_sli: + TSK_FREE(psfb->sli.first); + TSK_FREE(psfb->sli.number); + TSK_FREE(psfb->sli.pic_id); + break; + case trtp_rtcp_psfb_fci_type_rpsi: + TSK_FREE(psfb->rpsi.bytes); + break; + case trtp_rtcp_psfb_fci_type_fir: + TSK_FREE(psfb->fir.ssrc); + TSK_FREE(psfb->fir.seq_num); + break; + case trtp_rtcp_psfb_fci_type_afb: + switch(psfb->afb.type) { + case trtp_rtcp_psfb_afb_type_none: + TSK_FREE(psfb->afb.none.bytes); + break; + case trtp_rtcp_psfb_afb_type_remb: + TSK_FREE(psfb->afb.remb.ssrc_feedbacks); + break; + case trtp_rtcp_psfb_afb_type_jcng: + TSK_FREE(psfb->afb.jcng.ssrc_feedbacks); + break; + } + break; + } + // deinit base + trtp_rtcp_packet_deinit(TRTP_RTCP_PACKET(psfb)); + } + + return self; +} +static const tsk_object_def_t trtp_rtcp_report_psfb_def_s = { + sizeof(trtp_rtcp_report_psfb_t), + trtp_rtcp_report_psfb_ctor, + trtp_rtcp_report_psfb_dtor, + tsk_null, }; const tsk_object_def_t *trtp_rtcp_report_psfb_def_t = &trtp_rtcp_report_psfb_def_s; trtp_rtcp_report_psfb_t* trtp_rtcp_report_psfb_create_null() { - trtp_rtcp_report_psfb_t* psfb; - if((psfb = (trtp_rtcp_report_psfb_t*)tsk_object_new(trtp_rtcp_report_psfb_def_t))){ - trtp_rtcp_packet_init(TRTP_RTCP_PACKET(psfb), TRTP_RTCP_HEADER_VERSION_DEFAULT, 0, 0, trtp_rtcp_packet_type_psfb, TRTP_RTCP_PACKET_FB_MIN_SIZE); - } - return psfb; + trtp_rtcp_report_psfb_t* psfb; + if ((psfb = (trtp_rtcp_report_psfb_t*)tsk_object_new(trtp_rtcp_report_psfb_def_t))) { + trtp_rtcp_packet_init(TRTP_RTCP_PACKET(psfb), TRTP_RTCP_HEADER_VERSION_DEFAULT, 0, 0, trtp_rtcp_packet_type_psfb, TRTP_RTCP_PACKET_FB_MIN_SIZE); + } + return psfb; } trtp_rtcp_report_psfb_t* trtp_rtcp_report_psfb_create(trtp_rtcp_header_t* header) { - trtp_rtcp_report_psfb_t* psfb; - if((psfb = (trtp_rtcp_report_psfb_t*)tsk_object_new(trtp_rtcp_report_psfb_def_t))){ - TRTP_RTCP_PACKET(psfb)->header = tsk_object_ref(header); - } - return psfb; + trtp_rtcp_report_psfb_t* psfb; + if ((psfb = (trtp_rtcp_report_psfb_t*)tsk_object_new(trtp_rtcp_report_psfb_def_t))) { + TRTP_RTCP_PACKET(psfb)->header = tsk_object_ref(header); + } + return psfb; } trtp_rtcp_report_psfb_t* trtp_rtcp_report_psfb_create_2(trtp_rtcp_psfb_fci_type_t fci_type, uint32_t ssrc_sender, uint32_t ssrc_media_src) { - trtp_rtcp_report_psfb_t* psfb; - if((psfb = trtp_rtcp_report_psfb_create_null())){ - TRTP_RTCP_PACKET(psfb)->header->rc = psfb->fci_type = fci_type; - TRTP_RTCP_REPORT_FB(psfb)->ssrc_sender = ssrc_sender; - TRTP_RTCP_REPORT_FB(psfb)->ssrc_media = ssrc_media_src; - } - return psfb; + trtp_rtcp_report_psfb_t* psfb; + if ((psfb = trtp_rtcp_report_psfb_create_null())) { + TRTP_RTCP_PACKET(psfb)->header->rc = psfb->fci_type = fci_type; + TRTP_RTCP_REPORT_FB(psfb)->ssrc_sender = ssrc_sender; + TRTP_RTCP_REPORT_FB(psfb)->ssrc_media = ssrc_media_src; + } + return psfb; } trtp_rtcp_report_psfb_t* trtp_rtcp_report_psfb_create_pli(uint32_t ssrc_sender, uint32_t ssrc_media_src) { - return trtp_rtcp_report_psfb_create_2(trtp_rtcp_psfb_fci_type_pli, ssrc_sender, ssrc_media_src); + return trtp_rtcp_report_psfb_create_2(trtp_rtcp_psfb_fci_type_pli, ssrc_sender, ssrc_media_src); } trtp_rtcp_report_psfb_t* trtp_rtcp_report_psfb_create_fir(uint8_t seq_num, uint32_t ssrc_sender, uint32_t ssrc_media_src) { - trtp_rtcp_report_psfb_t* psfb; - if((psfb = trtp_rtcp_report_psfb_create_2(trtp_rtcp_psfb_fci_type_fir, ssrc_sender, ssrc_media_src))){ - psfb->fir.ssrc = tsk_malloc(sizeof(uint32_t)); - psfb->fir.seq_num = tsk_malloc(sizeof(uint8_t)); - if(!psfb->fir.ssrc || !psfb->fir.seq_num){ - TSK_OBJECT_SAFE_FREE(psfb); - return tsk_null; - } - psfb->fir.count = 1; - psfb->fir.seq_num[0] = seq_num; - psfb->fir.ssrc[0] = ssrc_media_src; - TRTP_RTCP_PACKET(psfb)->header->length_in_bytes += (uint32_t)(psfb->fir.count << 3); - TRTP_RTCP_PACKET(psfb)->header->length_in_words_minus1 = ((TRTP_RTCP_PACKET(psfb)->header->length_in_bytes >> 2) - 1); - } - return psfb; + trtp_rtcp_report_psfb_t* psfb; + if ((psfb = trtp_rtcp_report_psfb_create_2(trtp_rtcp_psfb_fci_type_fir, ssrc_sender, ssrc_media_src))) { + psfb->fir.ssrc = tsk_malloc(sizeof(uint32_t)); + psfb->fir.seq_num = tsk_malloc(sizeof(uint8_t)); + if (!psfb->fir.ssrc || !psfb->fir.seq_num) { + TSK_OBJECT_SAFE_FREE(psfb); + return tsk_null; + } + psfb->fir.count = 1; + psfb->fir.seq_num[0] = seq_num; + psfb->fir.ssrc[0] = ssrc_media_src; + TRTP_RTCP_PACKET(psfb)->header->length_in_bytes += (uint32_t)(psfb->fir.count << 3); + TRTP_RTCP_PACKET(psfb)->header->length_in_words_minus1 = ((TRTP_RTCP_PACKET(psfb)->header->length_in_bytes >> 2) - 1); + } + return psfb; } trtp_rtcp_report_psfb_t* trtp_rtcp_report_psfb_create_afb_remb(uint32_t ssrc_sender, const uint32_t* ssrc_media_src_list, uint32_t ssrc_media_src_list_count, uint32_t bitrate/*in bps*/) { - trtp_rtcp_report_psfb_t* psfb; - // draft-alvestrand-rmcat-remb-02 2.2: SSRC media source always equal to zero - if((psfb = trtp_rtcp_report_psfb_create_2(trtp_rtcp_psfb_fci_type_afb, ssrc_sender, 0))){ - static const uint32_t __max_mantissa = 131072; - psfb->afb.type = trtp_rtcp_psfb_afb_type_remb; - psfb->afb.remb.exp = 0; - if(bitrate <= __max_mantissa){ - psfb->afb.remb.mantissa = bitrate; - } - else{ - while(bitrate >= (__max_mantissa << psfb->afb.remb.exp) && psfb->afb.remb.exp < 63) ++psfb->afb.remb.exp; - psfb->afb.remb.mantissa = (bitrate >> psfb->afb.remb.exp); - } - if(ssrc_media_src_list && ssrc_media_src_list_count > 0 && (psfb->afb.remb.ssrc_feedbacks = (uint32_t*)tsk_malloc(ssrc_media_src_list_count << 2))){ - uint32_t i; - psfb->afb.remb.num_ssrc = ssrc_media_src_list_count; - for(i = 0; i < ssrc_media_src_list_count; ++i){ - psfb->afb.remb.ssrc_feedbacks[i] = ssrc_media_src_list[i]; - } - } - TRTP_RTCP_PACKET(psfb)->header->length_in_bytes += 8; /*'R' 'E' 'M' 'B', Num SSRC, BR Exp, BR Mantissa */ - TRTP_RTCP_PACKET(psfb)->header->length_in_bytes += (psfb->afb.remb.num_ssrc << 2); - TRTP_RTCP_PACKET(psfb)->header->length_in_words_minus1 = ((TRTP_RTCP_PACKET(psfb)->header->length_in_bytes >> 2) - 1); - } - return psfb; + trtp_rtcp_report_psfb_t* psfb; + // draft-alvestrand-rmcat-remb-02 2.2: SSRC media source always equal to zero + if ((psfb = trtp_rtcp_report_psfb_create_2(trtp_rtcp_psfb_fci_type_afb, ssrc_sender, 0))) { + static const uint32_t __max_mantissa = 131072; + psfb->afb.type = trtp_rtcp_psfb_afb_type_remb; + psfb->afb.remb.exp = 0; + if (bitrate <= __max_mantissa) { + psfb->afb.remb.mantissa = bitrate; + } + else { + while (bitrate >= (__max_mantissa << psfb->afb.remb.exp) && psfb->afb.remb.exp < 63) { + ++psfb->afb.remb.exp; + } + psfb->afb.remb.mantissa = (bitrate >> psfb->afb.remb.exp); + } + if (ssrc_media_src_list && ssrc_media_src_list_count > 0 && (psfb->afb.remb.ssrc_feedbacks = (uint32_t*)tsk_malloc(ssrc_media_src_list_count << 2))) { + uint32_t i; + psfb->afb.remb.num_ssrc = ssrc_media_src_list_count; + for (i = 0; i < ssrc_media_src_list_count; ++i) { + psfb->afb.remb.ssrc_feedbacks[i] = ssrc_media_src_list[i]; + } + } + TRTP_RTCP_PACKET(psfb)->header->length_in_bytes += 8; /*'R' 'E' 'M' 'B', Num SSRC, BR Exp, BR Mantissa */ + TRTP_RTCP_PACKET(psfb)->header->length_in_bytes += (psfb->afb.remb.num_ssrc << 2); + TRTP_RTCP_PACKET(psfb)->header->length_in_words_minus1 = ((TRTP_RTCP_PACKET(psfb)->header->length_in_bytes >> 2) - 1); + } + return psfb; +} + +trtp_rtcp_report_psfb_t* trtp_rtcp_report_psfb_create_afb_jcng(uint32_t ssrc_sender, const uint32_t* ssrc_media_src_list, uint32_t ssrc_media_src_list_count, float jcng_q/*in quality metric*/) +{ + trtp_rtcp_report_psfb_t* psfb; + // SSRC media source always equal to zero + if ((psfb = trtp_rtcp_report_psfb_create_2(trtp_rtcp_psfb_fci_type_afb, ssrc_sender, 0))) { + psfb->afb.type = trtp_rtcp_psfb_afb_type_jcng; + psfb->afb.jcng.q = (uint8_t)(jcng_q * 255.f); + if (ssrc_media_src_list && ssrc_media_src_list_count > 0 && (psfb->afb.jcng.ssrc_feedbacks = (uint32_t*)tsk_malloc(ssrc_media_src_list_count << 2))) { + uint32_t i; + psfb->afb.jcng.num_ssrc = ssrc_media_src_list_count; + for (i = 0; i < ssrc_media_src_list_count; ++i) { + psfb->afb.jcng.ssrc_feedbacks[i] = ssrc_media_src_list[i]; + } + } + TRTP_RTCP_PACKET(psfb)->header->length_in_bytes += 8; /*'J' 'C' 'N' 'G', Num SSRC, Q, Reserverd */ + TRTP_RTCP_PACKET(psfb)->header->length_in_bytes += (psfb->afb.jcng.num_ssrc << 2); + TRTP_RTCP_PACKET(psfb)->header->length_in_words_minus1 = ((TRTP_RTCP_PACKET(psfb)->header->length_in_bytes >> 2) - 1); + } + return psfb; } trtp_rtcp_report_psfb_t* trtp_rtcp_report_psfb_deserialize(const void* data, tsk_size_t _size) { - trtp_rtcp_report_psfb_t* psfb = tsk_null; - trtp_rtcp_header_t* header = tsk_null; - uint32_t ssrc_sender, ssrc_media_src; - - if(_trtp_rtcp_report_fb_deserialize(data, _size, &header, &ssrc_sender, &ssrc_media_src) == 0){ - if((psfb = trtp_rtcp_report_psfb_create(header))){ - const uint8_t* pdata = ((const uint8_t*)data) + TRTP_RTCP_PACKET_FB_MIN_SIZE; - tsk_size_t size = (header->length_in_bytes - TRTP_RTCP_PACKET_FB_MIN_SIZE); - - TRTP_RTCP_REPORT_FB(psfb)->ssrc_sender = ssrc_sender; - TRTP_RTCP_REPORT_FB(psfb)->ssrc_media = ssrc_media_src; - - switch((psfb->fci_type = header->rc)/* FMT for RTCP-FB messages */){ - case trtp_rtcp_psfb_fci_type_pli: - { - // No FCI in PLI - // TSK_DEBUG_INFO("PLI"); - break; - } - case trtp_rtcp_psfb_fci_type_sli: - { - tsk_size_t sli_count = (size >> 2), i; - uint32_t u32; - if(sli_count == 0){ - TSK_DEBUG_ERROR("Too short"); - goto bail; - } - psfb->sli.first = tsk_realloc(psfb->sli.first, (sli_count * sizeof(uint16_t))); - psfb->sli.number = tsk_realloc(psfb->sli.number, (sli_count * sizeof(uint16_t))); - psfb->sli.pic_id = tsk_realloc(psfb->sli.pic_id, (sli_count * sizeof(uint16_t))); - for(i = 0; i < sli_count; ++i){ - u32 = (uint32_t)tnet_ntohl_2(&pdata[i >> 2]); - if(psfb->sli.first) psfb->sli.first[i] = (u32 >> 19); - if(psfb->sli.number) psfb->sli.number[i] = (u32 >> 6) & 0x1FFF; - if(psfb->sli.pic_id) psfb->sli.pic_id[i] = u32 & 0x3F; - } - - break; - } - case trtp_rtcp_psfb_fci_type_rpsi: - { - uint16_t u16; - if(size < 2){ - TSK_DEBUG_ERROR("Too short"); - goto bail; - } - u16 = tnet_ntohs_2(&pdata[0]); - psfb->rpsi.pb = (u16 >> 8); - psfb->rpsi.pt = (u16 & 0x7F); - if((psfb->rpsi.bytes = tsk_calloc((size - 2), sizeof(uint8_t)))){ - memcpy(psfb->rpsi.bytes, &pdata[2], (size - 2)); - } - break; - } - case trtp_rtcp_psfb_fci_type_fir: - { - tsk_size_t fir_count = (size >> 3), i; - if(fir_count == 0){ - TSK_DEBUG_ERROR("Too short"); - goto bail; - } - psfb->fir.count = fir_count; - psfb->fir.ssrc = tsk_realloc(psfb->fir.seq_num, (fir_count * sizeof(uint32_t))); - psfb->fir.seq_num = tsk_realloc(psfb->fir.seq_num, (fir_count * sizeof(uint8_t))); - for(i = 0; i < fir_count; ++i){ - if(psfb->fir.ssrc) psfb->fir.ssrc[i] = (uint32_t)tnet_ntohl_2(&pdata[0]); - if(psfb->fir.seq_num) psfb->fir.seq_num[i] = pdata[4]; - pdata+=8; - } - break; - } - case trtp_rtcp_psfb_fci_type_afb: - { - if(size > 0){ - psfb->afb.type = trtp_rtcp_psfb_afb_type_none; - // REMB (http://tools.ietf.org/html/draft-alvestrand-rmcat-remb-02) ? - if(size > 4 && tsk_strniequals(pdata, "REMB", 4)){ - uint32_t _u32; - if(size < 8){ // REMB, Num SSRC, BR Exp, BR Mantissa - TSK_DEBUG_ERROR("Too short"); - goto bail; - } - psfb->afb.type = trtp_rtcp_psfb_afb_type_remb; - _u32 = (uint32_t)tnet_ntohl_2(&pdata[4]); - psfb->afb.remb.num_ssrc = ((_u32 >> 24) & 0xFF); - if((psfb->afb.remb.num_ssrc << 2) != (size - 8)){ - TSK_DEBUG_ERROR("Invalid size"); - psfb->afb.remb.num_ssrc = 0; - goto bail; - } - psfb->afb.remb.exp = ((_u32 >> 18) & 0x3F); - psfb->afb.remb.mantissa = (_u32 & 0x3FFFF); - if((psfb->afb.remb.ssrc_feedbacks = tsk_malloc(psfb->afb.remb.num_ssrc << 2))){ - for(_u32 = 0; _u32 < psfb->afb.remb.num_ssrc; ++_u32){ - psfb->afb.remb.ssrc_feedbacks[_u32] = (uint32_t)tnet_ntohl_2(&pdata[8 + (_u32 << 2)]); - } - } - } - else{ - if((psfb->afb.none.bytes = tsk_calloc(size, sizeof(uint8_t)))){ - memcpy(psfb->afb.none.bytes, &pdata[0], size); - } - } - } - break; - } - default: - { - TSK_DEBUG_ERROR("%d not a valid FCI", psfb->fci_type); - goto bail; - } - } - } - } + trtp_rtcp_report_psfb_t* psfb = tsk_null; + trtp_rtcp_header_t* header = tsk_null; + uint32_t ssrc_sender, ssrc_media_src; + + if(_trtp_rtcp_report_fb_deserialize(data, _size, &header, &ssrc_sender, &ssrc_media_src) == 0) { + if((psfb = trtp_rtcp_report_psfb_create(header))) { + const uint8_t* pdata = ((const uint8_t*)data) + TRTP_RTCP_PACKET_FB_MIN_SIZE; + tsk_size_t size = (header->length_in_bytes - TRTP_RTCP_PACKET_FB_MIN_SIZE); + + TRTP_RTCP_REPORT_FB(psfb)->ssrc_sender = ssrc_sender; + TRTP_RTCP_REPORT_FB(psfb)->ssrc_media = ssrc_media_src; + + switch((psfb->fci_type = header->rc)/* FMT for RTCP-FB messages */) { + case trtp_rtcp_psfb_fci_type_pli: { + // No FCI in PLI + // TSK_DEBUG_INFO("PLI"); + break; + } + case trtp_rtcp_psfb_fci_type_sli: { + tsk_size_t sli_count = (size >> 2), i; + uint32_t u32; + if(sli_count == 0) { + TSK_DEBUG_ERROR("Too short"); + goto bail; + } + psfb->sli.first = tsk_realloc(psfb->sli.first, (sli_count * sizeof(uint16_t))); + psfb->sli.number = tsk_realloc(psfb->sli.number, (sli_count * sizeof(uint16_t))); + psfb->sli.pic_id = tsk_realloc(psfb->sli.pic_id, (sli_count * sizeof(uint16_t))); + for(i = 0; i < sli_count; ++i) { + u32 = (uint32_t)tnet_ntohl_2(&pdata[i >> 2]); + if(psfb->sli.first) { + psfb->sli.first[i] = (u32 >> 19); + } + if(psfb->sli.number) { + psfb->sli.number[i] = (u32 >> 6) & 0x1FFF; + } + if(psfb->sli.pic_id) { + psfb->sli.pic_id[i] = u32 & 0x3F; + } + } + + break; + } + case trtp_rtcp_psfb_fci_type_rpsi: { + uint16_t u16; + if(size < 2) { + TSK_DEBUG_ERROR("Too short"); + goto bail; + } + u16 = tnet_ntohs_2(&pdata[0]); + psfb->rpsi.pb = (u16 >> 8); + psfb->rpsi.pt = (u16 & 0x7F); + if((psfb->rpsi.bytes = tsk_calloc((size - 2), sizeof(uint8_t)))) { + memcpy(psfb->rpsi.bytes, &pdata[2], (size - 2)); + } + break; + } + case trtp_rtcp_psfb_fci_type_fir: { + tsk_size_t fir_count = (size >> 3), i; + if(fir_count == 0) { + TSK_DEBUG_ERROR("Too short"); + goto bail; + } + psfb->fir.count = fir_count; + psfb->fir.ssrc = tsk_realloc(psfb->fir.seq_num, (fir_count * sizeof(uint32_t))); + psfb->fir.seq_num = tsk_realloc(psfb->fir.seq_num, (fir_count * sizeof(uint8_t))); + for(i = 0; i < fir_count; ++i) { + if(psfb->fir.ssrc) { + psfb->fir.ssrc[i] = (uint32_t)tnet_ntohl_2(&pdata[0]); + } + if(psfb->fir.seq_num) { + psfb->fir.seq_num[i] = pdata[4]; + } + pdata+=8; + } + break; + } + case trtp_rtcp_psfb_fci_type_afb: { + if(size > 0) { + psfb->afb.type = trtp_rtcp_psfb_afb_type_none; + // REMB (http://tools.ietf.org/html/draft-alvestrand-rmcat-remb-02) or jitter buffer congestion estimation message? + if (size > 4 && tsk_strniequals(pdata, "REMB", 4)) { + uint32_t _u32; + if (size < 8) { // REMB, Num SSRC, BR Exp, BR Mantissa + TSK_DEBUG_ERROR("Too short"); + goto bail; + } + psfb->afb.type = trtp_rtcp_psfb_afb_type_remb; + _u32 = (uint32_t)tnet_ntohl_2(&pdata[4]); + psfb->afb.remb.num_ssrc = ((_u32 >> 24) & 0xFF); + if ((psfb->afb.remb.num_ssrc << 2) != (size - 8)) { + TSK_DEBUG_ERROR("Invalid size"); + psfb->afb.remb.num_ssrc = 0; + goto bail; + } + psfb->afb.remb.exp = ((_u32 >> 18) & 0x3F); + psfb->afb.remb.mantissa = (_u32 & 0x3FFFF); + if ((psfb->afb.remb.ssrc_feedbacks = tsk_malloc(psfb->afb.remb.num_ssrc << 2))) { + for (_u32 = 0; _u32 < psfb->afb.remb.num_ssrc; ++_u32) { + psfb->afb.remb.ssrc_feedbacks[_u32] = (uint32_t)tnet_ntohl_2(&pdata[8 + (_u32 << 2)]); + } + } + } + else if (size > 4 && tsk_strniequals(pdata, "JCNG", 4)) { + uint32_t _u32; + if (size < 8) { // JCNG, Num SSRC, Q, Reserved + TSK_DEBUG_ERROR("Too short"); + goto bail; + } + psfb->afb.type = trtp_rtcp_psfb_afb_type_jcng; + _u32 = (uint32_t)tnet_ntohl_2(&pdata[4]); + psfb->afb.jcng.num_ssrc = ((_u32 >> 24) & 0xFF); + if ((psfb->afb.jcng.num_ssrc << 2) != (size - 8)) { + TSK_DEBUG_ERROR("Invalid size"); + psfb->afb.jcng.num_ssrc = 0; + goto bail; + } + psfb->afb.jcng.q = ((_u32 >> 16) & 0xFF); + if ((psfb->afb.jcng.ssrc_feedbacks = tsk_malloc(psfb->afb.jcng.num_ssrc << 2))) { + for (_u32 = 0; _u32 < psfb->afb.jcng.num_ssrc; ++_u32) { + psfb->afb.jcng.ssrc_feedbacks[_u32] = (uint32_t)tnet_ntohl_2(&pdata[8 + (_u32 << 2)]); + } + } + } + else { + if ((psfb->afb.none.bytes = tsk_calloc(size, sizeof(uint8_t)))) { + memcpy(psfb->afb.none.bytes, &pdata[0], size); + } + } + } + break; + } + default: { + TSK_DEBUG_ERROR("%d not a valid FCI", psfb->fci_type); + goto bail; + } + } + } + } bail: - TSK_OBJECT_SAFE_FREE(header); - return psfb; + TSK_OBJECT_SAFE_FREE(header); + return psfb; } int trtp_rtcp_report_psfb_serialize_to(const trtp_rtcp_report_psfb_t* self, void* data, tsk_size_t size) { - int ret; - uint8_t* pdata = (uint8_t*)data; - - if(!self || !data || size < trtp_rtcp_report_psfb_get_size(self)){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if((ret = _trtp_rtcp_report_fb_serialize_to(TRTP_RTCP_REPORT_FB(self), pdata, size))){ - TSK_DEBUG_ERROR("Failed to serialize FB message"); - return ret; - } - pdata += TRTP_RTCP_PACKET_FB_MIN_SIZE; - size -= TRTP_RTCP_PACKET_FB_MIN_SIZE; - - switch(self->fci_type){ - case trtp_rtcp_psfb_fci_type_pli: - { - // No FCI in PLI - break; - } - case trtp_rtcp_psfb_fci_type_fir: - { - tsk_size_t i; - for(i = 0; i < self->fir.count; ++i){ - pdata[0] = self->fir.ssrc[i] >> 24; - pdata[1] = (self->fir.ssrc[i] >> 16) & 0xFF; - pdata[2] = (self->fir.ssrc[i] >> 8) & 0xFF; - pdata[3] = (self->fir.ssrc[i] & 0xFF); - pdata[4] = self->fir.seq_num[i]; - pdata += 8; // SSRC (4), Seq nr(1), Reserved(3) - } - break; - } - case trtp_rtcp_psfb_fci_type_afb: - { - if(self->afb.type == trtp_rtcp_psfb_afb_type_remb){ - tsk_size_t i; - // 'R' 'E' 'M' 'B' - pdata[0] = 'R', pdata[1] = 'E', pdata[2] = 'M', pdata[3] = 'B'; - // | Num SSRC | BR Exp | BR Mantissa - pdata[4] = self->afb.remb.num_ssrc; // 8bits - pdata[5] = (self->afb.remb.exp << 2) & 0xFC;// 6bits - // 18bits - pdata[5] |= (self->afb.remb.mantissa >> 16) & 0x3; - pdata[6] = (self->afb.remb.mantissa >> 8) & 0xFF; - pdata[7] = (self->afb.remb.mantissa & 0xFF); - if(self->afb.remb.ssrc_feedbacks){ - for(i = 0; i < self->afb.remb.num_ssrc; ++i){ - pdata[8 + (i<<2)] = self->afb.remb.ssrc_feedbacks[i] >> 24; - pdata[8 + (i<<2) + 1] = (self->afb.remb.ssrc_feedbacks[i] >> 16) & 0xFF; - pdata[8 + (i<<2) + 2] = (self->afb.remb.ssrc_feedbacks[i] >> 8) & 0xFF; - pdata[8 + (i<<2) + 3] = (self->afb.remb.ssrc_feedbacks[i] & 0xFF); - } - } - } - else{ - TSK_DEBUG_ERROR("Not implemented yet"); - return -1; - } - break; - } - default: - { - TSK_DEBUG_ERROR("Not implemented yet"); - return -1; - } - } - - return ret; + int ret; + uint8_t* pdata = (uint8_t*)data; + + if(!self || !data || size < trtp_rtcp_report_psfb_get_size(self)) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if((ret = _trtp_rtcp_report_fb_serialize_to(TRTP_RTCP_REPORT_FB(self), pdata, size))) { + TSK_DEBUG_ERROR("Failed to serialize FB message"); + return ret; + } + pdata += TRTP_RTCP_PACKET_FB_MIN_SIZE; + size -= TRTP_RTCP_PACKET_FB_MIN_SIZE; + + switch(self->fci_type) { + case trtp_rtcp_psfb_fci_type_pli: { + // No FCI in PLI + break; + } + case trtp_rtcp_psfb_fci_type_fir: { + tsk_size_t i; + for(i = 0; i < self->fir.count; ++i) { + pdata[0] = self->fir.ssrc[i] >> 24; + pdata[1] = (self->fir.ssrc[i] >> 16) & 0xFF; + pdata[2] = (self->fir.ssrc[i] >> 8) & 0xFF; + pdata[3] = (self->fir.ssrc[i] & 0xFF); + pdata[4] = self->fir.seq_num[i]; + pdata += 8; // SSRC (4), Seq nr(1), Reserved(3) + } + break; + } + case trtp_rtcp_psfb_fci_type_afb: { + if (self->afb.type == trtp_rtcp_psfb_afb_type_remb) { + tsk_size_t i; + // 'R' 'E' 'M' 'B' + pdata[0] = 'R', pdata[1] = 'E', pdata[2] = 'M', pdata[3] = 'B'; + // | Num SSRC | BR Exp | BR Mantissa + pdata[4] = self->afb.remb.num_ssrc; // 8bits + pdata[5] = (self->afb.remb.exp << 2) & 0xFC;// 6bits + // 18bits + pdata[5] |= (self->afb.remb.mantissa >> 16) & 0x3; + pdata[6] = (self->afb.remb.mantissa >> 8) & 0xFF; + pdata[7] = (self->afb.remb.mantissa & 0xFF); + if (self->afb.remb.ssrc_feedbacks) { + for (i = 0; i < self->afb.remb.num_ssrc; ++i) { + pdata[8 + (i<<2)] = self->afb.remb.ssrc_feedbacks[i] >> 24; + pdata[8 + (i<<2) + 1] = (self->afb.remb.ssrc_feedbacks[i] >> 16) & 0xFF; + pdata[8 + (i<<2) + 2] = (self->afb.remb.ssrc_feedbacks[i] >> 8) & 0xFF; + pdata[8 + (i<<2) + 3] = (self->afb.remb.ssrc_feedbacks[i] & 0xFF); + } + } + } + else if (self->afb.type == trtp_rtcp_psfb_afb_type_jcng) { + tsk_size_t i; + // 'J' 'C' 'N' 'G' + pdata[0] = 'J', pdata[1] = 'C', pdata[2] = 'N', pdata[3] = 'G'; + // | Num SSRC | Q | Reserved + pdata[4] = self->afb.jcng.num_ssrc; // 8bits + pdata[5] = self->afb.jcng.q;// 8bits + // 16bits, reserved, zeros + pdata[6] = 0x00; + pdata[7] = 0x00; + if (self->afb.jcng.ssrc_feedbacks) { + for (i = 0; i < self->afb.jcng.num_ssrc; ++i) { + pdata[8 + (i<<2)] = self->afb.jcng.ssrc_feedbacks[i] >> 24; + pdata[8 + (i<<2) + 1] = (self->afb.jcng.ssrc_feedbacks[i] >> 16) & 0xFF; + pdata[8 + (i<<2) + 2] = (self->afb.jcng.ssrc_feedbacks[i] >> 8) & 0xFF; + pdata[8 + (i<<2) + 3] = (self->afb.jcng.ssrc_feedbacks[i] & 0xFF); + } + } + } + else { + TSK_DEBUG_ERROR("Not implemented yet"); + return -1; + } + break; + } + default: { + TSK_DEBUG_ERROR("Not implemented yet"); + return -1; + } + } + + return ret; } tsk_size_t trtp_rtcp_report_psfb_get_size(const trtp_rtcp_report_psfb_t* self) { - if(!self || !TRTP_RTCP_PACKET(self)->header){ - TSK_DEBUG_ERROR("Invalid parameter"); - return 0; - } - return TRTP_RTCP_PACKET(self)->header->length_in_bytes; + if(!self || !TRTP_RTCP_PACKET(self)->header) { + TSK_DEBUG_ERROR("Invalid parameter"); + return 0; + } + return TRTP_RTCP_PACKET(self)->header->length_in_bytes; } \ No newline at end of file diff --git a/tinyRTP/src/rtcp/trtp_rtcp_report_rr.c b/tinyRTP/src/rtcp/trtp_rtcp_report_rr.c index 2a38a4c..0842921 100755 --- a/tinyRTP/src/rtcp/trtp_rtcp_report_rr.c +++ b/tinyRTP/src/rtcp/trtp_rtcp_report_rr.c @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -30,203 +30,202 @@ static tsk_object_t* trtp_rtcp_report_rr_ctor(tsk_object_t * self, va_list * app) { - trtp_rtcp_report_rr_t *rr = self; - if(rr){ - rr->packets = tsk_list_create(); - rr->blocks = tsk_list_create(); - } - return self; + trtp_rtcp_report_rr_t *rr = self; + if(rr) { + rr->packets = tsk_list_create(); + rr->blocks = tsk_list_create(); + } + return self; } static tsk_object_t* trtp_rtcp_report_rr_dtor(tsk_object_t * self) -{ - trtp_rtcp_report_rr_t *rr = self; - if(rr){ - // deinit self - TSK_OBJECT_SAFE_FREE(rr->packets); - TSK_OBJECT_SAFE_FREE(rr->blocks); - // deinit base - trtp_rtcp_packet_deinit(TRTP_RTCP_PACKET(rr)); - } - - return self; -} -static const tsk_object_def_t trtp_rtcp_report_rr_def_s = { - sizeof(trtp_rtcp_report_rr_t), - trtp_rtcp_report_rr_ctor, - trtp_rtcp_report_rr_dtor, - tsk_null, + trtp_rtcp_report_rr_t *rr = self; + if(rr) { + // deinit self + TSK_OBJECT_SAFE_FREE(rr->packets); + TSK_OBJECT_SAFE_FREE(rr->blocks); + // deinit base + trtp_rtcp_packet_deinit(TRTP_RTCP_PACKET(rr)); + } + + return self; +} +static const tsk_object_def_t trtp_rtcp_report_rr_def_s = { + sizeof(trtp_rtcp_report_rr_t), + trtp_rtcp_report_rr_ctor, + trtp_rtcp_report_rr_dtor, + tsk_null, }; const tsk_object_def_t *trtp_rtcp_report_rr_def_t = &trtp_rtcp_report_rr_def_s; trtp_rtcp_report_rr_t* trtp_rtcp_report_rr_create_null() { - trtp_rtcp_report_rr_t* rr; - if((rr = (trtp_rtcp_report_rr_t*)tsk_object_new(trtp_rtcp_report_rr_def_t))){ - trtp_rtcp_packet_init(TRTP_RTCP_PACKET(rr), TRTP_RTCP_HEADER_VERSION_DEFAULT, 0, 0, trtp_rtcp_packet_type_rr, (TRTP_RTCP_HEADER_SIZE + 4)); - } - return rr; + trtp_rtcp_report_rr_t* rr; + if((rr = (trtp_rtcp_report_rr_t*)tsk_object_new(trtp_rtcp_report_rr_def_t))) { + trtp_rtcp_packet_init(TRTP_RTCP_PACKET(rr), TRTP_RTCP_HEADER_VERSION_DEFAULT, 0, 0, trtp_rtcp_packet_type_rr, (TRTP_RTCP_HEADER_SIZE + 4)); + } + return rr; } trtp_rtcp_report_rr_t* trtp_rtcp_report_rr_create(trtp_rtcp_header_t* header) { - trtp_rtcp_report_rr_t* rr; - if((rr = (trtp_rtcp_report_rr_t*)tsk_object_new(trtp_rtcp_report_rr_def_t))){ - TRTP_RTCP_PACKET(rr)->header = tsk_object_ref(header); - } - return rr; + trtp_rtcp_report_rr_t* rr; + if((rr = (trtp_rtcp_report_rr_t*)tsk_object_new(trtp_rtcp_report_rr_def_t))) { + TRTP_RTCP_PACKET(rr)->header = tsk_object_ref(header); + } + return rr; } trtp_rtcp_report_rr_t* trtp_rtcp_report_rr_create_2(uint32_t ssrc) { - trtp_rtcp_report_rr_t* rr; - if((rr = trtp_rtcp_report_rr_create_null())){ - rr->ssrc = ssrc; - } - return rr; + trtp_rtcp_report_rr_t* rr; + if((rr = trtp_rtcp_report_rr_create_null())) { + rr->ssrc = ssrc; + } + return rr; } trtp_rtcp_report_rr_t* trtp_rtcp_report_rr_deserialize(const void* data, tsk_size_t _size) { - trtp_rtcp_report_rr_t* rr = tsk_null; - trtp_rtcp_header_t* header = tsk_null; - const uint8_t* pdata = (const uint8_t*)data; - int32_t size = (int32_t)_size; - - if(!data || size < TRTP_RTCP_PACKET_RR_MIN_SIZE){ - TSK_DEBUG_ERROR("Invalid parameter"); - return tsk_null; - } - - if(!(header = trtp_rtcp_header_deserialize(pdata, size))){ - TSK_DEBUG_ERROR("Failed to deserialize the header"); - goto bail; - } - if(header->length_in_bytes < TRTP_RTCP_PACKET_RR_MIN_SIZE){ - TSK_DEBUG_ERROR("Too short"); - goto bail; - } - - if(!(rr = trtp_rtcp_report_rr_create(header))){ - TSK_DEBUG_ERROR("Failed to create object"); - goto bail; - } - - rr->ssrc = (uint32_t)tnet_ntohl_2(&pdata[4]); - - pdata += (TRTP_RTCP_HEADER_SIZE + 4); - size -= (TRTP_RTCP_HEADER_SIZE + 4); - - // Blocks - if(header->rc > 0){ - tsk_size_t i = 0; - trtp_rtcp_rblock_t* rblock; - - while(i++ < header->rc && size >= TRTP_RTCP_RBLOCK_SIZE){ - if((rblock = trtp_rtcp_rblock_deserialize(pdata, size))){ - tsk_list_push_back_data(rr->blocks, (void**)&rblock); - } - pdata += TRTP_RTCP_RBLOCK_SIZE; - size -= TRTP_RTCP_RBLOCK_SIZE; - } - } - - // Other Packets - while(size > TRTP_RTCP_HEADER_SIZE){ - trtp_rtcp_packet_t* packet; - - if((packet = trtp_rtcp_packet_deserialize(pdata, size))){ - if((size -= packet->header->length_in_bytes) > 0){ - pdata += packet->header->length_in_bytes; - } - tsk_list_push_back_data(rr->packets, (void**)&packet); - continue; - } - break; - } + trtp_rtcp_report_rr_t* rr = tsk_null; + trtp_rtcp_header_t* header = tsk_null; + const uint8_t* pdata = (const uint8_t*)data; + int32_t size = (int32_t)_size; + + if(!data || size < TRTP_RTCP_PACKET_RR_MIN_SIZE) { + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_null; + } + + if(!(header = trtp_rtcp_header_deserialize(pdata, size))) { + TSK_DEBUG_ERROR("Failed to deserialize the header"); + goto bail; + } + if(header->length_in_bytes < TRTP_RTCP_PACKET_RR_MIN_SIZE) { + TSK_DEBUG_ERROR("Too short"); + goto bail; + } + + if(!(rr = trtp_rtcp_report_rr_create(header))) { + TSK_DEBUG_ERROR("Failed to create object"); + goto bail; + } + + rr->ssrc = (uint32_t)tnet_ntohl_2(&pdata[4]); + + pdata += (TRTP_RTCP_HEADER_SIZE + 4); + size -= (TRTP_RTCP_HEADER_SIZE + 4); + + // Blocks + if(header->rc > 0) { + tsk_size_t i = 0; + trtp_rtcp_rblock_t* rblock; + + while(i++ < header->rc && size >= TRTP_RTCP_RBLOCK_SIZE) { + if((rblock = trtp_rtcp_rblock_deserialize(pdata, size))) { + tsk_list_push_back_data(rr->blocks, (void**)&rblock); + } + pdata += TRTP_RTCP_RBLOCK_SIZE; + size -= TRTP_RTCP_RBLOCK_SIZE; + } + } + + // Other Packets + while(size > TRTP_RTCP_HEADER_SIZE) { + trtp_rtcp_packet_t* packet; + + if((packet = trtp_rtcp_packet_deserialize(pdata, size))) { + if((size -= packet->header->length_in_bytes) > 0) { + pdata += packet->header->length_in_bytes; + } + tsk_list_push_back_data(rr->packets, (void**)&packet); + continue; + } + break; + } bail: - TSK_OBJECT_SAFE_FREE(header); - return rr; + TSK_OBJECT_SAFE_FREE(header); + return rr; } int trtp_rtcp_report_rr_serialize_to(const trtp_rtcp_report_rr_t* self, void* data, tsk_size_t size) { - int ret; - const tsk_list_item_t* item; - uint8_t* pdata = (uint8_t*)data; - - if(!self || !data || size < trtp_rtcp_report_rr_get_size(self)){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if((ret = trtp_rtcp_header_serialize_to(TRTP_RTCP_PACKET(self)->header, pdata, size))){ - TSK_DEBUG_ERROR("Failed to serialize the header"); - return ret; - } - - pdata[TRTP_RTCP_HEADER_SIZE] = self->ssrc >> 24; - pdata[TRTP_RTCP_HEADER_SIZE + 1] = (self->ssrc >> 16) & 0xFF; - pdata[TRTP_RTCP_HEADER_SIZE + 2] = (self->ssrc >> 8) & 0xFF; - pdata[TRTP_RTCP_HEADER_SIZE + 3] = (self->ssrc & 0xFF); - - pdata += (TRTP_RTCP_HEADER_SIZE + 4); - size -= (TRTP_RTCP_HEADER_SIZE + 4); - - if(TRTP_RTCP_PACKET(self)->header->rc > 0){ - tsk_list_foreach(item, self->blocks){ - if(!item->data){ - continue; - } - if((ret = trtp_rtcp_rblock_serialize_to(TRTP_RTCP_RBLOCK(item->data), pdata, size))){ - TSK_DEBUG_ERROR("Failed to serialize the rblock"); - goto bail; - } - pdata += TRTP_RTCP_RBLOCK_SIZE; - size -= TRTP_RTCP_RBLOCK_SIZE; - } - } - - tsk_list_foreach(item, self->packets){ - if(!item->data){ - continue; - } - if((ret = trtp_rtcp_packet_serialize_to(TRTP_RTCP_PACKET(item->data), pdata, size))){ - TSK_DEBUG_ERROR("Failed to serialize packet"); - goto bail; - } - pdata += TRTP_RTCP_PACKET(item->data)->header->length_in_bytes; - size -= TRTP_RTCP_PACKET(item->data)->header->length_in_bytes; - } + int ret; + const tsk_list_item_t* item; + uint8_t* pdata = (uint8_t*)data; + + if(!self || !data || size < trtp_rtcp_report_rr_get_size(self)) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if((ret = trtp_rtcp_header_serialize_to(TRTP_RTCP_PACKET(self)->header, pdata, size))) { + TSK_DEBUG_ERROR("Failed to serialize the header"); + return ret; + } + + pdata[TRTP_RTCP_HEADER_SIZE] = self->ssrc >> 24; + pdata[TRTP_RTCP_HEADER_SIZE + 1] = (self->ssrc >> 16) & 0xFF; + pdata[TRTP_RTCP_HEADER_SIZE + 2] = (self->ssrc >> 8) & 0xFF; + pdata[TRTP_RTCP_HEADER_SIZE + 3] = (self->ssrc & 0xFF); + + pdata += (TRTP_RTCP_HEADER_SIZE + 4); + size -= (TRTP_RTCP_HEADER_SIZE + 4); + + if(TRTP_RTCP_PACKET(self)->header->rc > 0) { + tsk_list_foreach(item, self->blocks) { + if(!item->data) { + continue; + } + if((ret = trtp_rtcp_rblock_serialize_to(TRTP_RTCP_RBLOCK(item->data), pdata, size))) { + TSK_DEBUG_ERROR("Failed to serialize the rblock"); + goto bail; + } + pdata += TRTP_RTCP_RBLOCK_SIZE; + size -= TRTP_RTCP_RBLOCK_SIZE; + } + } + + tsk_list_foreach(item, self->packets) { + if(!item->data) { + continue; + } + if((ret = trtp_rtcp_packet_serialize_to(TRTP_RTCP_PACKET(item->data), pdata, size))) { + TSK_DEBUG_ERROR("Failed to serialize packet"); + goto bail; + } + pdata += TRTP_RTCP_PACKET(item->data)->header->length_in_bytes; + size -= TRTP_RTCP_PACKET(item->data)->header->length_in_bytes; + } bail: - return ret; + return ret; } tsk_size_t trtp_rtcp_report_rr_get_size(const trtp_rtcp_report_rr_t* self) { - tsk_size_t size; - const tsk_list_item_t* item; - - if(!self || !TRTP_RTCP_PACKET(self)->header){ - TSK_DEBUG_ERROR("Invalid parameter"); - return 0; - } - - size = TRTP_RTCP_PACKET(self)->header->length_in_bytes; - if(TRTP_RTCP_PACKET(self)->header->rc > 0){ - tsk_list_foreach(item, self->blocks){ - if(item->data){ - size += TRTP_RTCP_RBLOCK_SIZE; - } - } - } - tsk_list_foreach(item, self->packets){ - if(item->data && TRTP_RTCP_PACKET(item->data)->header){ - size += TRTP_RTCP_PACKET(item->data)->header->length_in_bytes; - } - } - - return size; + tsk_size_t size; + const tsk_list_item_t* item; + + if(!self || !TRTP_RTCP_PACKET(self)->header) { + TSK_DEBUG_ERROR("Invalid parameter"); + return 0; + } + + size = TRTP_RTCP_PACKET(self)->header->length_in_bytes; + if(TRTP_RTCP_PACKET(self)->header->rc > 0) { + tsk_list_foreach(item, self->blocks) { + if(item->data) { + size += TRTP_RTCP_RBLOCK_SIZE; + } + } + } + tsk_list_foreach(item, self->packets) { + if(item->data && TRTP_RTCP_PACKET(item->data)->header) { + size += TRTP_RTCP_PACKET(item->data)->header->length_in_bytes; + } + } + + return size; } \ No newline at end of file diff --git a/tinyRTP/src/rtcp/trtp_rtcp_report_sdes.c b/tinyRTP/src/rtcp/trtp_rtcp_report_sdes.c index 4f5e944..8013509 100755 --- a/tinyRTP/src/rtcp/trtp_rtcp_report_sdes.c +++ b/tinyRTP/src/rtcp/trtp_rtcp_report_sdes.c @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -26,7 +26,7 @@ /* 6.5 SDES: Source Description RTCP Packet - 0 1 2 + 0 1 2 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ header |V=2|P| SC | PT=SDES=202 | length | @@ -45,170 +45,169 @@ chunk | SSRC/CSRC_2 | static tsk_object_t* trtp_rtcp_report_sdes_ctor(tsk_object_t * self, va_list * app) { - trtp_rtcp_report_sdes_t *sdes = self; - if(sdes){ - sdes->chuncks = tsk_list_create(); - } - return self; + trtp_rtcp_report_sdes_t *sdes = self; + if(sdes) { + sdes->chuncks = tsk_list_create(); + } + return self; } static tsk_object_t* trtp_rtcp_report_sdes_dtor(tsk_object_t * self) -{ - trtp_rtcp_report_sdes_t *sdes = self; - if(sdes){ - // deinit base - trtp_rtcp_packet_deinit(TRTP_RTCP_PACKET(sdes)); - // deinit self - TSK_OBJECT_SAFE_FREE(sdes->chuncks); - } - - return self; -} -static const tsk_object_def_t trtp_rtcp_report_sdes_def_s = { - sizeof(trtp_rtcp_report_sdes_t), - trtp_rtcp_report_sdes_ctor, - trtp_rtcp_report_sdes_dtor, - tsk_null, + trtp_rtcp_report_sdes_t *sdes = self; + if(sdes) { + // deinit base + trtp_rtcp_packet_deinit(TRTP_RTCP_PACKET(sdes)); + // deinit self + TSK_OBJECT_SAFE_FREE(sdes->chuncks); + } + + return self; +} +static const tsk_object_def_t trtp_rtcp_report_sdes_def_s = { + sizeof(trtp_rtcp_report_sdes_t), + trtp_rtcp_report_sdes_ctor, + trtp_rtcp_report_sdes_dtor, + tsk_null, }; const tsk_object_def_t *trtp_rtcp_report_sdes_def_t = &trtp_rtcp_report_sdes_def_s; trtp_rtcp_report_sdes_t* trtp_rtcp_report_sdes_create_null() { - trtp_rtcp_report_sdes_t* sdes; - if((sdes = (trtp_rtcp_report_sdes_t*)tsk_object_new(trtp_rtcp_report_sdes_def_t))){ - trtp_rtcp_packet_init(TRTP_RTCP_PACKET(sdes), TRTP_RTCP_HEADER_VERSION_DEFAULT, 0, 0, trtp_rtcp_packet_type_sdes, TRTP_RTCP_HEADER_SIZE); - } - return sdes; + trtp_rtcp_report_sdes_t* sdes; + if((sdes = (trtp_rtcp_report_sdes_t*)tsk_object_new(trtp_rtcp_report_sdes_def_t))) { + trtp_rtcp_packet_init(TRTP_RTCP_PACKET(sdes), TRTP_RTCP_HEADER_VERSION_DEFAULT, 0, 0, trtp_rtcp_packet_type_sdes, TRTP_RTCP_HEADER_SIZE); + } + return sdes; } trtp_rtcp_report_sdes_t* trtp_rtcp_report_sdes_create(trtp_rtcp_header_t* header) { - trtp_rtcp_report_sdes_t* sdes; - if((sdes = (trtp_rtcp_report_sdes_t*)tsk_object_new(trtp_rtcp_report_sdes_def_t))){ - TRTP_RTCP_PACKET(sdes)->header = tsk_object_ref(header); - } - return sdes; + trtp_rtcp_report_sdes_t* sdes; + if((sdes = (trtp_rtcp_report_sdes_t*)tsk_object_new(trtp_rtcp_report_sdes_def_t))) { + TRTP_RTCP_PACKET(sdes)->header = tsk_object_ref(header); + } + return sdes; } trtp_rtcp_report_sdes_t* trtp_rtcp_report_sdes_deserialize(const void* data, tsk_size_t _size) { - trtp_rtcp_report_sdes_t* sdes = tsk_null; - trtp_rtcp_header_t* header = tsk_null; - const uint8_t* pdata = (const uint8_t*)data; - int32_t size = (int32_t)_size; - - if(!data || size < TRTP_RTCP_HEADER_SIZE){ - TSK_DEBUG_ERROR("Invalid parameter"); - return tsk_null; - } - - if(!(header = trtp_rtcp_header_deserialize(pdata, size))){ - TSK_DEBUG_ERROR("Failed to deserialize the header"); - goto bail; - } - if(header->length_in_bytes < (TRTP_RTCP_HEADER_SIZE + 4)){ - TSK_DEBUG_ERROR("Too short"); - goto bail; - } - - if(!(sdes = trtp_rtcp_report_sdes_create(header))){ - TSK_DEBUG_ERROR("Failed to create object"); - goto bail; - } - - pdata += TRTP_RTCP_HEADER_SIZE; - size -= TRTP_RTCP_HEADER_SIZE; - - // Chuncks - if(header->rc > 0){ - tsk_size_t i = 0, chunck_size; - trtp_rtcp_sdes_chunck_t* chunck; - while(i++ < header->rc && size > TRTP_RTCP_SDES_CHUNCK_MIN_SIZE){ - if((chunck = trtp_rtcp_sdes_chunck_deserialize(pdata, size))){ - chunck_size = trtp_rtcp_sdes_chunck_get_size(chunck); - if((size -= (int32_t)chunck_size)){ - pdata += chunck_size; - } - tsk_list_push_ascending_data(sdes->chuncks, (void**)&chunck); - continue; - } - break; - } - } + trtp_rtcp_report_sdes_t* sdes = tsk_null; + trtp_rtcp_header_t* header = tsk_null; + const uint8_t* pdata = (const uint8_t*)data; + int32_t size = (int32_t)_size; + + if(!data || size < TRTP_RTCP_HEADER_SIZE) { + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_null; + } + + if(!(header = trtp_rtcp_header_deserialize(pdata, size))) { + TSK_DEBUG_ERROR("Failed to deserialize the header"); + goto bail; + } + if(header->length_in_bytes < (TRTP_RTCP_HEADER_SIZE + 4)) { + TSK_DEBUG_ERROR("Too short"); + goto bail; + } + + if(!(sdes = trtp_rtcp_report_sdes_create(header))) { + TSK_DEBUG_ERROR("Failed to create object"); + goto bail; + } + + pdata += TRTP_RTCP_HEADER_SIZE; + size -= TRTP_RTCP_HEADER_SIZE; + + // Chuncks + if(header->rc > 0) { + tsk_size_t i = 0, chunck_size; + trtp_rtcp_sdes_chunck_t* chunck; + while(i++ < header->rc && size > TRTP_RTCP_SDES_CHUNCK_MIN_SIZE) { + if((chunck = trtp_rtcp_sdes_chunck_deserialize(pdata, size))) { + chunck_size = trtp_rtcp_sdes_chunck_get_size(chunck); + if((size -= (int32_t)chunck_size)) { + pdata += chunck_size; + } + tsk_list_push_ascending_data(sdes->chuncks, (void**)&chunck); + continue; + } + break; + } + } bail: - TSK_OBJECT_SAFE_FREE(header); - return sdes; + TSK_OBJECT_SAFE_FREE(header); + return sdes; } int trtp_rtcp_report_sdes_serialize_to(const trtp_rtcp_report_sdes_t* self, void* data, tsk_size_t size) { - int ret; - uint8_t* pdata = (uint8_t*)data; - if(!self || !data || size < trtp_rtcp_report_sdes_get_size(self)){ - return -1; - } - - if((ret = trtp_rtcp_header_serialize_to(TRTP_RTCP_PACKET(self)->header, pdata, size))){ - TSK_DEBUG_ERROR("Failed to serialize the header"); - return ret; - } - - pdata += (TRTP_RTCP_HEADER_SIZE); - size -= (TRTP_RTCP_HEADER_SIZE); - - if(TRTP_RTCP_PACKET(self)->header->rc > 0){ - const tsk_list_item_t* item; - tsk_size_t chunck_size; - const trtp_rtcp_sdes_chunck_t* chunck; - tsk_list_foreach(item, self->chuncks){ - if(!(chunck = item->data)){ - continue; - } - if((ret = trtp_rtcp_sdes_chunck_serialize_to(chunck, pdata, size))){ - TSK_DEBUG_ERROR("Failed to serialize SDES chunck"); - goto bail; - } - chunck_size = trtp_rtcp_sdes_chunck_get_size(chunck); - pdata += chunck_size; - size -= chunck_size; - } - } + int ret; + uint8_t* pdata = (uint8_t*)data; + if(!self || !data || size < trtp_rtcp_report_sdes_get_size(self)) { + return -1; + } + + if((ret = trtp_rtcp_header_serialize_to(TRTP_RTCP_PACKET(self)->header, pdata, size))) { + TSK_DEBUG_ERROR("Failed to serialize the header"); + return ret; + } + + pdata += (TRTP_RTCP_HEADER_SIZE); + size -= (TRTP_RTCP_HEADER_SIZE); + + if(TRTP_RTCP_PACKET(self)->header->rc > 0) { + const tsk_list_item_t* item; + tsk_size_t chunck_size; + const trtp_rtcp_sdes_chunck_t* chunck; + tsk_list_foreach(item, self->chuncks) { + if(!(chunck = item->data)) { + continue; + } + if((ret = trtp_rtcp_sdes_chunck_serialize_to(chunck, pdata, size))) { + TSK_DEBUG_ERROR("Failed to serialize SDES chunck"); + goto bail; + } + chunck_size = trtp_rtcp_sdes_chunck_get_size(chunck); + pdata += chunck_size; + size -= chunck_size; + } + } bail: - return ret; + return ret; } int trtp_rtcp_report_sdes_add_chunck(trtp_rtcp_report_sdes_t* self, trtp_rtcp_sdes_chunck_t* chunck) { - if(!self || !self->chuncks || !chunck){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - chunck = tsk_object_ref(chunck); - TRTP_RTCP_PACKET(self)->header->length_in_bytes += (uint32_t)trtp_rtcp_sdes_chunck_get_size(chunck); - TRTP_RTCP_PACKET(self)->header->length_in_words_minus1 = ((TRTP_RTCP_PACKET(self)->header->length_in_bytes >> 2) - 1) - + ((TRTP_RTCP_PACKET(self)->header->length_in_bytes & 0x03) ? 1 : 0); - ++TRTP_RTCP_PACKET(self)->header->rc; - tsk_list_push_back_data(self->chuncks, (void**)&chunck); - return 0; + if(!self || !self->chuncks || !chunck) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + chunck = tsk_object_ref(chunck); + TRTP_RTCP_PACKET(self)->header->length_in_bytes += (uint32_t)trtp_rtcp_sdes_chunck_get_size(chunck); + TRTP_RTCP_PACKET(self)->header->length_in_words_minus1 = ((TRTP_RTCP_PACKET(self)->header->length_in_bytes >> 2) - 1) + + ((TRTP_RTCP_PACKET(self)->header->length_in_bytes & 0x03) ? 1 : 0); + ++TRTP_RTCP_PACKET(self)->header->rc; + tsk_list_push_back_data(self->chuncks, (void**)&chunck); + return 0; } tsk_size_t trtp_rtcp_report_sdes_get_size(const trtp_rtcp_report_sdes_t* self) { - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return 0; - } - else{ - tsk_size_t size = TRTP_RTCP_HEADER_SIZE; - const tsk_list_item_t* item; - tsk_list_foreach(item, self->chuncks){ - size += trtp_rtcp_sdes_chunck_get_size(TRTP_RTCP_SDES_CHUNCK(item->data)); - } - return size; - } + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return 0; + } + else { + tsk_size_t size = TRTP_RTCP_HEADER_SIZE; + const tsk_list_item_t* item; + tsk_list_foreach(item, self->chuncks) { + size += trtp_rtcp_sdes_chunck_get_size(TRTP_RTCP_SDES_CHUNCK(item->data)); + } + return size; + } } diff --git a/tinyRTP/src/rtcp/trtp_rtcp_report_sr.c b/tinyRTP/src/rtcp/trtp_rtcp_report_sr.c index 5d8ceda..e807f17 100755 --- a/tinyRTP/src/rtcp/trtp_rtcp_report_sr.c +++ b/tinyRTP/src/rtcp/trtp_rtcp_report_sr.c @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -30,241 +30,240 @@ static tsk_object_t* trtp_rtcp_report_sr_ctor(tsk_object_t * self, va_list * app) { - trtp_rtcp_report_sr_t *sr = self; - if(sr){ - sr->blocks = tsk_list_create(); - sr->packets = tsk_list_create(); - } - return self; + trtp_rtcp_report_sr_t *sr = self; + if(sr) { + sr->blocks = tsk_list_create(); + sr->packets = tsk_list_create(); + } + return self; } static tsk_object_t* trtp_rtcp_report_sr_dtor(tsk_object_t * self) -{ - trtp_rtcp_report_sr_t *sr = self; - if(sr){ - // deinit self - TSK_OBJECT_SAFE_FREE(sr->blocks); - TSK_OBJECT_SAFE_FREE(sr->packets); - // deinit base - trtp_rtcp_packet_deinit(TRTP_RTCP_PACKET(sr)); - } - - return self; +{ + trtp_rtcp_report_sr_t *sr = self; + if(sr) { + // deinit self + TSK_OBJECT_SAFE_FREE(sr->blocks); + TSK_OBJECT_SAFE_FREE(sr->packets); + // deinit base + trtp_rtcp_packet_deinit(TRTP_RTCP_PACKET(sr)); + } + + return self; } -static const tsk_object_def_t trtp_rtcp_report_sr_def_s = -{ - sizeof(trtp_rtcp_report_sr_t), - trtp_rtcp_report_sr_ctor, - trtp_rtcp_report_sr_dtor, - tsk_null, +static const tsk_object_def_t trtp_rtcp_report_sr_def_s = { + sizeof(trtp_rtcp_report_sr_t), + trtp_rtcp_report_sr_ctor, + trtp_rtcp_report_sr_dtor, + tsk_null, }; const tsk_object_def_t *trtp_rtcp_report_sr_def_t = &trtp_rtcp_report_sr_def_s; trtp_rtcp_report_sr_t* trtp_rtcp_report_sr_create_null() { - trtp_rtcp_report_sr_t* sr; - if((sr = (trtp_rtcp_report_sr_t*)tsk_object_new(trtp_rtcp_report_sr_def_t))){ - trtp_rtcp_packet_init(TRTP_RTCP_PACKET(sr), TRTP_RTCP_HEADER_VERSION_DEFAULT, 0, 0, trtp_rtcp_packet_type_sr, (TRTP_RTCP_HEADER_SIZE + 4 + 20)); - } - return sr; + trtp_rtcp_report_sr_t* sr; + if((sr = (trtp_rtcp_report_sr_t*)tsk_object_new(trtp_rtcp_report_sr_def_t))) { + trtp_rtcp_packet_init(TRTP_RTCP_PACKET(sr), TRTP_RTCP_HEADER_VERSION_DEFAULT, 0, 0, trtp_rtcp_packet_type_sr, (TRTP_RTCP_HEADER_SIZE + 4 + 20)); + } + return sr; } trtp_rtcp_report_sr_t* trtp_rtcp_report_sr_create(struct trtp_rtcp_header_s* header) { - trtp_rtcp_report_sr_t* sr; - if((sr = (trtp_rtcp_report_sr_t*)tsk_object_new(trtp_rtcp_report_sr_def_t))){ - TRTP_RTCP_PACKET(sr)->header = tsk_object_ref(header); - } - return sr; + trtp_rtcp_report_sr_t* sr; + if((sr = (trtp_rtcp_report_sr_t*)tsk_object_new(trtp_rtcp_report_sr_def_t))) { + TRTP_RTCP_PACKET(sr)->header = tsk_object_ref(header); + } + return sr; } trtp_rtcp_report_sr_t* trtp_rtcp_report_sr_deserialize(const void* data, tsk_size_t _size) { - trtp_rtcp_report_sr_t* sr = tsk_null; - trtp_rtcp_header_t* header = tsk_null; - const uint8_t* pdata = (const uint8_t*)data; - int32_t size = (int32_t)_size; - - if(!data || size < TRTP_RTCP_PACKET_SR_MIN_SIZE){ - TSK_DEBUG_ERROR("Invalid parameter"); - return tsk_null; - } - - if(!(header = trtp_rtcp_header_deserialize(pdata, size))){ - TSK_DEBUG_ERROR("Failed to deserialize the header"); - goto bail; - } - if(header->length_in_bytes < TRTP_RTCP_PACKET_SR_MIN_SIZE){ - TSK_DEBUG_ERROR("Too short"); - goto bail; - } - - if(!(sr = trtp_rtcp_report_sr_create(header))){ - TSK_DEBUG_ERROR("Failed to create object"); - goto bail; - } - - sr->ssrc = (uint32_t)tnet_ntohl_2(&pdata[4]); - pdata += (TRTP_RTCP_HEADER_SIZE + 4); - size -= (TRTP_RTCP_HEADER_SIZE + 4); - - // sender info - sr->sender_info.ntp_msw = (uint32_t)tnet_ntohl_2(&pdata[0]); - sr->sender_info.ntp_lsw = (uint32_t)tnet_ntohl_2(&pdata[4]); - sr->sender_info.rtp_timestamp = (uint32_t)tnet_ntohl_2(&pdata[8]); - sr->sender_info.sender_pcount = (uint32_t)tnet_ntohl_2(&pdata[12]); - sr->sender_info.sender_ocount = (uint32_t)tnet_ntohl_2(&pdata[16]); - pdata += 20; - size -= 20; - - // Blocks - if(header->rc > 0){ - tsk_size_t i = 0; - trtp_rtcp_rblock_t* rblock; - - while(i++ < header->rc && size >= TRTP_RTCP_RBLOCK_SIZE){ - if((rblock = trtp_rtcp_rblock_deserialize(pdata, size))){ - tsk_list_push_back_data(sr->blocks, (void**)&rblock); - } - pdata += TRTP_RTCP_RBLOCK_SIZE; - size -= TRTP_RTCP_RBLOCK_SIZE; - } - } - - // Other Packets - while(size > TRTP_RTCP_HEADER_SIZE){ - trtp_rtcp_packet_t* packet; - - if((packet = trtp_rtcp_packet_deserialize(pdata, size))){ - if((size -= packet->header->length_in_bytes) > 0){ - pdata += packet->header->length_in_bytes; - } - tsk_list_push_back_data(sr->packets, (void**)&packet); - continue; - } - break; - } + trtp_rtcp_report_sr_t* sr = tsk_null; + trtp_rtcp_header_t* header = tsk_null; + const uint8_t* pdata = (const uint8_t*)data; + int32_t size = (int32_t)_size; + + if(!data || size < TRTP_RTCP_PACKET_SR_MIN_SIZE) { + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_null; + } + + if(!(header = trtp_rtcp_header_deserialize(pdata, size))) { + TSK_DEBUG_ERROR("Failed to deserialize the header"); + goto bail; + } + if(header->length_in_bytes < TRTP_RTCP_PACKET_SR_MIN_SIZE) { + TSK_DEBUG_ERROR("Too short"); + goto bail; + } + + if(!(sr = trtp_rtcp_report_sr_create(header))) { + TSK_DEBUG_ERROR("Failed to create object"); + goto bail; + } + + sr->ssrc = (uint32_t)tnet_ntohl_2(&pdata[4]); + pdata += (TRTP_RTCP_HEADER_SIZE + 4); + size -= (TRTP_RTCP_HEADER_SIZE + 4); + + // sender info + sr->sender_info.ntp_msw = (uint32_t)tnet_ntohl_2(&pdata[0]); + sr->sender_info.ntp_lsw = (uint32_t)tnet_ntohl_2(&pdata[4]); + sr->sender_info.rtp_timestamp = (uint32_t)tnet_ntohl_2(&pdata[8]); + sr->sender_info.sender_pcount = (uint32_t)tnet_ntohl_2(&pdata[12]); + sr->sender_info.sender_ocount = (uint32_t)tnet_ntohl_2(&pdata[16]); + pdata += 20; + size -= 20; + + // Blocks + if(header->rc > 0) { + tsk_size_t i = 0; + trtp_rtcp_rblock_t* rblock; + + while(i++ < header->rc && size >= TRTP_RTCP_RBLOCK_SIZE) { + if((rblock = trtp_rtcp_rblock_deserialize(pdata, size))) { + tsk_list_push_back_data(sr->blocks, (void**)&rblock); + } + pdata += TRTP_RTCP_RBLOCK_SIZE; + size -= TRTP_RTCP_RBLOCK_SIZE; + } + } + + // Other Packets + while(size > TRTP_RTCP_HEADER_SIZE) { + trtp_rtcp_packet_t* packet; + + if((packet = trtp_rtcp_packet_deserialize(pdata, size))) { + if((size -= packet->header->length_in_bytes) > 0) { + pdata += packet->header->length_in_bytes; + } + tsk_list_push_back_data(sr->packets, (void**)&packet); + continue; + } + break; + } bail: - TSK_OBJECT_SAFE_FREE(header); - return sr; + TSK_OBJECT_SAFE_FREE(header); + return sr; } int trtp_rtcp_report_sr_serialize_to(const trtp_rtcp_report_sr_t* self, void* data, tsk_size_t size) { - int ret; - const tsk_list_item_t* item; - uint8_t* pdata = (uint8_t*)data; - - if(!self || !data || size < trtp_rtcp_report_sr_get_size(self)){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if((ret = trtp_rtcp_header_serialize_to(TRTP_RTCP_PACKET(self)->header, pdata, size))){ - TSK_DEBUG_ERROR("Failed to serialize the header"); - return ret; - } - - pdata[TRTP_RTCP_HEADER_SIZE] = self->ssrc >> 24; - pdata[TRTP_RTCP_HEADER_SIZE + 1] = (self->ssrc >> 16) & 0xFF; - pdata[TRTP_RTCP_HEADER_SIZE + 2] = (self->ssrc >> 8) & 0xFF; - pdata[TRTP_RTCP_HEADER_SIZE + 3] = (self->ssrc & 0xFF); - pdata[TRTP_RTCP_HEADER_SIZE + 4] = self->sender_info.ntp_msw >> 24; - pdata[TRTP_RTCP_HEADER_SIZE + 5] = (self->sender_info.ntp_msw >> 16) & 0xFF; - pdata[TRTP_RTCP_HEADER_SIZE + 6] = (self->sender_info.ntp_msw >> 8) & 0xFF; - pdata[TRTP_RTCP_HEADER_SIZE + 7] = self->sender_info.ntp_msw & 0xFF; - pdata[TRTP_RTCP_HEADER_SIZE + 8] = self->sender_info.ntp_lsw >> 24; - pdata[TRTP_RTCP_HEADER_SIZE + 9] = (self->sender_info.ntp_lsw >> 16) & 0xFF; - pdata[TRTP_RTCP_HEADER_SIZE + 10] = (self->sender_info.ntp_lsw >> 8) & 0xFF; - pdata[TRTP_RTCP_HEADER_SIZE + 11] = self->sender_info.ntp_lsw & 0xFF; - pdata[TRTP_RTCP_HEADER_SIZE + 12] = self->sender_info.rtp_timestamp >> 24; - pdata[TRTP_RTCP_HEADER_SIZE + 13] = (self->sender_info.rtp_timestamp >> 16) & 0xFF; - pdata[TRTP_RTCP_HEADER_SIZE + 14] = (self->sender_info.rtp_timestamp >> 8) & 0xFF; - pdata[TRTP_RTCP_HEADER_SIZE + 15] = self->sender_info.rtp_timestamp & 0xFF; - pdata[TRTP_RTCP_HEADER_SIZE + 16] = self->sender_info.sender_pcount >> 24; - pdata[TRTP_RTCP_HEADER_SIZE + 17] = (self->sender_info.sender_pcount >> 16) & 0xFF; - pdata[TRTP_RTCP_HEADER_SIZE + 18] = (self->sender_info.sender_pcount >> 8) & 0xFF; - pdata[TRTP_RTCP_HEADER_SIZE + 19] = self->sender_info.sender_pcount & 0xFF; - pdata[TRTP_RTCP_HEADER_SIZE + 20] = self->sender_info.sender_ocount >> 24; - pdata[TRTP_RTCP_HEADER_SIZE + 21] = (self->sender_info.sender_ocount >> 16) & 0xFF; - pdata[TRTP_RTCP_HEADER_SIZE + 22] = (self->sender_info.sender_ocount >> 8) & 0xFF; - pdata[TRTP_RTCP_HEADER_SIZE + 23] = self->sender_info.sender_ocount & 0xFF; - - pdata += (TRTP_RTCP_HEADER_SIZE + 4 + 20); - size -= (TRTP_RTCP_HEADER_SIZE + 4 + 20); - - if(TRTP_RTCP_PACKET(self)->header->rc > 0){ - tsk_list_foreach(item, self->blocks){ - if(!item->data){ - continue; - } - if((ret = trtp_rtcp_rblock_serialize_to(TRTP_RTCP_RBLOCK(item->data), pdata, size))){ - TSK_DEBUG_ERROR("Failed to serialize the rblock"); - goto bail; - } - pdata += TRTP_RTCP_RBLOCK_SIZE; - size -= TRTP_RTCP_RBLOCK_SIZE; - } - } - - tsk_list_foreach(item, self->packets){ - if(!item->data){ - continue; - } - if((ret = trtp_rtcp_packet_serialize_to(TRTP_RTCP_PACKET(item->data), pdata, size))){ - TSK_DEBUG_ERROR("Failed to serialize packet"); - goto bail; - } - pdata += TRTP_RTCP_PACKET(item->data)->header->length_in_bytes; - size -= TRTP_RTCP_PACKET(item->data)->header->length_in_bytes; - } + int ret; + const tsk_list_item_t* item; + uint8_t* pdata = (uint8_t*)data; + + if(!self || !data || size < trtp_rtcp_report_sr_get_size(self)) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if((ret = trtp_rtcp_header_serialize_to(TRTP_RTCP_PACKET(self)->header, pdata, size))) { + TSK_DEBUG_ERROR("Failed to serialize the header"); + return ret; + } + + pdata[TRTP_RTCP_HEADER_SIZE] = self->ssrc >> 24; + pdata[TRTP_RTCP_HEADER_SIZE + 1] = (self->ssrc >> 16) & 0xFF; + pdata[TRTP_RTCP_HEADER_SIZE + 2] = (self->ssrc >> 8) & 0xFF; + pdata[TRTP_RTCP_HEADER_SIZE + 3] = (self->ssrc & 0xFF); + pdata[TRTP_RTCP_HEADER_SIZE + 4] = self->sender_info.ntp_msw >> 24; + pdata[TRTP_RTCP_HEADER_SIZE + 5] = (self->sender_info.ntp_msw >> 16) & 0xFF; + pdata[TRTP_RTCP_HEADER_SIZE + 6] = (self->sender_info.ntp_msw >> 8) & 0xFF; + pdata[TRTP_RTCP_HEADER_SIZE + 7] = self->sender_info.ntp_msw & 0xFF; + pdata[TRTP_RTCP_HEADER_SIZE + 8] = self->sender_info.ntp_lsw >> 24; + pdata[TRTP_RTCP_HEADER_SIZE + 9] = (self->sender_info.ntp_lsw >> 16) & 0xFF; + pdata[TRTP_RTCP_HEADER_SIZE + 10] = (self->sender_info.ntp_lsw >> 8) & 0xFF; + pdata[TRTP_RTCP_HEADER_SIZE + 11] = self->sender_info.ntp_lsw & 0xFF; + pdata[TRTP_RTCP_HEADER_SIZE + 12] = self->sender_info.rtp_timestamp >> 24; + pdata[TRTP_RTCP_HEADER_SIZE + 13] = (self->sender_info.rtp_timestamp >> 16) & 0xFF; + pdata[TRTP_RTCP_HEADER_SIZE + 14] = (self->sender_info.rtp_timestamp >> 8) & 0xFF; + pdata[TRTP_RTCP_HEADER_SIZE + 15] = self->sender_info.rtp_timestamp & 0xFF; + pdata[TRTP_RTCP_HEADER_SIZE + 16] = self->sender_info.sender_pcount >> 24; + pdata[TRTP_RTCP_HEADER_SIZE + 17] = (self->sender_info.sender_pcount >> 16) & 0xFF; + pdata[TRTP_RTCP_HEADER_SIZE + 18] = (self->sender_info.sender_pcount >> 8) & 0xFF; + pdata[TRTP_RTCP_HEADER_SIZE + 19] = self->sender_info.sender_pcount & 0xFF; + pdata[TRTP_RTCP_HEADER_SIZE + 20] = self->sender_info.sender_ocount >> 24; + pdata[TRTP_RTCP_HEADER_SIZE + 21] = (self->sender_info.sender_ocount >> 16) & 0xFF; + pdata[TRTP_RTCP_HEADER_SIZE + 22] = (self->sender_info.sender_ocount >> 8) & 0xFF; + pdata[TRTP_RTCP_HEADER_SIZE + 23] = self->sender_info.sender_ocount & 0xFF; + + pdata += (TRTP_RTCP_HEADER_SIZE + 4 + 20); + size -= (TRTP_RTCP_HEADER_SIZE + 4 + 20); + + if(TRTP_RTCP_PACKET(self)->header->rc > 0) { + tsk_list_foreach(item, self->blocks) { + if(!item->data) { + continue; + } + if((ret = trtp_rtcp_rblock_serialize_to(TRTP_RTCP_RBLOCK(item->data), pdata, size))) { + TSK_DEBUG_ERROR("Failed to serialize the rblock"); + goto bail; + } + pdata += TRTP_RTCP_RBLOCK_SIZE; + size -= TRTP_RTCP_RBLOCK_SIZE; + } + } + + tsk_list_foreach(item, self->packets) { + if(!item->data) { + continue; + } + if((ret = trtp_rtcp_packet_serialize_to(TRTP_RTCP_PACKET(item->data), pdata, size))) { + TSK_DEBUG_ERROR("Failed to serialize packet"); + goto bail; + } + pdata += TRTP_RTCP_PACKET(item->data)->header->length_in_bytes; + size -= TRTP_RTCP_PACKET(item->data)->header->length_in_bytes; + } bail: - return ret; + return ret; } int trtp_rtcp_report_sr_add_block(trtp_rtcp_report_sr_t* self, trtp_rtcp_rblock_t* rblock) { - if(!self || !TRTP_RTCP_PACKET(self)->header || !rblock){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - rblock = tsk_object_ref(rblock); - tsk_list_push_back_data(self->blocks, (void**)&rblock); - ++TRTP_RTCP_PACKET(self)->header->rc; - TRTP_RTCP_PACKET(self)->header->length_in_bytes += TRTP_RTCP_RBLOCK_SIZE; - TRTP_RTCP_PACKET(self)->header->length_in_words_minus1 = ((TRTP_RTCP_PACKET(self)->header->length_in_bytes >> 2) - 1) + - ((TRTP_RTCP_PACKET(self)->header->length_in_bytes & 0x03) ? 1 : 0); - return 0; + if(!self || !TRTP_RTCP_PACKET(self)->header || !rblock) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + rblock = tsk_object_ref(rblock); + tsk_list_push_back_data(self->blocks, (void**)&rblock); + ++TRTP_RTCP_PACKET(self)->header->rc; + TRTP_RTCP_PACKET(self)->header->length_in_bytes += TRTP_RTCP_RBLOCK_SIZE; + TRTP_RTCP_PACKET(self)->header->length_in_words_minus1 = ((TRTP_RTCP_PACKET(self)->header->length_in_bytes >> 2) - 1) + + ((TRTP_RTCP_PACKET(self)->header->length_in_bytes & 0x03) ? 1 : 0); + return 0; } tsk_size_t trtp_rtcp_report_sr_get_size(const trtp_rtcp_report_sr_t* self) { - tsk_size_t size; - const tsk_list_item_t* item; - - if(!self || !TRTP_RTCP_PACKET(self)->header){ - TSK_DEBUG_ERROR("Invalid parameter"); - return 0; - } - - size = TRTP_RTCP_PACKET(self)->header->length_in_bytes; - //if(TRTP_RTCP_PACKET(self)->header->rc > 0){ - // tsk_list_foreach(item, self->blocks){ - // if(item->data){ - // size += TRTP_RTCP_RBLOCK_SIZE; - // } - // } - //} - tsk_list_foreach(item, self->packets){ - if(item->data && TRTP_RTCP_PACKET(item->data)->header){ - size += TRTP_RTCP_PACKET(item->data)->header->length_in_bytes; - } - } - - return size; + tsk_size_t size; + const tsk_list_item_t* item; + + if(!self || !TRTP_RTCP_PACKET(self)->header) { + TSK_DEBUG_ERROR("Invalid parameter"); + return 0; + } + + size = TRTP_RTCP_PACKET(self)->header->length_in_bytes; + //if(TRTP_RTCP_PACKET(self)->header->rc > 0){ + // tsk_list_foreach(item, self->blocks){ + // if(item->data){ + // size += TRTP_RTCP_RBLOCK_SIZE; + // } + // } + //} + tsk_list_foreach(item, self->packets) { + if(item->data && TRTP_RTCP_PACKET(item->data)->header) { + size += TRTP_RTCP_PACKET(item->data)->header->length_in_bytes; + } + } + + return size; } diff --git a/tinyRTP/src/rtcp/trtp_rtcp_report_xr.c b/tinyRTP/src/rtcp/trtp_rtcp_report_xr.c index 5fb2697..41e177b 100755 --- a/tinyRTP/src/rtcp/trtp_rtcp_report_xr.c +++ b/tinyRTP/src/rtcp/trtp_rtcp_report_xr.c @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * diff --git a/tinyRTP/src/rtcp/trtp_rtcp_sdes_chunck.c b/tinyRTP/src/rtcp/trtp_rtcp_sdes_chunck.c index 9104580..f8bed63 100755 --- a/tinyRTP/src/rtcp/trtp_rtcp_sdes_chunck.c +++ b/tinyRTP/src/rtcp/trtp_rtcp_sdes_chunck.c @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -44,27 +44,26 @@ Each chunk consists of an SSRC/CSRC identifier followed by a list of static tsk_object_t* trtp_rtcp_sdes_chunck_ctor(tsk_object_t * self, va_list * app) { - trtp_rtcp_sdes_chunck_t *chunck = self; - if(chunck){ - chunck->items = tsk_list_create(); - } - return self; + trtp_rtcp_sdes_chunck_t *chunck = self; + if(chunck) { + chunck->items = tsk_list_create(); + } + return self; } static tsk_object_t* trtp_rtcp_sdes_chunck_dtor(tsk_object_t * self) -{ - trtp_rtcp_sdes_chunck_t *chunck = self; - if(chunck){ - TSK_OBJECT_SAFE_FREE(chunck->items); - } +{ + trtp_rtcp_sdes_chunck_t *chunck = self; + if(chunck) { + TSK_OBJECT_SAFE_FREE(chunck->items); + } - return self; + return self; } -static const tsk_object_def_t trtp_rtcp_sdes_chunck_def_s = -{ - sizeof(trtp_rtcp_sdes_chunck_t), - trtp_rtcp_sdes_chunck_ctor, - trtp_rtcp_sdes_chunck_dtor, - tsk_null, +static const tsk_object_def_t trtp_rtcp_sdes_chunck_def_s = { + sizeof(trtp_rtcp_sdes_chunck_t), + trtp_rtcp_sdes_chunck_ctor, + trtp_rtcp_sdes_chunck_dtor, + tsk_null, }; const tsk_object_def_t *trtp_rtcp_sdes_chunck_def_t = &trtp_rtcp_sdes_chunck_def_s; @@ -72,119 +71,120 @@ const tsk_object_def_t *trtp_rtcp_sdes_chunck_def_t = &trtp_rtcp_sdes_chunck_def trtp_rtcp_sdes_chunck_t* trtp_rtcp_sdes_chunck_create_null() { - return tsk_object_new(trtp_rtcp_sdes_chunck_def_t); + return tsk_object_new(trtp_rtcp_sdes_chunck_def_t); } trtp_rtcp_sdes_chunck_t* trtp_rtcp_sdes_chunck_create(uint32_t ssrc) { - trtp_rtcp_sdes_chunck_t* chunck; - if((chunck = trtp_rtcp_sdes_chunck_create_null())){ - chunck->ssrc = ssrc; - } - return chunck; + trtp_rtcp_sdes_chunck_t* chunck; + if((chunck = trtp_rtcp_sdes_chunck_create_null())) { + chunck->ssrc = ssrc; + } + return chunck; } trtp_rtcp_sdes_chunck_t* trtp_rtcp_sdes_chunck_deserialize(const void* data, tsk_size_t size) { - trtp_rtcp_sdes_chunck_t* chunck = tsk_null; - const uint8_t* pdata = (uint8_t*)data; - const uint8_t* pend; - if(!data || size < TRTP_RTCP_SDES_CHUNCK_MIN_SIZE){ - TSK_DEBUG_ERROR("Invalid parameter"); - return tsk_null; - } - - pend = (pdata + size); - if((chunck = trtp_rtcp_sdes_chunck_create_null())){ - trtp_rtcp_sdes_item_t* item; - tsk_bool_t is_last_item = tsk_false; - // SSRC/CSRC - chunck->ssrc = (uint32_t)tnet_ntohl_2(pdata); - pdata += TRTP_RTCP_SDES_CHUNCK_SSRC_OR_CSRC_SIZE; - while((pdata < pend) && !is_last_item){ - if((item = trtp_rtcp_sdes_item_deserialize(pdata, (pend-pdata)))){ - is_last_item = (item->type == trtp_rtcp_sdes_item_type_end); - pdata += trtp_rtcp_sdes_item_get_size(item); - tsk_list_push_back_data(chunck->items, (void**)&item); - } - else{ - TSK_DEBUG_ERROR("Failed to deserialize sdes item"); - break; - } - } - } - else{ - TSK_DEBUG_ERROR("Failed to create new sdes_chunck object"); - return tsk_null; - } - - return chunck; + trtp_rtcp_sdes_chunck_t* chunck = tsk_null; + const uint8_t* pdata = (uint8_t*)data; + const uint8_t* pend; + if(!data || size < TRTP_RTCP_SDES_CHUNCK_MIN_SIZE) { + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_null; + } + + pend = (pdata + size); + if((chunck = trtp_rtcp_sdes_chunck_create_null())) { + trtp_rtcp_sdes_item_t* item; + tsk_bool_t is_last_item = tsk_false; + // SSRC/CSRC + chunck->ssrc = (uint32_t)tnet_ntohl_2(pdata); + pdata += TRTP_RTCP_SDES_CHUNCK_SSRC_OR_CSRC_SIZE; + while((pdata < pend) && !is_last_item) { + if((item = trtp_rtcp_sdes_item_deserialize(pdata, (pend-pdata)))) { + is_last_item = (item->type == trtp_rtcp_sdes_item_type_end); + pdata += trtp_rtcp_sdes_item_get_size(item); + tsk_list_push_back_data(chunck->items, (void**)&item); + } + else { + TSK_DEBUG_ERROR("Failed to deserialize sdes item"); + break; + } + } + } + else { + TSK_DEBUG_ERROR("Failed to create new sdes_chunck object"); + return tsk_null; + } + + return chunck; } int trtp_rtcp_sdes_chunck_serialize_to(const trtp_rtcp_sdes_chunck_t* self, void* data, tsk_size_t size) { - uint8_t* pdata = (uint8_t*)data; - const tsk_list_item_t* item; - const trtp_rtcp_sdes_item_t* sdes_item; - tsk_size_t sdes_item_size; - int ret = 0; - - if(!self || !data || size < trtp_rtcp_sdes_chunck_get_size(self)){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - pdata[0] = self->ssrc >> 24; - pdata[1] = (self->ssrc >> 16) & 0xFF; - pdata[2] = (self->ssrc >> 8) & 0xFF; - pdata[3] = (self->ssrc & 0xFF); - pdata += 4; - - tsk_list_foreach(item, self->items){ - if(!(sdes_item = TRTP_RTCP_SDES_ITEM(item->data))){ - continue; - } - if((ret = trtp_rtcp_sdes_item_serialize_to(sdes_item, pdata, size))){ - TSK_DEBUG_ERROR("SDES item serialization failed"); - goto bail; - } - sdes_item_size = trtp_rtcp_sdes_item_get_size(sdes_item); - pdata += sdes_item_size; size -= sdes_item_size; - } + uint8_t* pdata = (uint8_t*)data; + const tsk_list_item_t* item; + const trtp_rtcp_sdes_item_t* sdes_item; + tsk_size_t sdes_item_size; + int ret = 0; + + if(!self || !data || size < trtp_rtcp_sdes_chunck_get_size(self)) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + pdata[0] = self->ssrc >> 24; + pdata[1] = (self->ssrc >> 16) & 0xFF; + pdata[2] = (self->ssrc >> 8) & 0xFF; + pdata[3] = (self->ssrc & 0xFF); + pdata += 4; + + tsk_list_foreach(item, self->items) { + if(!(sdes_item = TRTP_RTCP_SDES_ITEM(item->data))) { + continue; + } + if((ret = trtp_rtcp_sdes_item_serialize_to(sdes_item, pdata, size))) { + TSK_DEBUG_ERROR("SDES item serialization failed"); + goto bail; + } + sdes_item_size = trtp_rtcp_sdes_item_get_size(sdes_item); + pdata += sdes_item_size; + size -= sdes_item_size; + } bail: - return ret; + return ret; } int trtp_rtcp_sdes_chunck_add_item(trtp_rtcp_sdes_chunck_t* self, trtp_rtcp_sdes_item_type_t type, const void* data, uint8_t length) { - trtp_rtcp_sdes_item_t *item; - if(!self || !self->items){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if((item = trtp_rtcp_sdes_item_create(type, data, length))){ - tsk_list_push_back_data(self->items, (void**)&item); - } - return 0; + trtp_rtcp_sdes_item_t *item; + if(!self || !self->items) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if((item = trtp_rtcp_sdes_item_create(type, data, length))) { + tsk_list_push_back_data(self->items, (void**)&item); + } + return 0; } tsk_size_t trtp_rtcp_sdes_chunck_get_size(const trtp_rtcp_sdes_chunck_t* self) { - const tsk_list_item_t* item; - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return 0; - } - else{ - tsk_size_t size = TRTP_RTCP_SDES_CHUNCK_SSRC_OR_CSRC_SIZE; - tsk_list_foreach(item, self->items){ - size += trtp_rtcp_sdes_item_get_size(TRTP_RTCP_SDES_ITEM(item->data)); - } - if(size & 0x03){//Each chunk starts on a 32-bit boundary - size += (4 - (size & 0x03)); - } - return size; - } + const tsk_list_item_t* item; + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return 0; + } + else { + tsk_size_t size = TRTP_RTCP_SDES_CHUNCK_SSRC_OR_CSRC_SIZE; + tsk_list_foreach(item, self->items) { + size += trtp_rtcp_sdes_item_get_size(TRTP_RTCP_SDES_ITEM(item->data)); + } + if(size & 0x03) { //Each chunk starts on a 32-bit boundary + size += (4 - (size & 0x03)); + } + return size; + } } diff --git a/tinyRTP/src/rtcp/trtp_rtcp_sdes_item.c b/tinyRTP/src/rtcp/trtp_rtcp_sdes_item.c index 7f22537..6d70a46 100755 --- a/tinyRTP/src/rtcp/trtp_rtcp_sdes_item.c +++ b/tinyRTP/src/rtcp/trtp_rtcp_sdes_item.c @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -32,117 +32,118 @@ static tsk_object_t* trtp_rtcp_sdes_item_ctor(tsk_object_t * self, va_list * app) { - trtp_rtcp_sdes_item_t *item = self; - if(item){ - } - return self; + trtp_rtcp_sdes_item_t *item = self; + if(item) { + } + return self; } static tsk_object_t* trtp_rtcp_sdes_item_dtor(tsk_object_t * self) -{ - trtp_rtcp_sdes_item_t *item = self; - if(item){ - TSK_OBJECT_SAFE_FREE(item->data); - } +{ + trtp_rtcp_sdes_item_t *item = self; + if(item) { + TSK_OBJECT_SAFE_FREE(item->data); + } - return self; + return self; } -static const tsk_object_def_t trtp_rtcp_sdes_item_def_s = -{ - sizeof(trtp_rtcp_sdes_item_t), - trtp_rtcp_sdes_item_ctor, - trtp_rtcp_sdes_item_dtor, - tsk_null, +static const tsk_object_def_t trtp_rtcp_sdes_item_def_s = { + sizeof(trtp_rtcp_sdes_item_t), + trtp_rtcp_sdes_item_ctor, + trtp_rtcp_sdes_item_dtor, + tsk_null, }; const tsk_object_def_t *trtp_rtcp_sdes_item_def_t = &trtp_rtcp_sdes_item_def_s; trtp_rtcp_sdes_item_t* _trtp_rtcp_sdes_item_create_null(trtp_rtcp_sdes_item_type_t type) { - return tsk_object_new(trtp_rtcp_sdes_item_def_t); + return tsk_object_new(trtp_rtcp_sdes_item_def_t); } trtp_rtcp_sdes_item_t* trtp_rtcp_sdes_item_create(trtp_rtcp_sdes_item_type_t type, const void* data, uint8_t length) { - trtp_rtcp_sdes_item_t* item; - if(!(item = _trtp_rtcp_sdes_item_create_null(type))){ - TSK_DEBUG_ERROR("Failed to create new SDES item"); - return tsk_null; - } - item->type = type; - if(data && length){ - item->data = tsk_buffer_create(data, length); - } - - return item; + trtp_rtcp_sdes_item_t* item; + if(!(item = _trtp_rtcp_sdes_item_create_null(type))) { + TSK_DEBUG_ERROR("Failed to create new SDES item"); + return tsk_null; + } + item->type = type; + if(data && length) { + item->data = tsk_buffer_create(data, length); + } + + return item; } trtp_rtcp_sdes_item_t* trtp_rtcp_sdes_item_deserialize(const void* data, tsk_size_t size) { - const uint8_t* pdata = (const uint8_t*)data; - - if(!data || !size){ - TSK_DEBUG_ERROR("Invlaid parameter"); - return tsk_null; - } - - if(pdata[0] == trtp_rtcp_sdes_item_type_end){ - return trtp_rtcp_sdes_item_create(trtp_rtcp_sdes_item_type_end, tsk_null, 0); - } - - if(size < TRTP_RTCP_SDES_ITEM_MIN_SIZE || size < (tsk_size_t)(pdata[1] + 2)){ - TSK_DEBUG_ERROR("Too short"); - return tsk_null; - } - - return trtp_rtcp_sdes_item_create((trtp_rtcp_sdes_item_type_t)pdata[0], &pdata[2], pdata[1]); + const uint8_t* pdata = (const uint8_t*)data; + + if(!data || !size) { + TSK_DEBUG_ERROR("Invlaid parameter"); + return tsk_null; + } + + if(pdata[0] == trtp_rtcp_sdes_item_type_end) { + return trtp_rtcp_sdes_item_create(trtp_rtcp_sdes_item_type_end, tsk_null, 0); + } + + if(size < TRTP_RTCP_SDES_ITEM_MIN_SIZE || size < (tsk_size_t)(pdata[1] + 2)) { + TSK_DEBUG_ERROR("Too short"); + return tsk_null; + } + + return trtp_rtcp_sdes_item_create((trtp_rtcp_sdes_item_type_t)pdata[0], &pdata[2], pdata[1]); } tsk_buffer_t* trtp_rtcp_sdes_item_serialize(const trtp_rtcp_sdes_item_t* self) { - tsk_buffer_t*buffer = tsk_null; - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return tsk_null; - } - if((buffer = tsk_buffer_create(tsk_null, trtp_rtcp_sdes_item_get_size(self)))){ - if(trtp_rtcp_sdes_item_serialize_to(self, buffer->data, buffer->size) != 0){ - TSK_OBJECT_SAFE_FREE(buffer); - } - } - return buffer; + tsk_buffer_t*buffer = tsk_null; + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_null; + } + if((buffer = tsk_buffer_create(tsk_null, trtp_rtcp_sdes_item_get_size(self)))) { + if(trtp_rtcp_sdes_item_serialize_to(self, buffer->data, buffer->size) != 0) { + TSK_OBJECT_SAFE_FREE(buffer); + } + } + return buffer; } int trtp_rtcp_sdes_item_serialize_to(const trtp_rtcp_sdes_item_t* self, void* data, tsk_size_t size) { - if(!self || !data || (size < trtp_rtcp_sdes_item_get_size(self))){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if(self->type == trtp_rtcp_sdes_item_type_end){ - ((uint8_t*)data)[0] = trtp_rtcp_sdes_item_type_end; - } - else{ - ((uint8_t*)data)[0] = self->type; - if(self->data){ - ((uint8_t*)data)[1] = (uint8_t)self->data->size; - memcpy(&((uint8_t*)data)[2], self->data->data, self->data->size); - } - else{ - ((uint8_t*)data)[1] = 0; - } - } - return 0; + if(!self || !data || (size < trtp_rtcp_sdes_item_get_size(self))) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if(self->type == trtp_rtcp_sdes_item_type_end) { + ((uint8_t*)data)[0] = trtp_rtcp_sdes_item_type_end; + } + else { + ((uint8_t*)data)[0] = self->type; + if(self->data) { + ((uint8_t*)data)[1] = (uint8_t)self->data->size; + memcpy(&((uint8_t*)data)[2], self->data->data, self->data->size); + } + else { + ((uint8_t*)data)[1] = 0; + } + } + return 0; } tsk_size_t trtp_rtcp_sdes_item_get_size(const trtp_rtcp_sdes_item_t* self) { - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return 0; - } - switch(self->type){ - case trtp_rtcp_sdes_item_type_end: return 1; - default: return 2 + (self->data ? self->data->size : 0); - } + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return 0; + } + switch(self->type) { + case trtp_rtcp_sdes_item_type_end: + return 1; + default: + return 2 + (self->data ? self->data->size : 0); + } } diff --git a/tinyRTP/src/rtcp/trtp_rtcp_session.c b/tinyRTP/src/rtcp/trtp_rtcp_session.c index b2f4733..226b0cd 100755 --- a/tinyRTP/src/rtcp/trtp_rtcp_session.c +++ b/tinyRTP/src/rtcp/trtp_rtcp_session.c @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -56,8 +56,14 @@ #include /* INT_MAX */ #ifdef _MSC_VER -static double drand48() { return (((double)rand()) / RAND_MAX); } -static void srand48(long sv) { srand((unsigned int) sv); } +static double drand48() +{ + return (((double)rand()) / RAND_MAX); +} +static void srand48(long sv) +{ + srand((unsigned int) sv); +} #endif #define RTCP_BW (160 * 50) // FIXME: default bandwidth (octet/second) @@ -70,19 +76,17 @@ static void srand48(long sv) { srand((unsigned int) sv); } typedef double time_tp; typedef void* packet_; -typedef enum event_ -{ - EVENT_BYE, - EVENT_REPORT, - EVENT_RTP +typedef enum event_ { + EVENT_BYE, + EVENT_REPORT, + EVENT_RTP } event_; -typedef enum PacketType_ -{ - PACKET_RTCP_REPORT, - PACKET_BYE, - PACKET_RTP, +typedef enum PacketType_ { + PACKET_RTCP_REPORT, + PACKET_BYE, + PACKET_RTP, } PacketType_; @@ -90,53 +94,51 @@ PacketType_; #define TRTP_RTCP_SOURCE(self) ((trtp_rtcp_source_t*)self) -typedef struct trtp_rtcp_source_s -{ - TSK_DECLARE_OBJECT; - - uint32_t ssrc; /* source's ssrc */ - uint16_t max_seq; /* highest seq. number seen */ - uint32_t cycles; /* shifted count of seq. number cycles */ - uint32_t base_seq; /* base seq number */ - uint32_t bad_seq; /* last 'bad' seq number + 1 */ - uint32_t probation; /* sequ. packets till source is valid */ - uint32_t received; /* packets received */ - uint32_t expected_prior; /* packet expected at last interval */ - uint32_t received_prior; /* packet received at last interval */ - uint32_t transit; /* relative trans time for prev pkt */ - double jitter; /* estimated jitter */ - - uint32_t base_ts; /* base timestamp */ - uint32_t max_ts; /* highest timestamp number seen */ - uint32_t rate; /* codec sampling rate */ - - uint32_t ntp_msw; /* last received NTP timestamp from RTCP sender */ - uint32_t ntp_lsw; /* last received NTP timestamp from RTCP sender */ - uint64_t dlsr; /* delay since last SR */ +typedef struct trtp_rtcp_source_s { + TSK_DECLARE_OBJECT; + + uint32_t ssrc; /* source's ssrc */ + uint16_t max_seq; /* highest seq. number seen */ + uint32_t cycles; /* shifted count of seq. number cycles */ + uint32_t base_seq; /* base seq number */ + uint32_t bad_seq; /* last 'bad' seq number + 1 */ + uint32_t probation; /* sequ. packets till source is valid */ + uint32_t received; /* packets received */ + uint32_t expected_prior; /* packet expected at last interval */ + uint32_t received_prior; /* packet received at last interval */ + uint32_t transit; /* relative trans time for prev pkt */ + double jitter; /* estimated jitter */ + + uint32_t base_ts; /* base timestamp */ + uint32_t max_ts; /* highest timestamp number seen */ + uint32_t rate; /* codec sampling rate */ + + uint32_t ntp_msw; /* last received NTP timestamp from RTCP sender */ + uint32_t ntp_lsw; /* last received NTP timestamp from RTCP sender */ + uint64_t dlsr; /* delay since last SR */ } trtp_rtcp_source_t; typedef tsk_list_t trtp_rtcp_sources_L_t; /**< List of @ref trtp_rtcp_header_t elements */ static tsk_object_t* trtp_rtcp_source_ctor(tsk_object_t * self, va_list * app) { - trtp_rtcp_source_t *source = self; - if(source){ - } - return self; + trtp_rtcp_source_t *source = self; + if(source) { + } + return self; } static tsk_object_t* trtp_rtcp_source_dtor(tsk_object_t * self) -{ - trtp_rtcp_source_t *source = self; - if(source){ - } - return self; -} -static const tsk_object_def_t trtp_rtcp_source_def_s = { - sizeof(trtp_rtcp_source_t), - trtp_rtcp_source_ctor, - trtp_rtcp_source_dtor, - tsk_null, + trtp_rtcp_source_t *source = self; + if(source) { + } + return self; +} +static const tsk_object_def_t trtp_rtcp_source_def_s = { + sizeof(trtp_rtcp_source_t), + trtp_rtcp_source_ctor, + trtp_rtcp_source_dtor, + tsk_null, }; const tsk_object_def_t *trtp_rtcp_source_def_t = &trtp_rtcp_source_def_s; @@ -145,113 +147,117 @@ static tsk_bool_t _trtp_rtcp_source_update_seq(trtp_rtcp_source_t* self, uint16_ static int __pred_find_source_by_ssrc(const tsk_list_item_t *item, const void *pssrc) { - if(item && item->data){ - trtp_rtcp_source_t *source = item->data; - return source->ssrc - *((uint32_t*)pssrc); - } - return -1; + if(item && item->data) { + trtp_rtcp_source_t *source = item->data; + return source->ssrc - *((uint32_t*)pssrc); + } + return -1; } static trtp_rtcp_source_t* _trtp_rtcp_source_create(uint32_t ssrc, uint16_t seq, uint32_t ts) { - trtp_rtcp_source_t* source; - if(!(source = tsk_object_new(trtp_rtcp_source_def_t))){ - TSK_DEBUG_ERROR("Failed to create source object"); - return tsk_null; - } - - _trtp_rtcp_source_init_seq(source, seq, ts); - source->ssrc = ssrc; - source->max_seq = seq - 1; - source->probation = MIN_SEQUENTIAL; - source->rate = CODEC_RATE;//FIXME - - return source; + trtp_rtcp_source_t* source; + if(!(source = tsk_object_new(trtp_rtcp_source_def_t))) { + TSK_DEBUG_ERROR("Failed to create source object"); + return tsk_null; + } + + _trtp_rtcp_source_init_seq(source, seq, ts); + source->ssrc = ssrc; + source->max_seq = seq - 1; + source->probation = MIN_SEQUENTIAL; + source->rate = CODEC_RATE;//FIXME + + return source; } static int _trtp_rtcp_source_init_seq(trtp_rtcp_source_t* self, uint16_t seq, uint32_t ts) { - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - self->base_seq = seq; - self->max_seq = seq; - self->bad_seq = RTP_SEQ_MOD + 1; /* so seq == bad_seq is false */ - self->cycles = 0; - self->received = 0; - self->received_prior = 0; - self->expected_prior = 0; - self->base_ts = ts; - self->max_ts = ts; - return 0; + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + self->base_seq = seq; + self->max_seq = seq; + self->bad_seq = RTP_SEQ_MOD + 1; /* so seq == bad_seq is false */ + self->cycles = 0; + self->received = 0; + self->received_prior = 0; + self->expected_prior = 0; + self->base_ts = ts; + self->max_ts = ts; + return 0; } static tsk_bool_t _trtp_rtcp_source_update_seq(trtp_rtcp_source_t* self, uint16_t seq, uint32_t ts) { - uint16_t udelta; - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return tsk_false; - } - - udelta = seq - self->max_seq; - - /* - * Source is not valid until MIN_SEQUENTIAL packets with - * sequential sequence numbers have been received. - */ - if (self->probation) { - /* packet is in sequence */ - if (seq == self->max_seq + 1) { - self->probation--; - self->max_seq = seq; - self->max_ts = ts; - if (self->probation == 0) { - _trtp_rtcp_source_init_seq(self, seq, ts); - self->received++; - return tsk_true; - } - } else { - self->probation = MIN_SEQUENTIAL - 1; - self->max_seq = seq; - self->max_ts = ts; - } - return tsk_false; - } else if (udelta < MAX_DROPOUT) { - /* in order, with permissible gap */ - if (seq < self->max_seq) { - /* - * Sequence number wrapped - count another 64K cycle. - */ - self->cycles += RTP_SEQ_MOD; - } - self->max_seq = seq; - self->max_ts = ts; - } else if (udelta <= RTP_SEQ_MOD - MAX_MISORDER) { - /* the sequence number made a very large jump */ - if (seq == self->bad_seq) { - /* - * Two sequential packets -- assume that the other side - * restarted without telling us so just re-sync - * (i.e., pretend this was the first packet). - */ - _trtp_rtcp_source_init_seq(self, seq, ts); - } - else { - self->bad_seq = (seq + 1) & (RTP_SEQ_MOD-1); - return tsk_false; - } - } else { - /* duplicate or reordered packet */ - } - self->received++; - return tsk_true; + uint16_t udelta; + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_false; + } + + udelta = seq - self->max_seq; + + /* + * Source is not valid until MIN_SEQUENTIAL packets with + * sequential sequence numbers have been received. + */ + if (self->probation) { + /* packet is in sequence */ + if (seq == self->max_seq + 1) { + self->probation--; + self->max_seq = seq; + self->max_ts = ts; + if (self->probation == 0) { + _trtp_rtcp_source_init_seq(self, seq, ts); + self->received++; + return tsk_true; + } + } + else { + self->probation = MIN_SEQUENTIAL - 1; + self->max_seq = seq; + self->max_ts = ts; + } + return tsk_false; + } + else if (udelta < MAX_DROPOUT) { + /* in order, with permissible gap */ + if (seq < self->max_seq) { + /* + * Sequence number wrapped - count another 64K cycle. + */ + self->cycles += RTP_SEQ_MOD; + } + self->max_seq = seq; + self->max_ts = ts; + } + else if (udelta <= RTP_SEQ_MOD - MAX_MISORDER) { + /* the sequence number made a very large jump */ + if (seq == self->bad_seq) { + /* + * Two sequential packets -- assume that the other side + * restarted without telling us so just re-sync + * (i.e., pretend this was the first packet). + */ + _trtp_rtcp_source_init_seq(self, seq, ts); + } + else { + self->bad_seq = (seq + 1) & (RTP_SEQ_MOD-1); + return tsk_false; + } + } + else { + /* duplicate or reordered packet */ + } + self->received++; + return tsk_true; } static tsk_bool_t _trtp_rtcp_source_is_probed(const trtp_rtcp_source_t* self) { - return (self && self->probation == 0); + return (self && self->probation == 0); } @@ -261,118 +267,120 @@ static tsk_bool_t _trtp_rtcp_source_is_probed(const trtp_rtcp_source_t* self) typedef time_tp (*tc_f)(); -static time_tp _trtp_rtcp_session_tc() { return (time_tp)tsk_time_now(); } - -typedef struct trtp_rtcp_session_s +static time_tp _trtp_rtcp_session_tc() { - TSK_DECLARE_OBJECT; - - tsk_bool_t is_started; - tnet_fd_t local_fd; + return (time_tp)tsk_time_now(); +} + +typedef struct trtp_rtcp_session_s { + TSK_DECLARE_OBJECT; + + tsk_bool_t is_started; + tnet_fd_t local_fd; struct tnet_transport_s* transport; // not starter -> do not stop - const struct sockaddr * remote_addr; - struct tnet_ice_ctx_s* ice_ctx; // not starter -> do not stop - tsk_bool_t is_ice_turn_active; - - const void* callback_data; - trtp_rtcp_cb_f callback; - - int32_t app_bw_max_upload; // application specific (kbps) - int32_t app_bw_max_download; // application specific (kbps) - - struct{ - tsk_timer_manager_handle_t* handle_global; - tsk_timer_id_t id_report; - tsk_timer_id_t id_bye; - } timer; - - trtp_rtcp_source_t* source_local; /**< local source */ - trtp_rtcp_report_sdes_t* sdes; - uint64_t time_start; /**< Start time in millis (NOT in NTP unit yet) */ - - // - uint8_t fir_seqnr; - // - - // - char* cname; - uint32_t packets_count; - uint32_t octets_count; - // - - // - time_tp tp; /**< the last time an RTCP packet was transmitted; */ - tc_f tc; /**< the current time */ - time_tp tn; /**< the next scheduled transmission time of an RTCP packet */ - int32_t pmembers; /**< the estimated number of session members at the time tn was last recomputed */ - int32_t members; /**< the most current estimate for the number of session members */ - int32_t senders; /**< the most current estimate for the number of senders in the session */ - double rtcp_bw; /**< The target RTCP bandwidth, i.e., the total bandwidth + const struct sockaddr * remote_addr; + struct tnet_ice_ctx_s* ice_ctx; // not starter -> do not stop + tsk_bool_t is_ice_turn_active; + + const void* callback_data; + trtp_rtcp_cb_f callback; + + int32_t app_bw_max_upload; // application specific (kbps) + int32_t app_bw_max_download; // application specific (kbps) + float app_jcng_q; // application specific for jitter buffer congestion estimation (quality in [0, 1]) + + struct { + tsk_timer_manager_handle_t* handle_global; + tsk_timer_id_t id_report; + tsk_timer_id_t id_bye; + } timer; + + trtp_rtcp_source_t* source_local; /**< local source */ + trtp_rtcp_report_sdes_t* sdes; + uint64_t time_start; /**< Start time in millis (NOT in NTP unit yet) */ + + // + uint8_t fir_seqnr; + // + + // + char* cname; + uint32_t packets_count; + uint32_t octets_count; + // + + // + time_tp tp; /**< the last time an RTCP packet was transmitted; */ + tc_f tc; /**< the current time */ + time_tp tn; /**< the next scheduled transmission time of an RTCP packet */ + int32_t pmembers; /**< the estimated number of session members at the time tn was last recomputed */ + int32_t members; /**< the most current estimate for the number of session members */ + int32_t senders; /**< the most current estimate for the number of senders in the session */ + double rtcp_bw; /**< The target RTCP bandwidth, i.e., the total bandwidth that will be used for RTCP packets by all members of this session, in octets per second. This will be a specified fraction of the "session bandwidth" parameter supplied to the application at startup*/ - tsk_bool_t we_sent; /**< Flag that is true if the application has sent data since the 2nd previous RTCP report was transmitted */ - double avg_rtcp_size; /**< The average compound RTCP packet size, in octets, + tsk_bool_t we_sent; /**< Flag that is true if the application has sent data since the 2nd previous RTCP report was transmitted */ + double avg_rtcp_size; /**< The average compound RTCP packet size, in octets, over all RTCP packets sent and received by this participant. The size includes lower-layer transport and network protocol headers (e.g., UDP and IP) as explained in Section 6.2*/ - tsk_bool_t initial; /**< Flag that is true if the application has not yet sent an RTCP packet */ - // + tsk_bool_t initial; /**< Flag that is true if the application has not yet sent an RTCP packet */ + // - trtp_rtcp_sources_L_t *sources; + trtp_rtcp_sources_L_t *sources; - TSK_DECLARE_SAFEOBJ; + TSK_DECLARE_SAFEOBJ; #if HAVE_SRTP - struct{ - const srtp_t* session; - } srtp; + struct { + const srtp_t* session; + } srtp; #endif } trtp_rtcp_session_t; static tsk_object_t* trtp_rtcp_session_ctor(tsk_object_t * self, va_list * app) { - trtp_rtcp_session_t *session = self; - if(session){ - session->app_bw_max_upload = INT_MAX; // INT_MAX or <=0 means undefined - session->app_bw_max_download = INT_MAX; // INT_MAX or <=0 means undefined - session->sources = tsk_list_create(); - session->timer.id_report = TSK_INVALID_TIMER_ID; - session->timer.id_bye = TSK_INVALID_TIMER_ID; - session->tc = _trtp_rtcp_session_tc; - // get a handle for the global timer manager - session->timer.handle_global = tsk_timer_mgr_global_ref(); - tsk_safeobj_init(session); - } - return self; + trtp_rtcp_session_t *session = self; + if(session) { + session->app_bw_max_upload = INT_MAX; // INT_MAX or <=0 means undefined + session->app_bw_max_download = INT_MAX; // INT_MAX or <=0 means undefined + session->sources = tsk_list_create(); + session->timer.id_report = TSK_INVALID_TIMER_ID; + session->timer.id_bye = TSK_INVALID_TIMER_ID; + session->tc = _trtp_rtcp_session_tc; + // get a handle for the global timer manager + session->timer.handle_global = tsk_timer_mgr_global_ref(); + tsk_safeobj_init(session); + } + return self; } static tsk_object_t* trtp_rtcp_session_dtor(tsk_object_t * self) -{ - trtp_rtcp_session_t *session = self; - if(session){ - trtp_rtcp_session_stop(session); - - TSK_OBJECT_SAFE_FREE(session->sources); - TSK_OBJECT_SAFE_FREE(session->source_local); - TSK_OBJECT_SAFE_FREE(session->sdes); - TSK_OBJECT_SAFE_FREE(session->ice_ctx); // not starter -> do not stop - TSK_FREE(session->cname); +{ + trtp_rtcp_session_t *session = self; + if(session) { + trtp_rtcp_session_stop(session); + + TSK_OBJECT_SAFE_FREE(session->sources); + TSK_OBJECT_SAFE_FREE(session->source_local); + TSK_OBJECT_SAFE_FREE(session->sdes); + TSK_OBJECT_SAFE_FREE(session->ice_ctx); // not starter -> do not stop + TSK_FREE(session->cname); TSK_OBJECT_SAFE_FREE(session->transport); // not starter -> do not stop - // release the handle for the global timer manager - tsk_timer_mgr_global_unref(&session->timer.handle_global); + // release the handle for the global timer manager + tsk_timer_mgr_global_unref(&session->timer.handle_global); - tsk_safeobj_deinit(session); - } - return self; + tsk_safeobj_deinit(session); + } + return self; } -static const tsk_object_def_t trtp_rtcp_session_def_s = -{ - sizeof(trtp_rtcp_session_t), - trtp_rtcp_session_ctor, - trtp_rtcp_session_dtor, - tsk_null, +static const tsk_object_def_t trtp_rtcp_session_def_s = { + sizeof(trtp_rtcp_session_t), + trtp_rtcp_session_ctor, + trtp_rtcp_session_dtor, + tsk_null, }; const tsk_object_def_t *trtp_rtcp_session_def_t = &trtp_rtcp_session_def_s; @@ -394,378 +402,394 @@ static void SendBYEPacket(trtp_rtcp_session_t* session, event_ e); trtp_rtcp_session_t* trtp_rtcp_session_create(uint32_t ssrc, const char* cname) { - trtp_rtcp_session_t* session; - - if(!(session = tsk_object_new(trtp_rtcp_session_def_t))){ - TSK_DEBUG_ERROR("Failed to create new session object"); - return tsk_null; - } - - // RFC 3550 - 6.3.2 Initialization - if(!(session->source_local = _trtp_rtcp_source_create(ssrc, 0, 0))){ - TSK_DEBUG_ERROR("Failed to create new local source"); - TSK_OBJECT_SAFE_FREE(session); - goto bail; - } - _trtp_rtcp_session_add_source(session, session->source_local); - session->initial = tsk_true; - session->we_sent = tsk_false; - session->senders = 1; - session->members = 1; - session->rtcp_bw = RTCP_BW;//FIXME: as parameter from the code, Also added possiblities to update this value - session->cname = tsk_strdup(cname); - + trtp_rtcp_session_t* session; + + if(!(session = tsk_object_new(trtp_rtcp_session_def_t))) { + TSK_DEBUG_ERROR("Failed to create new session object"); + return tsk_null; + } + + // RFC 3550 - 6.3.2 Initialization + if(!(session->source_local = _trtp_rtcp_source_create(ssrc, 0, 0))) { + TSK_DEBUG_ERROR("Failed to create new local source"); + TSK_OBJECT_SAFE_FREE(session); + goto bail; + } + _trtp_rtcp_session_add_source(session, session->source_local); + session->initial = tsk_true; + session->we_sent = tsk_false; + session->senders = 1; + session->members = 1; + session->rtcp_bw = RTCP_BW;//FIXME: as parameter from the code, Also added possiblities to update this value + session->cname = tsk_strdup(cname); + bail: - return session; + return session; } struct trtp_rtcp_session_s* trtp_rtcp_session_create_2(struct tnet_ice_ctx_s* ice_ctx, uint32_t ssrc, const char* cname) { - struct trtp_rtcp_session_s* session = trtp_rtcp_session_create(ssrc, cname); - if (session) { - if ((session->ice_ctx = tsk_object_ref(ice_ctx))) { - session->is_ice_turn_active = tnet_ice_ctx_is_turn_rtcp_active(session->ice_ctx); - } - } - return session; + struct trtp_rtcp_session_s* session = trtp_rtcp_session_create(ssrc, cname); + if (session) { + if ((session->ice_ctx = tsk_object_ref(ice_ctx))) { + session->is_ice_turn_active = tnet_ice_ctx_is_turn_rtcp_active(session->ice_ctx); + } + } + return session; } int trtp_rtcp_session_set_callback(trtp_rtcp_session_t* self, trtp_rtcp_cb_f callback, const void* callback_data) { - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - tsk_safeobj_lock(self); - self->callback = callback; - self->callback_data = callback_data; - tsk_safeobj_unlock(self); - return 0; + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + tsk_safeobj_lock(self); + self->callback = callback; + self->callback_data = callback_data; + tsk_safeobj_unlock(self); + return 0; } #if HAVE_SRTP int trtp_rtcp_session_set_srtp_sess(trtp_rtcp_session_t* self, const srtp_t* session) { - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - tsk_safeobj_lock(self); - self->srtp.session = session; - tsk_safeobj_unlock(self); + tsk_safeobj_lock(self); + self->srtp.session = session; + tsk_safeobj_unlock(self); - return 0; + return 0; } #endif -int trtp_rtcp_session_set_app_bandwidth_max(trtp_rtcp_session_t* self, int32_t bw_upload_kbps, int32_t bw_download_kbps) +int trtp_rtcp_session_set_app_bw_and_jcng(trtp_rtcp_session_t* self, int32_t bw_upload_kbps, int32_t bw_download_kbps, float jcng_q) { - trtp_rtcp_report_rr_t* rr; - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - tsk_safeobj_lock(self); - - self->app_bw_max_upload = bw_upload_kbps; - self->app_bw_max_download = bw_download_kbps; - - if(self->is_started && self->source_local && self->app_bw_max_download > 0 && self->app_bw_max_download != INT_MAX){ // INT_MAX or <=0 means undefined - tsk_list_item_t* item; - uint32_t media_ssrc_list[256] = {0}; - uint32_t media_ssrc_list_count = 0; - // retrieve sources as array - tsk_list_foreach(item, self->sources){ - if(!item->data){ - continue; - } - if((media_ssrc_list_count + 1) < sizeof(media_ssrc_list)/sizeof(media_ssrc_list[0])){ - media_ssrc_list[media_ssrc_list_count++] = TRTP_RTCP_SOURCE(item->data)->ssrc; - } - } - // create RTCP-RR packet and send it over the network - if(media_ssrc_list_count > 0 && (rr = trtp_rtcp_report_rr_create_2(self->source_local->ssrc))){ - // app_bw_max_download unit is kbps while create_afb_remb() expect bps - trtp_rtcp_report_psfb_t* psfb_afb_remb = trtp_rtcp_report_psfb_create_afb_remb(self->source_local->ssrc/*sender SSRC*/, media_ssrc_list, media_ssrc_list_count, (self->app_bw_max_download * 1024)); - if(psfb_afb_remb){ - TSK_DEBUG_INFO("Packing RTCP-AFB-REMB (bw_dwn=%d kbps) for outgoing RTCP-RR", self->app_bw_max_download); - if(trtp_rtcp_packet_add_packet((trtp_rtcp_packet_t*)rr, (trtp_rtcp_packet_t*)psfb_afb_remb, tsk_false) == 0){ - _trtp_rtcp_session_send_pkt(self, (trtp_rtcp_packet_t*)rr); - } - TSK_OBJECT_SAFE_FREE(psfb_afb_remb); - } - TSK_OBJECT_SAFE_FREE(rr); - } - } - - tsk_safeobj_unlock(self); - - return 0; + trtp_rtcp_report_rr_t* rr; + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + tsk_safeobj_lock(self); + + self->app_bw_max_upload = bw_upload_kbps; + self->app_bw_max_download = bw_download_kbps; + self->app_jcng_q = jcng_q; + + if(self->is_started && self->source_local) { // INT_MAX or <=0 means undefined + tsk_list_item_t* item; + uint32_t media_ssrc_list[256] = {0}; + uint32_t media_ssrc_list_count = 0; + // retrieve sources as array + tsk_list_foreach(item, self->sources) { + if(!item->data) { + continue; + } + if((media_ssrc_list_count + 1) < sizeof(media_ssrc_list)/sizeof(media_ssrc_list[0])) { + media_ssrc_list[media_ssrc_list_count++] = TRTP_RTCP_SOURCE(item->data)->ssrc; + } + } + // create RTCP-RR packet and send it over the network + if (media_ssrc_list_count > 0 && (rr = trtp_rtcp_report_rr_create_2(self->source_local->ssrc))) { + // RTCP-REMB + if (self->app_bw_max_download > 0 && self->app_bw_max_download != INT_MAX) { + // app_bw_max_download unit is kbps while create_afb_remb() expect bps + trtp_rtcp_report_psfb_t* psfb_afb_remb = trtp_rtcp_report_psfb_create_afb_remb(self->source_local->ssrc/*sender SSRC*/, media_ssrc_list, media_ssrc_list_count, (self->app_bw_max_download << 10)); + if (psfb_afb_remb) { + TSK_DEBUG_INFO("Packing RTCP-AFB-REMB (bw_dwn=%d kbps) for outgoing RTCP-RR", self->app_bw_max_download); + trtp_rtcp_packet_add_packet((trtp_rtcp_packet_t*)rr, (trtp_rtcp_packet_t*)psfb_afb_remb, tsk_false); + TSK_OBJECT_SAFE_FREE(psfb_afb_remb); + } + } + // RTCP-JCNG + if (self->app_jcng_q > 0.f && self->app_jcng_q <= 1.f) { + // app_bw_max_download unit is kbps while create_afb_remb() expect bps + trtp_rtcp_report_psfb_t* psfb_afb_jcng = trtp_rtcp_report_psfb_create_afb_jcng(self->source_local->ssrc/*sender SSRC*/, media_ssrc_list, media_ssrc_list_count, self->app_jcng_q); + if (psfb_afb_jcng) { + TSK_DEBUG_INFO("Packing RTCP-AFB-JCNG (q=%f) for outgoing RTCP-RR", self->app_jcng_q); + trtp_rtcp_packet_add_packet((trtp_rtcp_packet_t*)rr, (trtp_rtcp_packet_t*)psfb_afb_jcng, tsk_false); + TSK_OBJECT_SAFE_FREE(psfb_afb_jcng); + } + } + // send the RR message + _trtp_rtcp_session_send_pkt(self, (trtp_rtcp_packet_t*)rr); + TSK_OBJECT_SAFE_FREE(rr); + } + } + + tsk_safeobj_unlock(self); + + return 0; } int trtp_rtcp_session_start(trtp_rtcp_session_t* self, tnet_fd_t local_fd, const struct sockaddr * remote_addr) { - int ret; - - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if(self->is_started){ - TSK_DEBUG_WARN("Already started"); - return 0; - } - - // start global timer manager - if((ret = tsk_timer_manager_start(self->timer.handle_global))){ - TSK_DEBUG_ERROR("Failed to start timer"); - return ret; - } - - self->local_fd = local_fd; - self->remote_addr = remote_addr; - - // Send Initial RR (mandatory) - Schedule(self, 0., EVENT_REPORT); - - // set start time - self->time_start = tsk_time_now(); - - self->is_started = tsk_true; - - return ret; + int ret; + + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if(self->is_started) { + TSK_DEBUG_WARN("Already started"); + return 0; + } + + // start global timer manager + if((ret = tsk_timer_manager_start(self->timer.handle_global))) { + TSK_DEBUG_ERROR("Failed to start timer"); + return ret; + } + + self->local_fd = local_fd; + self->remote_addr = remote_addr; + + // Send Initial RR (mandatory) + Schedule(self, 0., EVENT_REPORT); + + // set start time + self->time_start = tsk_time_now(); + + self->is_started = tsk_true; + + return ret; } int trtp_rtcp_session_stop(trtp_rtcp_session_t* self) { - int ret = 0; - - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - if(self->is_started){ - // send BYE synchronous way - SendBYEPacket(self, EVENT_REPORT); - - // this is a global timer shared by many components -> stopping it won't remove - // all scheduled items as it could continue running if still used - tsk_safeobj_lock(self); // must - if(TSK_TIMER_ID_IS_VALID(self->timer.id_bye)){ - tsk_timer_manager_cancel(self->timer.handle_global, self->timer.id_bye); - self->timer.id_bye = TSK_INVALID_TIMER_ID; - } - if(TSK_TIMER_ID_IS_VALID(self->timer.id_report)){ - tsk_timer_manager_cancel(self->timer.handle_global, self->timer.id_report); - self->timer.id_report = TSK_INVALID_TIMER_ID; - } - tsk_safeobj_unlock(self); - self->is_started = tsk_false; - } - - return ret; + int ret = 0; + + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + if(self->is_started) { + // send BYE synchronous way + SendBYEPacket(self, EVENT_REPORT); + + // this is a global timer shared by many components -> stopping it won't remove + // all scheduled items as it could continue running if still used + tsk_safeobj_lock(self); // must + if(TSK_TIMER_ID_IS_VALID(self->timer.id_bye)) { + tsk_timer_manager_cancel(self->timer.handle_global, self->timer.id_bye); + self->timer.id_bye = TSK_INVALID_TIMER_ID; + } + if(TSK_TIMER_ID_IS_VALID(self->timer.id_report)) { + tsk_timer_manager_cancel(self->timer.handle_global, self->timer.id_report); + self->timer.id_report = TSK_INVALID_TIMER_ID; + } + tsk_safeobj_unlock(self); + self->is_started = tsk_false; + } + + return ret; } int trtp_rtcp_session_process_rtp_out(trtp_rtcp_session_t* self, const trtp_rtp_packet_t* packet_rtp, tsk_size_t size) { - int ret = 0; - - if(!self || !packet_rtp || !packet_rtp->header){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - if(!self->is_started){ - TSK_DEBUG_ERROR("Not started"); - return -2; - } - - tsk_safeobj_lock(self); - - // create local source if not already done - // first destroy it if the ssrc don't match - if(self->source_local && self->source_local->ssrc != packet_rtp->header->ssrc){ - tsk_bool_t removed = tsk_false; - // local ssrc has changed: sould never happen ...but who know? - // remove the source - TSK_DEBUG_WARN("Not expected to be called"); - _trtp_rtcp_session_remove_source(self, self->source_local->ssrc, &removed); - TSK_OBJECT_SAFE_FREE(self->source_local); - TSK_OBJECT_SAFE_FREE(self->sdes); - self->packets_count = 0; - self->octets_count = 0; - if(removed){ - --self->senders; - --self->members; - } - } - if(!self->source_local){ - if(!(self->source_local = _trtp_rtcp_source_create(packet_rtp->header->ssrc, packet_rtp->header->seq_num, packet_rtp->header->timestamp))){ - TSK_DEBUG_ERROR("Failed to create new local source"); - } - // add the source (refresh the number of senders, ...) - _trtp_rtcp_session_add_source(self, self->source_local); - // 'members' and 'senders' were already initialized in the constructor - } - - if(!self->we_sent){ - self->we_sent = tsk_true; - } - - ++self->packets_count; - self->octets_count += (uint32_t)size; - - tsk_safeobj_unlock(self); - - return ret; + int ret = 0; + + if(!self || !packet_rtp || !packet_rtp->header) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + if(!self->is_started) { + TSK_DEBUG_ERROR("Not started"); + return -2; + } + + tsk_safeobj_lock(self); + + // create local source if not already done + // first destroy it if the ssrc don't match + if(self->source_local && self->source_local->ssrc != packet_rtp->header->ssrc) { + tsk_bool_t removed = tsk_false; + // local ssrc has changed: sould never happen ...but who know? + // remove the source + TSK_DEBUG_WARN("Not expected to be called"); + _trtp_rtcp_session_remove_source(self, self->source_local->ssrc, &removed); + TSK_OBJECT_SAFE_FREE(self->source_local); + TSK_OBJECT_SAFE_FREE(self->sdes); + self->packets_count = 0; + self->octets_count = 0; + if(removed) { + --self->senders; + --self->members; + } + } + if(!self->source_local) { + if(!(self->source_local = _trtp_rtcp_source_create(packet_rtp->header->ssrc, packet_rtp->header->seq_num, packet_rtp->header->timestamp))) { + TSK_DEBUG_ERROR("Failed to create new local source"); + } + // add the source (refresh the number of senders, ...) + _trtp_rtcp_session_add_source(self, self->source_local); + // 'members' and 'senders' were already initialized in the constructor + } + + if(!self->we_sent) { + self->we_sent = tsk_true; + } + + ++self->packets_count; + self->octets_count += (uint32_t)size; + + tsk_safeobj_unlock(self); + + return ret; } int trtp_rtcp_session_process_rtp_in(trtp_rtcp_session_t* self, const trtp_rtp_packet_t* packet_rtp, tsk_size_t size) { - int ret = 0; - trtp_rtcp_source_t* source; - - if(!self || !packet_rtp || !packet_rtp->header){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - if(!self->is_started){ - TSK_DEBUG_INFO("RTCP session not started"); - return -2; - } - - tsk_safeobj_lock(self); - OnReceive(self, (const packet_)packet_rtp, EVENT_RTP, size); - if((source = _trtp_rtcp_session_find_source(self, packet_rtp->header->ssrc))){ - if(_trtp_rtcp_source_update_seq(source, packet_rtp->header->seq_num, packet_rtp->header->timestamp)){ - // RFC 3550 A.8 Estimating the Interarrival Jitter - /* uint32_t expected = (source->cycles + source->max_seq) - source->base_seq + 1; */ - double arrival = (((double)(source->max_ts - source->base_ts) / (double)source->rate) * 1000); - int32_t transit = (int32_t)arrival - packet_rtp->header->timestamp; - int32_t d = (transit - source->transit); - if(d < 0) d = -d; - source->transit = transit; - source->jitter += (1./16.) * ((double)d - source->jitter); - } - TSK_OBJECT_SAFE_FREE(source); - } - - tsk_safeobj_unlock(self); - - return ret; + int ret = 0; + trtp_rtcp_source_t* source; + + if(!self || !packet_rtp || !packet_rtp->header) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + if(!self->is_started) { + TSK_DEBUG_INFO("RTCP session not started"); + return -2; + } + + tsk_safeobj_lock(self); + OnReceive(self, (const packet_)packet_rtp, EVENT_RTP, size); + if((source = _trtp_rtcp_session_find_source(self, packet_rtp->header->ssrc))) { + if(_trtp_rtcp_source_update_seq(source, packet_rtp->header->seq_num, packet_rtp->header->timestamp)) { + // RFC 3550 A.8 Estimating the Interarrival Jitter + /* uint32_t expected = (source->cycles + source->max_seq) - source->base_seq + 1; */ + double arrival = (((double)(source->max_ts - source->base_ts) / (double)source->rate) * 1000); + int32_t transit = (int32_t)arrival - packet_rtp->header->timestamp; + int32_t d = (transit - source->transit); + if(d < 0) { + d = -d; + } + source->transit = transit; + source->jitter += (1./16.) * ((double)d - source->jitter); + } + TSK_OBJECT_SAFE_FREE(source); + } + + tsk_safeobj_unlock(self); + + return ret; } int trtp_rtcp_session_process_rtcp_in(trtp_rtcp_session_t* self, const void* buffer, tsk_size_t size) { - int ret = 0; - trtp_rtcp_packet_t* packet_rtcp = tsk_null; - - if(!self || !buffer || size < TRTP_RTCP_HEADER_SIZE){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - if(!self->is_started){ - TSK_DEBUG_ERROR("Not started"); - return -2; - } - - // derialize the RTCP packet for processing - packet_rtcp = trtp_rtcp_packet_deserialize(buffer, size); - if(packet_rtcp){ - tsk_safeobj_lock(self); - OnReceive(self, - (const packet_)packet_rtcp, - (packet_rtcp->header->type == trtp_rtcp_packet_type_bye) ? EVENT_BYE : EVENT_REPORT, - size); - if(packet_rtcp->header->type == trtp_rtcp_packet_type_sr){ - trtp_rtcp_source_t* source; - const trtp_rtcp_report_sr_t* sr = (const trtp_rtcp_report_sr_t*)packet_rtcp; - if((source = _trtp_rtcp_session_find_source(self, sr->ssrc))){ - source->ntp_lsw = sr->sender_info.ntp_lsw; - source->ntp_msw = sr->sender_info.ntp_msw; - source->dlsr = tsk_time_now(); - TSK_OBJECT_SAFE_FREE(source); - } - } - tsk_safeobj_unlock(self); // must be before callback() - - if(self->callback){ - ret = self->callback(self->callback_data, packet_rtcp); - } - TSK_OBJECT_SAFE_FREE(packet_rtcp); - } - - - return ret; + int ret = 0; + trtp_rtcp_packet_t* packet_rtcp = tsk_null; + + if(!self || !buffer || size < TRTP_RTCP_HEADER_SIZE) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + if(!self->is_started) { + TSK_DEBUG_ERROR("Not started"); + return -2; + } + + // derialize the RTCP packet for processing + packet_rtcp = trtp_rtcp_packet_deserialize(buffer, size); + if(packet_rtcp) { + tsk_safeobj_lock(self); + OnReceive(self, + (const packet_)packet_rtcp, + (packet_rtcp->header->type == trtp_rtcp_packet_type_bye) ? EVENT_BYE : EVENT_REPORT, + size); + if(packet_rtcp->header->type == trtp_rtcp_packet_type_sr) { + trtp_rtcp_source_t* source; + const trtp_rtcp_report_sr_t* sr = (const trtp_rtcp_report_sr_t*)packet_rtcp; + if((source = _trtp_rtcp_session_find_source(self, sr->ssrc))) { + source->ntp_lsw = sr->sender_info.ntp_lsw; + source->ntp_msw = sr->sender_info.ntp_msw; + source->dlsr = tsk_time_now(); + TSK_OBJECT_SAFE_FREE(source); + } + } + tsk_safeobj_unlock(self); // must be before callback() + + if(self->callback) { + ret = self->callback(self->callback_data, packet_rtcp); + } + TSK_OBJECT_SAFE_FREE(packet_rtcp); + } + + + return ret; } int trtp_rtcp_session_signal_pkt_loss(trtp_rtcp_session_t* self, uint32_t ssrc_media, const uint16_t* seq_nums, tsk_size_t count) { - trtp_rtcp_report_rr_t* rr; - if(!self || !self->source_local || !seq_nums || !count){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if(!self->is_started){ - TSK_DEBUG_ERROR("Not started"); - return -1; - } - - tsk_safeobj_lock(self); - - if((rr = trtp_rtcp_report_rr_create_2(self->source_local->ssrc))){ - trtp_rtcp_report_rtpfb_t* rtpfb; - if((rtpfb = trtp_rtcp_report_rtpfb_create_nack(self->source_local->ssrc, ssrc_media, seq_nums, count))){ - trtp_rtcp_packet_add_packet((trtp_rtcp_packet_t*)rr, (trtp_rtcp_packet_t*)rtpfb, tsk_false); - _trtp_rtcp_session_send_pkt(self, (trtp_rtcp_packet_t*)rr); - TSK_OBJECT_SAFE_FREE(rtpfb); - } - TSK_OBJECT_SAFE_FREE(rr); - } - - tsk_safeobj_unlock(self); - - return 0; + trtp_rtcp_report_rr_t* rr; + if(!self || !self->source_local || !seq_nums || !count) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if(!self->is_started) { + TSK_DEBUG_ERROR("Not started"); + return -1; + } + + tsk_safeobj_lock(self); + + if((rr = trtp_rtcp_report_rr_create_2(self->source_local->ssrc))) { + trtp_rtcp_report_rtpfb_t* rtpfb; + if((rtpfb = trtp_rtcp_report_rtpfb_create_nack(self->source_local->ssrc, ssrc_media, seq_nums, count))) { + trtp_rtcp_packet_add_packet((trtp_rtcp_packet_t*)rr, (trtp_rtcp_packet_t*)rtpfb, tsk_false); + _trtp_rtcp_session_send_pkt(self, (trtp_rtcp_packet_t*)rr); + TSK_OBJECT_SAFE_FREE(rtpfb); + } + TSK_OBJECT_SAFE_FREE(rr); + } + + tsk_safeobj_unlock(self); + + return 0; } // Frame corrupted means the prediction chain is broken -> Send FIR int trtp_rtcp_session_signal_frame_corrupted(trtp_rtcp_session_t* self, uint32_t ssrc_media) { - trtp_rtcp_report_rr_t* rr; - if(!self || !self->source_local){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if(!self->is_started){ - TSK_DEBUG_ERROR("Not started"); - return -1; - } - - tsk_safeobj_lock(self); - - if((rr = trtp_rtcp_report_rr_create_2(self->source_local->ssrc))){ - trtp_rtcp_report_psfb_t* psfb_fir = trtp_rtcp_report_psfb_create_fir(self->fir_seqnr++, self->source_local->ssrc, ssrc_media); - if(psfb_fir){ - trtp_rtcp_packet_add_packet((trtp_rtcp_packet_t*)rr, (trtp_rtcp_packet_t*)psfb_fir, tsk_false); - _trtp_rtcp_session_send_pkt(self, (trtp_rtcp_packet_t*)rr); - TSK_OBJECT_SAFE_FREE(psfb_fir); - } - TSK_OBJECT_SAFE_FREE(rr); - } - - tsk_safeobj_unlock(self); - return 0; + trtp_rtcp_report_rr_t* rr; + if(!self || !self->source_local) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if(!self->is_started) { + TSK_DEBUG_ERROR("Not started"); + return -1; + } + + tsk_safeobj_lock(self); + + if((rr = trtp_rtcp_report_rr_create_2(self->source_local->ssrc))) { + trtp_rtcp_report_psfb_t* psfb_fir = trtp_rtcp_report_psfb_create_fir(self->fir_seqnr++, self->source_local->ssrc, ssrc_media); + if(psfb_fir) { + trtp_rtcp_packet_add_packet((trtp_rtcp_packet_t*)rr, (trtp_rtcp_packet_t*)psfb_fir, tsk_false); + _trtp_rtcp_session_send_pkt(self, (trtp_rtcp_packet_t*)rr); + TSK_OBJECT_SAFE_FREE(psfb_fir); + } + TSK_OBJECT_SAFE_FREE(rr); + } + + tsk_safeobj_unlock(self); + return 0; } // for now send just a FIR int trtp_rtcp_session_signal_jb_error(struct trtp_rtcp_session_s* self, uint32_t ssrc_media) { - return trtp_rtcp_session_signal_frame_corrupted(self, ssrc_media); + return trtp_rtcp_session_signal_frame_corrupted(self, ssrc_media); } tnet_fd_t trtp_rtcp_session_get_local_fd(const struct trtp_rtcp_session_s* self) @@ -800,314 +824,329 @@ int trtp_rtcp_session_set_net_transport(struct trtp_rtcp_session_s* self, struct static tsk_bool_t _trtp_rtcp_session_have_source(trtp_rtcp_session_t* self, uint32_t ssrc) { - tsk_list_item_t* item; - tsk_list_foreach(item, self->sources){ - if(TRTP_RTCP_SOURCE(item->data)->ssrc == ssrc){ - return tsk_true; - } - } - return tsk_false; + tsk_list_item_t* item; + tsk_list_foreach(item, self->sources) { + if(TRTP_RTCP_SOURCE(item->data)->ssrc == ssrc) { + return tsk_true; + } + } + return tsk_false; } // find source by ssrc // the caller must release the returned object static trtp_rtcp_source_t* _trtp_rtcp_session_find_source(trtp_rtcp_session_t* self, uint32_t ssrc) { - tsk_list_item_t* item; - tsk_list_foreach(item, self->sources){ - if(TRTP_RTCP_SOURCE(item->data)->ssrc == ssrc){ - return tsk_object_ref(item->data); - } - } - return tsk_null; + tsk_list_item_t* item; + tsk_list_foreach(item, self->sources) { + if(TRTP_RTCP_SOURCE(item->data)->ssrc == ssrc) { + return tsk_object_ref(item->data); + } + } + return tsk_null; } // find or add source by ssrc // the caller must release the returned object static trtp_rtcp_source_t* _trtp_rtcp_session_find_or_add_source(trtp_rtcp_session_t* self, uint32_t ssrc, uint16_t seq_if_add, uint32_t ts_id_add) { - trtp_rtcp_source_t* source; - if((source = _trtp_rtcp_session_find_source(self, ssrc))){ - return source; - } - - if((source = _trtp_rtcp_source_create(ssrc, seq_if_add, ts_id_add))){ - if((_trtp_rtcp_session_add_source(self, source)) != 0){ - TSK_DEBUG_ERROR("Failed to add source"); - TSK_OBJECT_SAFE_FREE(source); - return tsk_null; - } - return tsk_object_ref(source); - } - return tsk_null; + trtp_rtcp_source_t* source; + if((source = _trtp_rtcp_session_find_source(self, ssrc))) { + return source; + } + + if((source = _trtp_rtcp_source_create(ssrc, seq_if_add, ts_id_add))) { + if((_trtp_rtcp_session_add_source(self, source)) != 0) { + TSK_DEBUG_ERROR("Failed to add source"); + TSK_OBJECT_SAFE_FREE(source); + return tsk_null; + } + return tsk_object_ref(source); + } + return tsk_null; } int _trtp_rtcp_session_add_source(trtp_rtcp_session_t* self, trtp_rtcp_source_t* source) { - if(!self || !source){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if(!self || !source) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - tsk_list_lock(self->sources); - source = tsk_object_ref(source); - tsk_list_push_back_data(self->sources, (void**)&source); - tsk_list_unlock(self->sources); + tsk_list_lock(self->sources); + source = tsk_object_ref(source); + tsk_list_push_back_data(self->sources, (void**)&source); + tsk_list_unlock(self->sources); - return 0; + return 0; } // adds a source if doesn't exist static int _trtp_rtcp_session_add_source_2(trtp_rtcp_session_t* self, uint32_t ssrc, uint16_t seq, uint32_t ts, tsk_bool_t *added) { - int ret = 0; - tsk_list_item_t* item; - trtp_rtcp_source_t* source; - - tsk_list_lock(self->sources); - tsk_list_foreach(item, self->sources){ - if(TRTP_RTCP_SOURCE(item->data)->ssrc == ssrc){ - tsk_list_unlock(self->sources); - *added = tsk_false; - return 0; - } - } + int ret = 0; + tsk_list_item_t* item; + trtp_rtcp_source_t* source; + + tsk_list_lock(self->sources); + tsk_list_foreach(item, self->sources) { + if(TRTP_RTCP_SOURCE(item->data)->ssrc == ssrc) { + tsk_list_unlock(self->sources); + *added = tsk_false; + return 0; + } + } - tsk_list_unlock(self->sources); + tsk_list_unlock(self->sources); - if((source = _trtp_rtcp_source_create(ssrc, seq, ts))){ - ret = _trtp_rtcp_session_add_source(self, source); - } + if((source = _trtp_rtcp_source_create(ssrc, seq, ts))) { + ret = _trtp_rtcp_session_add_source(self, source); + } - TSK_OBJECT_SAFE_FREE(source); + TSK_OBJECT_SAFE_FREE(source); - *added = tsk_true; - return ret; + *added = tsk_true; + return ret; } int _trtp_rtcp_session_remove_source(trtp_rtcp_session_t* self, uint32_t ssrc, tsk_bool_t *removed) { - *removed = tsk_false; - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - tsk_list_lock(self->sources); - if((*removed = tsk_list_remove_item_by_pred(self->sources, __pred_find_source_by_ssrc, &ssrc)) == tsk_true){ - // ... - } - tsk_list_unlock(self->sources); - return 0; + *removed = tsk_false; + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + tsk_list_lock(self->sources); + if((*removed = tsk_list_remove_item_by_pred(self->sources, __pred_find_source_by_ssrc, &ssrc)) == tsk_true) { + // ... + } + tsk_list_unlock(self->sources); + return 0; } static tsk_size_t _trtp_rtcp_session_send_pkt(trtp_rtcp_session_t* self, trtp_rtcp_packet_t* pkt) { - tsk_size_t ret = 0; - tsk_size_t __num_bytes_pad = 0; - tsk_buffer_t* buffer; + tsk_size_t ret = 0; + tsk_size_t __num_bytes_pad = 0; + tsk_buffer_t* buffer; - if(!self->remote_addr || self->local_fd <= 0){ - TSK_DEBUG_ERROR("Invalid network settings"); - return 0; - } + if(!self->remote_addr || self->local_fd <= 0) { + TSK_DEBUG_ERROR("Invalid network settings"); + return 0; + } #if HAVE_SRTP - if(self->srtp.session) __num_bytes_pad = (SRTP_MAX_TRAILER_LEN + 0x4); + if(self->srtp.session) { + __num_bytes_pad = (SRTP_MAX_TRAILER_LEN + 0x4); + } #endif - // SDES - if(!self->sdes && (self->sdes = trtp_rtcp_report_sdes_create_null())){ - trtp_rtcp_sdes_chunck_t* chunck = trtp_rtcp_sdes_chunck_create(self->source_local->ssrc); - if(chunck){ - static const char* _name = "test@doubango.org"; - trtp_rtcp_sdes_chunck_add_item(chunck, trtp_rtcp_sdes_item_type_cname, self->cname, (uint8_t)tsk_strlen(self->cname)); - trtp_rtcp_sdes_chunck_add_item(chunck, trtp_rtcp_sdes_item_type_name, _name, (uint8_t)tsk_strlen(_name)); - trtp_rtcp_report_sdes_add_chunck(self->sdes, chunck); - TSK_OBJECT_SAFE_FREE(chunck); - } - } - if(self->sdes){ - trtp_rtcp_packet_add_packet(pkt, (trtp_rtcp_packet_t*)self->sdes, tsk_true); - } - - if((buffer = trtp_rtcp_packet_serialize(pkt, __num_bytes_pad))){ - void* data = buffer->data; - int size = (int)buffer->size; + // SDES + if(!self->sdes && (self->sdes = trtp_rtcp_report_sdes_create_null())) { + trtp_rtcp_sdes_chunck_t* chunck = trtp_rtcp_sdes_chunck_create(self->source_local->ssrc); + if(chunck) { + static const char* _name = "test@doubango.org"; + trtp_rtcp_sdes_chunck_add_item(chunck, trtp_rtcp_sdes_item_type_cname, self->cname, (uint8_t)tsk_strlen(self->cname)); + trtp_rtcp_sdes_chunck_add_item(chunck, trtp_rtcp_sdes_item_type_name, _name, (uint8_t)tsk_strlen(_name)); + trtp_rtcp_report_sdes_add_chunck(self->sdes, chunck); + TSK_OBJECT_SAFE_FREE(chunck); + } + } + if(self->sdes) { + trtp_rtcp_packet_add_packet(pkt, (trtp_rtcp_packet_t*)self->sdes, tsk_true); + } + + if((buffer = trtp_rtcp_packet_serialize(pkt, __num_bytes_pad))) { + void* data = buffer->data; + int size = (int)buffer->size; #if HAVE_SRTP - if(self->srtp.session){ - if(srtp_protect_rtcp(((srtp_t)*self->srtp.session), data, &size) != err_status_ok){ - TSK_DEBUG_ERROR("srtp_protect_rtcp() failed"); - } - } + if(self->srtp.session) { + if(srtp_protect_rtcp(((srtp_t)*self->srtp.session), data, &size) != err_status_ok) { + TSK_DEBUG_ERROR("srtp_protect_rtcp() failed"); + } + } #endif - ret = _trtp_rtcp_session_send_raw(self, data, size); - TSK_OBJECT_SAFE_FREE(buffer); - } + ret = _trtp_rtcp_session_send_raw(self, data, size); + TSK_OBJECT_SAFE_FREE(buffer); + } - return ret; + return ret; } static tsk_size_t _trtp_rtcp_session_send_raw(trtp_rtcp_session_t* self, const void* data, tsk_size_t size) { - tsk_size_t ret = 0; - if (!self || !data || !size) { - TSK_DEBUG_ERROR("Invalid parameter"); - return 0; - } - if (self->is_ice_turn_active) { - ret = (tnet_ice_ctx_send_turn_rtcp(self->ice_ctx, data, size) == 0) ? size : 0; // returns #0 if ok - } - else { + tsk_size_t ret = 0; + if (!self || !data || !size) { + TSK_DEBUG_ERROR("Invalid parameter"); + return 0; + } + if (self->is_ice_turn_active) { + ret = (tnet_ice_ctx_send_turn_rtcp(self->ice_ctx, data, size) == 0) ? size : 0; // returns #0 if ok + } + else { ret = self->transport - ? tnet_transport_sendto(self->transport, self->local_fd, self->remote_addr, data, size) - : tnet_sockfd_sendto(self->local_fd, self->remote_addr, data, size); - } - return ret; + ? tnet_transport_sendto(self->transport, self->local_fd, self->remote_addr, data, size) + : tnet_sockfd_sendto(self->local_fd, self->remote_addr, data, size); + } + return ret; } static int _trtp_rtcp_session_timer_callback(const void* arg, tsk_timer_id_t timer_id) { - trtp_rtcp_session_t* session = (trtp_rtcp_session_t*)arg; - tsk_safeobj_lock(session); // must - if(session->timer.id_bye == timer_id){ - session->timer.id_bye = TSK_INVALID_TIMER_ID; - OnExpire(session, EVENT_BYE); - } - else if(session->timer.id_report == timer_id){ - session->timer.id_report = TSK_INVALID_TIMER_ID; - OnExpire(session, EVENT_REPORT); - } - tsk_safeobj_unlock(session); - return 0; + trtp_rtcp_session_t* session = (trtp_rtcp_session_t*)arg; + tsk_safeobj_lock(session); // must + if(session->timer.id_bye == timer_id) { + session->timer.id_bye = TSK_INVALID_TIMER_ID; + OnExpire(session, EVENT_BYE); + } + else if(session->timer.id_report == timer_id) { + session->timer.id_report = TSK_INVALID_TIMER_ID; + OnExpire(session, EVENT_REPORT); + } + tsk_safeobj_unlock(session); + return 0; } static tsk_bool_t IsRtpPacket(const packet_ p) { - return (TSK_OBJECT_HEADER(p)->__def__ == trtp_rtp_packet_def_t); + return (TSK_OBJECT_HEADER(p)->__def__ == trtp_rtp_packet_def_t); } static PacketType_ PacketType(const packet_ p) { - if(IsRtpPacket(p)){ - return PACKET_RTP; - } - else{ - switch(((const trtp_rtcp_packet_t*)p)->header->type){ - case trtp_rtcp_packet_type_bye: return PACKET_BYE; - default: return PACKET_RTCP_REPORT; - } - } + if(IsRtpPacket(p)) { + return PACKET_RTP; + } + else { + switch(((const trtp_rtcp_packet_t*)p)->header->type) { + case trtp_rtcp_packet_type_bye: + return PACKET_BYE; + default: + return PACKET_RTCP_REPORT; + } + } } // Returns true if the packet is from a member or not // also checks all csrc static tsk_bool_t NewMember(trtp_rtcp_session_t* session, const packet_ p) { - uint32_t ssrc = 0; - if(IsRtpPacket(p)){ - const trtp_rtp_packet_t* packet_rtp = (const trtp_rtp_packet_t*)p; - tsk_size_t i; - for(i = 0; i < packet_rtp->header->csrc_count && i < sizeof(packet_rtp->header->csrc)/sizeof(packet_rtp->header->csrc[0]); ++i){ - if(!(_trtp_rtcp_session_have_source(session, packet_rtp->header->csrc[i]))){ - return tsk_false; - } - } - ssrc = packet_rtp->header->ssrc; - } - else{ - switch(((const trtp_rtcp_packet_t*)p)->header->type){ - case trtp_rtcp_packet_type_rr: ssrc = ((const trtp_rtcp_report_rr_t*)p)->ssrc; break; - case trtp_rtcp_packet_type_sr: ssrc = ((const trtp_rtcp_report_sr_t*)p)->ssrc; break; - case trtp_rtcp_packet_type_bye: - { - tsk_size_t i; - const trtp_rtcp_report_bye_t* bye = (const trtp_rtcp_report_bye_t*)p; - for(i = 0; i < TRTP_RTCP_PACKET(bye)->header->rc; ++i){ - if(!_trtp_rtcp_session_have_source(session, bye->ssrc_list[i])){ - return tsk_false; - } - } - return tsk_true; - } - default: return tsk_false; - } - } - - return !_trtp_rtcp_session_have_source(session, ssrc); + uint32_t ssrc = 0; + if(IsRtpPacket(p)) { + const trtp_rtp_packet_t* packet_rtp = (const trtp_rtp_packet_t*)p; + tsk_size_t i; + for(i = 0; i < packet_rtp->header->csrc_count && i < sizeof(packet_rtp->header->csrc)/sizeof(packet_rtp->header->csrc[0]); ++i) { + if(!(_trtp_rtcp_session_have_source(session, packet_rtp->header->csrc[i]))) { + return tsk_false; + } + } + ssrc = packet_rtp->header->ssrc; + } + else { + switch(((const trtp_rtcp_packet_t*)p)->header->type) { + case trtp_rtcp_packet_type_rr: + ssrc = ((const trtp_rtcp_report_rr_t*)p)->ssrc; + break; + case trtp_rtcp_packet_type_sr: + ssrc = ((const trtp_rtcp_report_sr_t*)p)->ssrc; + break; + case trtp_rtcp_packet_type_bye: { + tsk_size_t i; + const trtp_rtcp_report_bye_t* bye = (const trtp_rtcp_report_bye_t*)p; + for(i = 0; i < TRTP_RTCP_PACKET(bye)->header->rc; ++i) { + if(!_trtp_rtcp_session_have_source(session, bye->ssrc_list[i])) { + return tsk_false; + } + } + return tsk_true; + } + default: + return tsk_false; + } + } + + return !_trtp_rtcp_session_have_source(session, ssrc); } #define NewSender(session, p) NewMember((session), (p)) static tsk_size_t AddMemberUsingRTCPPacket(trtp_rtcp_session_t* session, const trtp_rtcp_packet_t* p, tsk_bool_t sender) { - trtp_rtcp_packets_L_t* packets = tsk_null; - trtp_rtcp_rblocks_L_t* blocks = tsk_null; - tsk_bool_t added = tsk_false; - tsk_size_t count = 0; - - switch(p->header->type){ - case trtp_rtcp_packet_type_rr: - { - const trtp_rtcp_report_rr_t* rr = (const trtp_rtcp_report_rr_t*)p; - _trtp_rtcp_session_add_source_2(session, ((const trtp_rtcp_report_rr_t*)p)->ssrc, 0, 0, &added); - if(added) ++count; - - packets = rr->packets; - blocks = rr->blocks; - break; - } - case trtp_rtcp_packet_type_sr: - { - const trtp_rtcp_report_sr_t* sr = (const trtp_rtcp_report_sr_t*)p; - _trtp_rtcp_session_add_source_2(session, ((const trtp_rtcp_report_sr_t*)p)->ssrc, 0, 0, &added); - if(added) ++count; - packets = sr->packets; - blocks = sr->blocks; - break; - } - default: - { - break; + trtp_rtcp_packets_L_t* packets = tsk_null; + trtp_rtcp_rblocks_L_t* blocks = tsk_null; + tsk_bool_t added = tsk_false; + tsk_size_t count = 0; + + switch(p->header->type) { + case trtp_rtcp_packet_type_rr: { + const trtp_rtcp_report_rr_t* rr = (const trtp_rtcp_report_rr_t*)p; + _trtp_rtcp_session_add_source_2(session, ((const trtp_rtcp_report_rr_t*)p)->ssrc, 0, 0, &added); + if(added) { + ++count; + } + + packets = rr->packets; + blocks = rr->blocks; + break; + } + case trtp_rtcp_packet_type_sr: { + const trtp_rtcp_report_sr_t* sr = (const trtp_rtcp_report_sr_t*)p; + _trtp_rtcp_session_add_source_2(session, ((const trtp_rtcp_report_sr_t*)p)->ssrc, 0, 0, &added); + if(added) { + ++count; + } + packets = sr->packets; + blocks = sr->blocks; + break; + } + default: { + break; + } + } + + if(!sender) { + if(packets) { + const tsk_list_item_t *item; + tsk_list_foreach(item, packets) { + AddMemberUsingRTCPPacket(session, (const trtp_rtcp_packet_t*)item->data, sender); + } + } + if(blocks) { + const tsk_list_item_t *item; + tsk_list_foreach(item, blocks) { + _trtp_rtcp_session_add_source_2(session, TRTP_RTCP_RBLOCK(item->data)->ssrc, 0, 0, &added); + if(added) { + ++count; + } } - } - - if(!sender){ - if(packets){ - const tsk_list_item_t *item; - tsk_list_foreach(item, packets){ - AddMemberUsingRTCPPacket(session, (const trtp_rtcp_packet_t*)item->data, sender); - } - } - if(blocks){ - const tsk_list_item_t *item; - tsk_list_foreach(item, blocks){ - _trtp_rtcp_session_add_source_2(session, TRTP_RTCP_RBLOCK(item->data)->ssrc, 0, 0, &added); - if(added) ++count; - } - } - } - - return count; + } + } + + return count; } static tsk_size_t AddMember_(trtp_rtcp_session_t* session, const packet_ p, tsk_bool_t sender) { - tsk_size_t count = 0; - if(IsRtpPacket(p)){ - const trtp_rtp_packet_t* packet_rtp = (const trtp_rtp_packet_t*)p; - tsk_size_t i; - tsk_bool_t added = tsk_false; - _trtp_rtcp_session_add_source_2(session, packet_rtp->header->ssrc, packet_rtp->header->seq_num, packet_rtp->header->timestamp, &added); - if(added) ++count; - for(i = 0; i < packet_rtp->header->csrc_count && i < sizeof(packet_rtp->header->csrc)/sizeof(packet_rtp->header->csrc[0]); ++i){ - _trtp_rtcp_session_add_source_2(session, packet_rtp->header->csrc[i], 0, 0, &added); - if(added) ++count; - } - } - else{ - count += AddMemberUsingRTCPPacket(session, (const trtp_rtcp_packet_t*) p, sender); - } - return count; + tsk_size_t count = 0; + if(IsRtpPacket(p)) { + const trtp_rtp_packet_t* packet_rtp = (const trtp_rtp_packet_t*)p; + tsk_size_t i; + tsk_bool_t added = tsk_false; + _trtp_rtcp_session_add_source_2(session, packet_rtp->header->ssrc, packet_rtp->header->seq_num, packet_rtp->header->timestamp, &added); + if(added) { + ++count; + } + for(i = 0; i < packet_rtp->header->csrc_count && i < sizeof(packet_rtp->header->csrc)/sizeof(packet_rtp->header->csrc[0]); ++i) { + _trtp_rtcp_session_add_source_2(session, packet_rtp->header->csrc[i], 0, 0, &added); + if(added) { + ++count; + } + } + } + else { + count += AddMemberUsingRTCPPacket(session, (const trtp_rtcp_packet_t*) p, sender); + } + return count; } #define AddMember(session, p) AddMember_((session), (p), tsk_false) @@ -1116,73 +1155,80 @@ static tsk_size_t AddMember_(trtp_rtcp_session_t* session, const packet_ p, tsk_ static tsk_size_t RemoveMemberUsingRTCPPacket(trtp_rtcp_session_t* session, const trtp_rtcp_packet_t* p) { - trtp_rtcp_packets_L_t* packets = tsk_null; - trtp_rtcp_rblocks_L_t* blocks = tsk_null; - tsk_bool_t removed = tsk_false; - tsk_size_t count = 0; - - switch(p->header->type){ - case trtp_rtcp_packet_type_rr: - { - const trtp_rtcp_report_rr_t* rr = (const trtp_rtcp_report_rr_t*)p; - _trtp_rtcp_session_remove_source(session, ((const trtp_rtcp_report_rr_t*)p)->ssrc, &removed); - if(removed) ++count; - - packets = rr->packets; - blocks = rr->blocks; - break; - } - case trtp_rtcp_packet_type_sr: - { - const trtp_rtcp_report_sr_t* sr = (const trtp_rtcp_report_sr_t*)p; - _trtp_rtcp_session_remove_source(session, ((const trtp_rtcp_report_sr_t*)p)->ssrc, &removed); - if(removed) ++count; - packets = sr->packets; - blocks = sr->blocks; - break; - } - default: - { - break; + trtp_rtcp_packets_L_t* packets = tsk_null; + trtp_rtcp_rblocks_L_t* blocks = tsk_null; + tsk_bool_t removed = tsk_false; + tsk_size_t count = 0; + + switch(p->header->type) { + case trtp_rtcp_packet_type_rr: { + const trtp_rtcp_report_rr_t* rr = (const trtp_rtcp_report_rr_t*)p; + _trtp_rtcp_session_remove_source(session, ((const trtp_rtcp_report_rr_t*)p)->ssrc, &removed); + if(removed) { + ++count; + } + + packets = rr->packets; + blocks = rr->blocks; + break; + } + case trtp_rtcp_packet_type_sr: { + const trtp_rtcp_report_sr_t* sr = (const trtp_rtcp_report_sr_t*)p; + _trtp_rtcp_session_remove_source(session, ((const trtp_rtcp_report_sr_t*)p)->ssrc, &removed); + if(removed) { + ++count; + } + packets = sr->packets; + blocks = sr->blocks; + break; + } + default: { + break; + } + } + + if(packets) { + const tsk_list_item_t *item; + tsk_list_foreach(item, packets) { + RemoveMemberUsingRTCPPacket(session, (const trtp_rtcp_packet_t*)item->data); + } + } + if(blocks) { + const tsk_list_item_t *item; + tsk_list_foreach(item, blocks) { + _trtp_rtcp_session_remove_source(session, TRTP_RTCP_RBLOCK(item->data)->ssrc, &removed); + if(removed) { + ++count; } - } - - if(packets){ - const tsk_list_item_t *item; - tsk_list_foreach(item, packets){ - RemoveMemberUsingRTCPPacket(session, (const trtp_rtcp_packet_t*)item->data); - } - } - if(blocks){ - const tsk_list_item_t *item; - tsk_list_foreach(item, blocks){ - _trtp_rtcp_session_remove_source(session, TRTP_RTCP_RBLOCK(item->data)->ssrc, &removed); - if(removed) ++count; - } - } - - - return count; + } + } + + + return count; } static tsk_size_t RemoveMember(trtp_rtcp_session_t* session, const packet_ p) { - tsk_size_t count = 0; - if(IsRtpPacket(p)){ - const trtp_rtp_packet_t* packet_rtp = (const trtp_rtp_packet_t*)p; - tsk_size_t i; - tsk_bool_t removed = tsk_false; - _trtp_rtcp_session_remove_source(session, packet_rtp->header->ssrc, &removed); - if(removed) ++count; - for(i = 0; i < packet_rtp->header->csrc_count && i < sizeof(packet_rtp->header->csrc)/sizeof(packet_rtp->header->csrc[0]); ++i){ - _trtp_rtcp_session_remove_source(session, packet_rtp->header->csrc[i], &removed); - if(removed) ++count; - } - } - else{ - count += RemoveMemberUsingRTCPPacket(session, (const trtp_rtcp_packet_t*) p); - } - return count; + tsk_size_t count = 0; + if(IsRtpPacket(p)) { + const trtp_rtp_packet_t* packet_rtp = (const trtp_rtp_packet_t*)p; + tsk_size_t i; + tsk_bool_t removed = tsk_false; + _trtp_rtcp_session_remove_source(session, packet_rtp->header->ssrc, &removed); + if(removed) { + ++count; + } + for(i = 0; i < packet_rtp->header->csrc_count && i < sizeof(packet_rtp->header->csrc)/sizeof(packet_rtp->header->csrc[0]); ++i) { + _trtp_rtcp_session_remove_source(session, packet_rtp->header->csrc[i], &removed); + if(removed) { + ++count; + } + } + } + else { + count += RemoveMemberUsingRTCPPacket(session, (const trtp_rtcp_packet_t*) p); + } + return count; } #define RemoveSender(session, p) RemoveMember((session), (p)) @@ -1190,395 +1236,414 @@ static tsk_size_t RemoveMember(trtp_rtcp_session_t* session, const packet_ p) // Sends BYE in synchronous mode static void SendBYEPacket(trtp_rtcp_session_t* session, event_ e) { - trtp_rtcp_report_bye_t* bye; - tsk_size_t __num_bytes_pad = 0; + trtp_rtcp_report_bye_t* bye; + tsk_size_t __num_bytes_pad = 0; - if(!session->remote_addr || session->local_fd <= 0){ - TSK_DEBUG_ERROR("Invalid network settings"); - return; - } + if(!session->remote_addr || session->local_fd <= 0) { + TSK_DEBUG_ERROR("Invalid network settings"); + return; + } - tsk_safeobj_lock(session); + tsk_safeobj_lock(session); #if HAVE_SRTP - if(session->srtp.session) __num_bytes_pad = (SRTP_MAX_TRAILER_LEN + 0x4); + if(session->srtp.session) { + __num_bytes_pad = (SRTP_MAX_TRAILER_LEN + 0x4); + } #endif - if(session->source_local && (bye = trtp_rtcp_report_bye_create_2(session->source_local->ssrc))){ - tsk_buffer_t* buffer; - // serialize and send the packet - if((buffer = trtp_rtcp_packet_serialize((const trtp_rtcp_packet_t*)bye, __num_bytes_pad))){ - void* data = buffer->data; - int size = (int)buffer->size; + if(session->source_local && (bye = trtp_rtcp_report_bye_create_2(session->source_local->ssrc))) { + tsk_buffer_t* buffer; + // serialize and send the packet + if((buffer = trtp_rtcp_packet_serialize((const trtp_rtcp_packet_t*)bye, __num_bytes_pad))) { + void* data = buffer->data; + int size = (int)buffer->size; #if HAVE_SRTP - if(session->srtp.session){ - if(srtp_protect_rtcp(((srtp_t)*session->srtp.session), data, &size) != err_status_ok){ - TSK_DEBUG_ERROR("srtp_protect_rtcp() failed"); - } - } + if(session->srtp.session) { + if(srtp_protect_rtcp(((srtp_t)*session->srtp.session), data, &size) != err_status_ok) { + TSK_DEBUG_ERROR("srtp_protect_rtcp() failed"); + } + } #endif - _trtp_rtcp_session_send_raw(session, data, size); - TSK_OBJECT_SAFE_FREE(buffer); - } - TSK_OBJECT_SAFE_FREE(bye); - } + _trtp_rtcp_session_send_raw(session, data, size); + TSK_OBJECT_SAFE_FREE(buffer); + } + TSK_OBJECT_SAFE_FREE(bye); + } - tsk_safeobj_unlock(session); + tsk_safeobj_unlock(session); } // returns sent packet size static tsk_size_t SendRTCPReport(trtp_rtcp_session_t* session, event_ e) { - tsk_size_t ret = 0; - - tsk_safeobj_lock(session); - - if(session->initial){ - // Send Receiver report (manadatory to be the first on) - trtp_rtcp_report_rr_t* rr = trtp_rtcp_report_rr_create_2(session->source_local->ssrc); - if(rr){ - // serialize and send the packet - ret = _trtp_rtcp_session_send_pkt(session, (trtp_rtcp_packet_t*)rr); - TSK_OBJECT_SAFE_FREE(rr); - } - } - else{ - trtp_rtcp_report_sr_t* sr = trtp_rtcp_report_sr_create_null(); - uint32_t media_ssrc_list[16] = {0}; - uint32_t media_ssrc_list_count = 0; - if(sr){ - uint64_t ntp_now = tsk_time_ntp(); - uint64_t time_now = tsk_time_now(); - trtp_rtcp_rblock_t* rblock; - trtp_rtcp_source_t* source; - tsk_list_item_t *item; - tsk_bool_t packet_lost = tsk_false; - - // sender info - sr->ssrc = session->source_local->ssrc; - sr->sender_info.ntp_msw = (ntp_now >> 32); - sr->sender_info.ntp_lsw = (ntp_now & 0xFFFFFFFF); - sr->sender_info.sender_pcount = session->packets_count; - sr->sender_info.sender_ocount = session->octets_count; - { /* rtp_timestamp */ - struct timeval tv; - uint64_t rtp_timestamp = (time_now - session->time_start) * (session->source_local->rate / 1000); - tv.tv_sec = (long)(rtp_timestamp / 1000); - tv.tv_usec = (long)(rtp_timestamp - ((rtp_timestamp / 1000) * 1000)) * 1000; + tsk_size_t ret = 0; + + tsk_safeobj_lock(session); + + if(session->initial) { + // Send Receiver report (manadatory to be the first on) + trtp_rtcp_report_rr_t* rr = trtp_rtcp_report_rr_create_2(session->source_local->ssrc); + if(rr) { + // serialize and send the packet + ret = _trtp_rtcp_session_send_pkt(session, (trtp_rtcp_packet_t*)rr); + TSK_OBJECT_SAFE_FREE(rr); + } + } + else { + trtp_rtcp_report_sr_t* sr = trtp_rtcp_report_sr_create_null(); + uint32_t media_ssrc_list[16] = {0}; + uint32_t media_ssrc_list_count = 0; + if(sr) { + uint64_t ntp_now = tsk_time_ntp(); + uint64_t time_now = tsk_time_now(); + trtp_rtcp_rblock_t* rblock; + trtp_rtcp_source_t* source; + tsk_list_item_t *item; + tsk_bool_t packet_lost = tsk_false; + + // sender info + sr->ssrc = session->source_local->ssrc; + sr->sender_info.ntp_msw = (ntp_now >> 32); + sr->sender_info.ntp_lsw = (ntp_now & 0xFFFFFFFF); + sr->sender_info.sender_pcount = session->packets_count; + sr->sender_info.sender_ocount = session->octets_count; + { /* rtp_timestamp */ + struct timeval tv; + uint64_t rtp_timestamp = (time_now - session->time_start) * (session->source_local->rate / 1000); + tv.tv_sec = (long)(rtp_timestamp / 1000); + tv.tv_usec = (long)(rtp_timestamp - ((rtp_timestamp / 1000) * 1000)) * 1000; #if 1 - sr->sender_info.rtp_timestamp = (uint32_t)tsk_time_get_ms(&tv); + sr->sender_info.rtp_timestamp = (uint32_t)tsk_time_get_ms(&tv); #else - sr->sender_info.rtp_timestamp = (uint32_t)tsk_time_get_ntp_ms(&tv); + sr->sender_info.rtp_timestamp = (uint32_t)tsk_time_get_ntp_ms(&tv); #endif - } - - // report blocks - tsk_list_foreach(item, session->sources){ - if(!(source = (trtp_rtcp_source_t*)item->data) || !_trtp_rtcp_source_is_probed(source)){ - continue; - } - if((rblock = trtp_rtcp_rblock_create_null())){ - int32_t expected, expected_interval, received_interval, lost_interval; - - rblock->ssrc = source->ssrc; - // RFC 3550 - A.3 Determining Number of Packets Expected and Lost - expected = (source->cycles + source->max_seq) - source->base_seq + 1; - expected_interval = expected - source->expected_prior; - source->expected_prior = expected; - received_interval = source->received - source->received_prior; - source->received_prior = source->received; - lost_interval = expected_interval - received_interval; - if (expected_interval == 0 || lost_interval <= 0) rblock->fraction = 0; - else rblock->fraction = (lost_interval << 8) / expected_interval; - rblock->cumulative_no_lost = ((expected - source->received)); - if(!packet_lost && rblock->fraction) packet_lost = tsk_true; - - rblock->last_seq = ((source->cycles & 0xFFFF) << 16) | source->max_seq; - rblock->jitter = (uint32_t)source->jitter; - rblock->lsr = ((source->ntp_msw & 0xFFFF) << 16) | ((source->ntp_lsw & 0xFFFF0000) >> 16); - if(source->dlsr){ - rblock->dlsr = (uint32_t)(((time_now - source->dlsr) * 65536) / 1000); // in units of 1/65536 seconds - } - - trtp_rtcp_report_sr_add_block(sr, rblock); - TSK_OBJECT_SAFE_FREE(rblock); - } - - if((media_ssrc_list_count + 1) < sizeof(media_ssrc_list)/sizeof(media_ssrc_list[0])){ - media_ssrc_list[media_ssrc_list_count++] = source->ssrc; - } - } - - if(media_ssrc_list_count > 0){ - // draft-alvestrand-rmcat-remb-02 - if(session->app_bw_max_download > 0 && session->app_bw_max_download != INT_MAX){ // INT_MAX or <=0 means undefined - // app_bw_max_download unit is kbps while create_afb_remb() expect bps - trtp_rtcp_report_psfb_t* psfb_afb_remb = trtp_rtcp_report_psfb_create_afb_remb(session->source_local->ssrc/*sender SSRC*/, media_ssrc_list, media_ssrc_list_count, (session->app_bw_max_download * 1024)); - if(psfb_afb_remb){ - TSK_DEBUG_INFO("Packing RTCP-AFB-REMB (bw_dwn=%d kbps) for outgoing RTCP-SR", session->app_bw_max_download); - trtp_rtcp_packet_add_packet((trtp_rtcp_packet_t*)sr, (trtp_rtcp_packet_t*)psfb_afb_remb, tsk_false); - TSK_OBJECT_SAFE_FREE(psfb_afb_remb); - } - } - } - - // serialize and send the packet - ret = _trtp_rtcp_session_send_pkt(session, (trtp_rtcp_packet_t*)sr); - TSK_OBJECT_SAFE_FREE(sr); - } - } - - tsk_safeobj_unlock(session); - return ret; + } + + // report blocks + tsk_list_foreach(item, session->sources) { + if(!(source = (trtp_rtcp_source_t*)item->data) || !_trtp_rtcp_source_is_probed(source)) { + continue; + } + if((rblock = trtp_rtcp_rblock_create_null())) { + int32_t expected, expected_interval, received_interval, lost_interval; + + rblock->ssrc = source->ssrc; + // RFC 3550 - A.3 Determining Number of Packets Expected and Lost + expected = (source->cycles + source->max_seq) - source->base_seq + 1; + expected_interval = expected - source->expected_prior; + source->expected_prior = expected; + received_interval = source->received - source->received_prior; + source->received_prior = source->received; + lost_interval = expected_interval - received_interval; + if (expected_interval == 0 || lost_interval <= 0) { + rblock->fraction = 0; + } + else { + rblock->fraction = (lost_interval << 8) / expected_interval; + } + rblock->cumulative_no_lost = ((expected - source->received)); + if(!packet_lost && rblock->fraction) { + packet_lost = tsk_true; + } + + rblock->last_seq = ((source->cycles & 0xFFFF) << 16) | source->max_seq; + rblock->jitter = (uint32_t)source->jitter; + rblock->lsr = ((source->ntp_msw & 0xFFFF) << 16) | ((source->ntp_lsw & 0xFFFF0000) >> 16); + if(source->dlsr) { + rblock->dlsr = (uint32_t)(((time_now - source->dlsr) * 65536) / 1000); // in units of 1/65536 seconds + } + + trtp_rtcp_report_sr_add_block(sr, rblock); + TSK_OBJECT_SAFE_FREE(rblock); + } + + if((media_ssrc_list_count + 1) < sizeof(media_ssrc_list)/sizeof(media_ssrc_list[0])) { + media_ssrc_list[media_ssrc_list_count++] = source->ssrc; + } + } + + if(media_ssrc_list_count > 0) { + // draft-alvestrand-rmcat-remb-02 + if(session->app_bw_max_download > 0 && session->app_bw_max_download != INT_MAX) { // INT_MAX or <=0 means undefined + // app_bw_max_download unit is kbps while create_afb_remb() expect bps + trtp_rtcp_report_psfb_t* psfb_afb_remb = trtp_rtcp_report_psfb_create_afb_remb(session->source_local->ssrc/*sender SSRC*/, media_ssrc_list, media_ssrc_list_count, (session->app_bw_max_download * 1024)); + if(psfb_afb_remb) { + TSK_DEBUG_INFO("Packing RTCP-AFB-REMB (bw_dwn=%d kbps) for outgoing RTCP-SR", session->app_bw_max_download); + trtp_rtcp_packet_add_packet((trtp_rtcp_packet_t*)sr, (trtp_rtcp_packet_t*)psfb_afb_remb, tsk_false); + TSK_OBJECT_SAFE_FREE(psfb_afb_remb); + } + } + } + + // serialize and send the packet + ret = _trtp_rtcp_session_send_pkt(session, (trtp_rtcp_packet_t*)sr); + TSK_OBJECT_SAFE_FREE(sr); + } + } + + tsk_safeobj_unlock(session); + return ret; } static void Schedule(trtp_rtcp_session_t* session, double tn, event_ e) { - tsk_safeobj_lock(session); // must - switch(e){ - case EVENT_BYE: - if(!TSK_TIMER_ID_IS_VALID(session->timer.id_bye)){ - session->timer.id_bye = tsk_timer_manager_schedule(session->timer.handle_global, (uint64_t)tn, _trtp_rtcp_session_timer_callback, session); - } - break; - case EVENT_REPORT: - if(!TSK_TIMER_ID_IS_VALID(session->timer.id_report)){ - session->timer.id_report = tsk_timer_manager_schedule(session->timer.handle_global, (uint64_t)tn, _trtp_rtcp_session_timer_callback, session); - } - break; - default: TSK_DEBUG_ERROR("Unexpected code called"); break; - } - tsk_safeobj_unlock(session); + tsk_safeobj_lock(session); // must + switch(e) { + case EVENT_BYE: + if(!TSK_TIMER_ID_IS_VALID(session->timer.id_bye)) { + session->timer.id_bye = tsk_timer_manager_schedule(session->timer.handle_global, (uint64_t)tn, _trtp_rtcp_session_timer_callback, session); + } + break; + case EVENT_REPORT: + if(!TSK_TIMER_ID_IS_VALID(session->timer.id_report)) { + session->timer.id_report = tsk_timer_manager_schedule(session->timer.handle_global, (uint64_t)tn, _trtp_rtcp_session_timer_callback, session); + } + break; + default: + TSK_DEBUG_ERROR("Unexpected code called"); + break; + } + tsk_safeobj_unlock(session); } #define Reschedule(session, tn, e) Schedule((session), (tn), (e)) static double rtcp_interval(int32_t members, - int32_t senders, - double rtcp_bw, - int32_t we_sent, - double avg_rtcp_size, - tsk_bool_t initial) + int32_t senders, + double rtcp_bw, + int32_t we_sent, + double avg_rtcp_size, + tsk_bool_t initial) { - /* - * Minimum average time between RTCP packets from this site (in - * seconds). This time prevents the reports from `clumping' when - * sessions are small and the law of large numbers isn't helping - * to smooth out the traffic. It also keeps the report interval - * from becoming ridiculously small during transient outages like - * a network partition. - */ - #define RTCP_MIN_TIME 5. - /* - * Fraction of the RTCP bandwidth to be shared among active - * senders. (This fraction was chosen so that in a typical - * session with one or two active senders, the computed report - * time would be roughly equal to the minimum report time so that - * we don't unnecessarily slow down receiver reports.) The - * receiver fraction must be 1 - the sender fraction. - */ - #define RTCP_SENDER_BW_FRACTION 0.25 - #define RTCP_RCVR_BW_FRACTION (1 - RTCP_SENDER_BW_FRACTION) - /* - * To compensate for "timer reconsideration" converging to a - * value below the intended average. - */ - #define COMPENSATION (2.71828 - 1.5) - - double t; /* interval */ - double rtcp_min_time = RTCP_MIN_TIME; - int n; /* no. of members for computation */ - - /* - * Very first call at application start-up uses half the min - * delay for quicker notification while still allowing some time - * before reporting for randomization and to learn about other - * sources so the report interval will converge to the correct - * interval more quickly. - */ - if (initial) { - rtcp_min_time /= 2; - } - /* - * Dedicate a fraction of the RTCP bandwidth to senders unless - * the number of senders is large enough that their share is - * more than that fraction. - */ - n = members; - if (senders <= members * RTCP_SENDER_BW_FRACTION) { - if (we_sent) { - rtcp_bw *= RTCP_SENDER_BW_FRACTION; - n = senders; - } else { - rtcp_bw *= RTCP_RCVR_BW_FRACTION; - n -= senders; - } - } - - /* - * The effective number of sites times the average packet size is - * the total number of octets sent when each site sends a report. - * Dividing this by the effective bandwidth gives the time - * interval over which those packets must be sent in order to - * meet the bandwidth target, with a minimum enforced. In that - * time interval we send one report so this time is also our - * average time between reports. - */ - t = avg_rtcp_size * n / rtcp_bw; - if (t < rtcp_min_time) t = rtcp_min_time; - - /* - * To avoid traffic bursts from unintended synchronization with - * other sites, we then pick our actual next report interval as a - * random number uniformly distributed between 0.5*t and 1.5*t. - */ - t = t * (drand48() + 0.5); - t = t / COMPENSATION; - - return (t * 1000); + /* + * Minimum average time between RTCP packets from this site (in + * seconds). This time prevents the reports from `clumping' when + * sessions are small and the law of large numbers isn't helping + * to smooth out the traffic. It also keeps the report interval + * from becoming ridiculously small during transient outages like + * a network partition. + */ +#define RTCP_MIN_TIME 5. + /* + * Fraction of the RTCP bandwidth to be shared among active + * senders. (This fraction was chosen so that in a typical + * session with one or two active senders, the computed report + * time would be roughly equal to the minimum report time so that + * we don't unnecessarily slow down receiver reports.) The + * receiver fraction must be 1 - the sender fraction. + */ +#define RTCP_SENDER_BW_FRACTION 0.25 +#define RTCP_RCVR_BW_FRACTION (1 - RTCP_SENDER_BW_FRACTION) + /* + * To compensate for "timer reconsideration" converging to a + * value below the intended average. + */ +#define COMPENSATION (2.71828 - 1.5) + + double t; /* interval */ + double rtcp_min_time = RTCP_MIN_TIME; + int n; /* no. of members for computation */ + + /* + * Very first call at application start-up uses half the min + * delay for quicker notification while still allowing some time + * before reporting for randomization and to learn about other + * sources so the report interval will converge to the correct + * interval more quickly. + */ + if (initial) { + rtcp_min_time /= 2; + } + /* + * Dedicate a fraction of the RTCP bandwidth to senders unless + * the number of senders is large enough that their share is + * more than that fraction. + */ + n = members; + if (senders <= members * RTCP_SENDER_BW_FRACTION) { + if (we_sent) { + rtcp_bw *= RTCP_SENDER_BW_FRACTION; + n = senders; + } + else { + rtcp_bw *= RTCP_RCVR_BW_FRACTION; + n -= senders; + } + } + + /* + * The effective number of sites times the average packet size is + * the total number of octets sent when each site sends a report. + * Dividing this by the effective bandwidth gives the time + * interval over which those packets must be sent in order to + * meet the bandwidth target, with a minimum enforced. In that + * time interval we send one report so this time is also our + * average time between reports. + */ + t = avg_rtcp_size * n / rtcp_bw; + if (t < rtcp_min_time) { + t = rtcp_min_time; + } + + /* + * To avoid traffic bursts from unintended synchronization with + * other sites, we then pick our actual next report interval as a + * random number uniformly distributed between 0.5*t and 1.5*t. + */ + t = t * (drand48() + 0.5); + t = t / COMPENSATION; + + return (t * 1000); } static void OnExpire(trtp_rtcp_session_t* session, event_ e) { - /* This function is responsible for deciding whether to send an - * RTCP report or BYE packet now, or to reschedule transmission. - * It is also responsible for updating the pmembers, initial, tp, - * and avg_rtcp_size state variables. This function should be - * called upon expiration of the event timer used by Schedule(). - */ - - double t; /* Interval */ - double tn; /* Next transmit time */ - double tc; - - /* In the case of a BYE, we use "timer reconsideration" to - * reschedule the transmission of the BYE if necessary */ - - if (TypeOfEvent(e) == EVENT_BYE) { - t = rtcp_interval(session->members, - session->senders, - session->rtcp_bw, - session->we_sent, - session->avg_rtcp_size, - session->initial); - tn = session->tp + t; - if (tn <= session->tc()) { - SendBYEPacket(session, e); + /* This function is responsible for deciding whether to send an + * RTCP report or BYE packet now, or to reschedule transmission. + * It is also responsible for updating the pmembers, initial, tp, + * and avg_rtcp_size state variables. This function should be + * called upon expiration of the event timer used by Schedule(). + */ + + double t; /* Interval */ + double tn; /* Next transmit time */ + double tc; + + /* In the case of a BYE, we use "timer reconsideration" to + * reschedule the transmission of the BYE if necessary */ + + if (TypeOfEvent(e) == EVENT_BYE) { + t = rtcp_interval(session->members, + session->senders, + session->rtcp_bw, + session->we_sent, + session->avg_rtcp_size, + session->initial); + tn = session->tp + t; + if (tn <= session->tc()) { + SendBYEPacket(session, e); #if 0 - exit(1); + exit(1); #endif - } else { + } + else { #if 0 - Schedule(session, tn, e); + Schedule(session, tn, e); #else - Schedule(session, 0, e); + Schedule(session, 0, e); #endif - } - - } else if (TypeOfEvent(e) == EVENT_REPORT) { - t = rtcp_interval(session->members, - session->senders, - session->rtcp_bw, - session->we_sent, - session->avg_rtcp_size, - session->initial); - tn = session->tp + t; - if (tn <= (tc = session->tc())) { - tsk_size_t SentPacketSize = SendRTCPReport(session, e); - session->avg_rtcp_size = (1./16.)*SentPacketSize + (15./16.)*(session->avg_rtcp_size); - session->tp = tc; - - /* We must redraw the interval. Don't reuse the - one computed above, since its not actually - distributed the same, as we are conditioned - on it being small enough to cause a packet to - be sent */ - - t = rtcp_interval(session->members, - session->senders, - session->rtcp_bw, - session->we_sent, - session->avg_rtcp_size, - session->initial); + } + + } + else if (TypeOfEvent(e) == EVENT_REPORT) { + t = rtcp_interval(session->members, + session->senders, + session->rtcp_bw, + session->we_sent, + session->avg_rtcp_size, + session->initial); + tn = session->tp + t; + if (tn <= (tc = session->tc())) { + tsk_size_t SentPacketSize = SendRTCPReport(session, e); + session->avg_rtcp_size = (1./16.)*SentPacketSize + (15./16.)*(session->avg_rtcp_size); + session->tp = tc; + + /* We must redraw the interval. Don't reuse the + one computed above, since its not actually + distributed the same, as we are conditioned + on it being small enough to cause a packet to + be sent */ + + t = rtcp_interval(session->members, + session->senders, + session->rtcp_bw, + session->we_sent, + session->avg_rtcp_size, + session->initial); #if 0 - Schedule(session, t+tc, e); + Schedule(session, t+tc, e); #else - Schedule(session, t, e); + Schedule(session, t, e); #endif - session->initial = tsk_false; - } else { + session->initial = tsk_false; + } + else { #if 0 - Schedule(session, tn, e); + Schedule(session, tn, e); #else - Schedule(session, 0, e); + Schedule(session, 0, e); #endif - } - session->pmembers = session->members; - } + } + session->pmembers = session->members; + } } static void OnReceive(trtp_rtcp_session_t* session, const packet_ p, event_ e, tsk_size_t ReceivedPacketSize) { - /* What we do depends on whether we have left the group, and are - * waiting to send a BYE (TypeOfEvent(e) == EVENT_BYE) or an RTCP - * report. p represents the packet that was just received. */ - - if (PacketType(p) == PACKET_RTCP_REPORT) { - if (NewMember(session, p) && (TypeOfEvent(e) == EVENT_REPORT)) { - session->members += (int32_t)AddMember(session, p); - } - session->avg_rtcp_size = (1./16.)*ReceivedPacketSize + (15./16.)*(session->avg_rtcp_size); - } else if (PacketType(p) == PACKET_RTP) { + /* What we do depends on whether we have left the group, and are + * waiting to send a BYE (TypeOfEvent(e) == EVENT_BYE) or an RTCP + * report. p represents the packet that was just received. */ + + if (PacketType(p) == PACKET_RTCP_REPORT) { + if (NewMember(session, p) && (TypeOfEvent(e) == EVENT_REPORT)) { + session->members += (int32_t)AddMember(session, p); + } + session->avg_rtcp_size = (1./16.)*ReceivedPacketSize + (15./16.)*(session->avg_rtcp_size); + } + else if (PacketType(p) == PACKET_RTP) { #if 0 - if (NewMember(session, p) && (TypeOfEvent(e) == EVENT_REPORT)) { - session->members += AddMember(session, p); - } - if (NewSender(session, p) && (TypeOfEvent(e) == EVENT_REPORT)) { - tsk_size_t count = AddSender(session, p); - session->senders += count; - session->members += count; - } + if (NewMember(session, p) && (TypeOfEvent(e) == EVENT_REPORT)) { + session->members += AddMember(session, p); + } + if (NewSender(session, p) && (TypeOfEvent(e) == EVENT_REPORT)) { + tsk_size_t count = AddSender(session, p); + session->senders += count; + session->members += count; + } #else - if (NewSender(session, p)) { - tsk_size_t count = AddSender(session, p); - session->senders += (int32_t)count; - session->members += (int32_t)count; - } + if (NewSender(session, p)) { + tsk_size_t count = AddSender(session, p); + session->senders += (int32_t)count; + session->members += (int32_t)count; + } #endif - } else if (PacketType(p) == PACKET_BYE) { - session->avg_rtcp_size = (1./16.)*ReceivedPacketSize + (15./16.)*(session->avg_rtcp_size); - - if (TypeOfEvent(e) == EVENT_REPORT) { - double tc = session->tc(); - tsk_size_t count = RemoveMember(session, p); - session->senders -= (int32_t)count; - session->members -= (int32_t)count; + } + else if (PacketType(p) == PACKET_BYE) { + session->avg_rtcp_size = (1./16.)*ReceivedPacketSize + (15./16.)*(session->avg_rtcp_size); + + if (TypeOfEvent(e) == EVENT_REPORT) { + double tc = session->tc(); + tsk_size_t count = RemoveMember(session, p); + session->senders -= (int32_t)count; + session->members -= (int32_t)count; #if 0 - if (NewSender(session, p) == tsk_false) { - RemoveSender(p); - session->senders -= 1; - } - if (NewMember(session, p) == tsk_false) { - RemoveMember(p); - session->members -= 1; - } + if (NewSender(session, p) == tsk_false) { + RemoveSender(p); + session->senders -= 1; + } + if (NewMember(session, p) == tsk_false) { + RemoveMember(p); + session->members -= 1; + } #endif - if (session->members < session->pmembers && session->pmembers) { - session->tn = (time_tp)(tc + - (((double) session->members)/(session->pmembers))*(session->tn - tc)); - session->tp = (time_tp)(tc - - (((double) session->members)/(session->pmembers))*(tc - session->tp)); + if (session->members < session->pmembers && session->pmembers) { + session->tn = (time_tp)(tc + + (((double) session->members)/(session->pmembers))*(session->tn - tc)); + session->tp = (time_tp)(tc - + (((double) session->members)/(session->pmembers))*(tc - session->tp)); - /* Reschedule the next report for time tn */ + /* Reschedule the next report for time tn */ - Reschedule(session, session->tn, e); - session->pmembers = session->members; - } + Reschedule(session, session->tn, e); + session->pmembers = session->members; + } - } else if (TypeOfEvent(e) == EVENT_BYE) { - session->members += 1; - } - } + } + else if (TypeOfEvent(e) == EVENT_BYE) { + session->members += 1; + } + } } diff --git a/tinyRTP/src/rtp/trtp_rtp_header.c b/tinyRTP/src/rtp/trtp_rtp_header.c index e833b10..7843d1b 100755 --- a/tinyRTP/src/rtp/trtp_rtp_header.c +++ b/tinyRTP/src/rtp/trtp_rtp_header.c @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -33,49 +33,49 @@ #include "tsk_memory.h" #include "tsk_debug.h" - /* RFC 3550 section 5.1 - RTP Fixed Header Fields - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |V=2|P|X| CC |M| PT | sequence number | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | timestamp | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | synchronization source (SSRC) identifier | - +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ - | contributing source (CSRC) identifiers | - | .... | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ +/* RFC 3550 section 5.1 - RTP Fixed Header Fields + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |V=2|P|X| CC |M| PT | sequence number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | timestamp | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | synchronization source (SSRC) identifier | + +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + | contributing source (CSRC) identifiers | + | .... | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ /* Create new RTP header */ trtp_rtp_header_t* trtp_rtp_header_create_null() { - return tsk_object_new(trtp_rtp_header_def_t); + return tsk_object_new(trtp_rtp_header_def_t); } trtp_rtp_header_t* trtp_rtp_header_create(uint32_t ssrc, uint16_t seq_num, uint32_t timestamp, uint8_t payload_type, tsk_bool_t marker) { - trtp_rtp_header_t* header; - if((header = trtp_rtp_header_create_null())){ - header->version = TRTP_RTP_VERSION; - header->marker = marker ? 1 : 0; - header->payload_type = payload_type; - header->seq_num = seq_num; - header->timestamp = timestamp; - header->ssrc = ssrc; - } - return header; + trtp_rtp_header_t* header; + if((header = trtp_rtp_header_create_null())) { + header->version = TRTP_RTP_VERSION; + header->marker = marker ? 1 : 0; + header->payload_type = payload_type; + header->seq_num = seq_num; + header->timestamp = timestamp; + header->ssrc = ssrc; + } + return header; } /* guess what is the minimum required size to serialize the header */ tsk_size_t trtp_rtp_header_guess_serialbuff_size(const trtp_rtp_header_t *self) { - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return 0; - } - return (TRTP_RTP_HEADER_MIN_SIZE + (self->csrc_count << 2)); + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return 0; + } + return (TRTP_RTP_HEADER_MIN_SIZE + (self->csrc_count << 2)); } /* serialize the RTP header to a buffer */ @@ -83,145 +83,145 @@ tsk_size_t trtp_rtp_header_guess_serialbuff_size(const trtp_rtp_header_t *self) // returns the number of written bytes tsk_size_t trtp_rtp_header_serialize_to(const trtp_rtp_header_t *self, void *buffer, tsk_size_t size) { - tsk_size_t ret; - tsk_size_t i, j; - uint8_t* pbuff = (uint8_t*)buffer; - - if(!buffer || (size < (ret = trtp_rtp_header_guess_serialbuff_size(self)))){ - TSK_DEBUG_ERROR("Invalid parameter"); - return 0; - } - - // Octet-0: version(2), Padding(1), Extension(1), CSRC Count(4) - pbuff[0] = (((uint8_t)self->version)<< 6) | - (((uint8_t)self->padding)<< 5) | - (((uint8_t)self->extension)<< 4) | - ((uint8_t)self->csrc_count); - // Octet-1: Marker(1), Payload Type(7) - pbuff[1] = (((uint8_t)self->marker)<< 7) | - ((uint8_t)self->payload_type); - // Octet-2-3: Sequence number (16) - // *((uint16_t*)&pbuff[2]) = tnet_htons(self->seq_num); - pbuff[2] = self->seq_num >> 8; - pbuff[3] = self->seq_num & 0xFF; - // Octet-4-5-6-7: timestamp (32) - // ((uint32_t*)&pbuff[4]) = tnet_htonl(self->timestamp); - pbuff[4] = self->timestamp >> 24; - pbuff[5] = (self->timestamp >> 16) & 0xFF; - pbuff[6] = (self->timestamp >> 8) & 0xFF; - pbuff[7] = self->timestamp & 0xFF; - // Octet-8-9-10-11: SSRC (32) - //((uint32_t*)&pbuff[8]) = tnet_htonl(self->ssrc); - pbuff[8] = self->ssrc >> 24; - pbuff[9] = (self->ssrc >> 16) & 0xFF; - pbuff[10] = (self->ssrc >> 8) & 0xFF; - pbuff[11] = self->ssrc & 0xFF; - - // Octet-12-13-14-15-****: CSRC - for(i = 0, j = 12; icsrc_count; ++i, ++j){ - // *((uint32_t*)&pbuff[12+i]) = tnet_htonl(self->csrc[i]); - pbuff[j] = self->csrc[i] >> 24; - pbuff[j + 1] = (self->csrc[i] >> 16) & 0xFF; - pbuff[j + 2] = (self->csrc[i] >> 8) & 0xFF; - pbuff[j + 3] = self->csrc[i] & 0xFF; - } - - return ret; + tsk_size_t ret; + tsk_size_t i, j; + uint8_t* pbuff = (uint8_t*)buffer; + + if(!buffer || (size < (ret = trtp_rtp_header_guess_serialbuff_size(self)))) { + TSK_DEBUG_ERROR("Invalid parameter"); + return 0; + } + + // Octet-0: version(2), Padding(1), Extension(1), CSRC Count(4) + pbuff[0] = (((uint8_t)self->version)<< 6) | + (((uint8_t)self->padding)<< 5) | + (((uint8_t)self->extension)<< 4) | + ((uint8_t)self->csrc_count); + // Octet-1: Marker(1), Payload Type(7) + pbuff[1] = (((uint8_t)self->marker)<< 7) | + ((uint8_t)self->payload_type); + // Octet-2-3: Sequence number (16) + // *((uint16_t*)&pbuff[2]) = tnet_htons(self->seq_num); + pbuff[2] = self->seq_num >> 8; + pbuff[3] = self->seq_num & 0xFF; + // Octet-4-5-6-7: timestamp (32) + // ((uint32_t*)&pbuff[4]) = tnet_htonl(self->timestamp); + pbuff[4] = self->timestamp >> 24; + pbuff[5] = (self->timestamp >> 16) & 0xFF; + pbuff[6] = (self->timestamp >> 8) & 0xFF; + pbuff[7] = self->timestamp & 0xFF; + // Octet-8-9-10-11: SSRC (32) + //((uint32_t*)&pbuff[8]) = tnet_htonl(self->ssrc); + pbuff[8] = self->ssrc >> 24; + pbuff[9] = (self->ssrc >> 16) & 0xFF; + pbuff[10] = (self->ssrc >> 8) & 0xFF; + pbuff[11] = self->ssrc & 0xFF; + + // Octet-12-13-14-15-****: CSRC + for(i = 0, j = 12; icsrc_count; ++i, ++j) { + // *((uint32_t*)&pbuff[12+i]) = tnet_htonl(self->csrc[i]); + pbuff[j] = self->csrc[i] >> 24; + pbuff[j + 1] = (self->csrc[i] >> 16) & 0xFF; + pbuff[j + 2] = (self->csrc[i] >> 8) & 0xFF; + pbuff[j + 3] = self->csrc[i] & 0xFF; + } + + return ret; } /** Serialize rtp header object into binary buffer */ tsk_buffer_t* trtp_rtp_header_serialize(const trtp_rtp_header_t *self) { - tsk_buffer_t* buffer; - tsk_size_t size; - - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return tsk_null; - } - - size = trtp_rtp_header_guess_serialbuff_size(self); - if(!(buffer = tsk_buffer_create(tsk_null, size))){ - TSK_DEBUG_ERROR("Failed to create new buffer"); - TSK_OBJECT_SAFE_FREE(buffer); - } - else{ - size = trtp_rtp_header_serialize_to(self, buffer->data, buffer->size); - } - - return buffer; + tsk_buffer_t* buffer; + tsk_size_t size; + + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_null; + } + + size = trtp_rtp_header_guess_serialbuff_size(self); + if(!(buffer = tsk_buffer_create(tsk_null, size))) { + TSK_DEBUG_ERROR("Failed to create new buffer"); + TSK_OBJECT_SAFE_FREE(buffer); + } + else { + size = trtp_rtp_header_serialize_to(self, buffer->data, buffer->size); + } + + return buffer; } /** Deserialize rtp header object from binary buffer */ trtp_rtp_header_t* trtp_rtp_header_deserialize(const void *data, tsk_size_t size) { - trtp_rtp_header_t* header = tsk_null; - const uint8_t* pdata = (const uint8_t*)data; - uint8_t csrc_count, i; - - if(!data){ - TSK_DEBUG_ERROR("Invalid parameter"); - return tsk_null; - } - - if(size version = (*pdata >> 6); - /* Padding (1bit) */ - header->padding = ((*pdata >>5) & 0x01); - /* Extension (1bit) */ - header->extension = ((*pdata >>4) & 0x01); - /* CSRC Count (4bits) */ - header->csrc_count = csrc_count; - // skip octet - ++pdata; - - /* Marker (1bit) */ - header->marker = (*pdata >> 7); - /* Payload Type (7bits) */ - header->payload_type = (*pdata & 0x7F); - // skip octet - ++pdata; - - /* Sequence Number (16bits) */ - header->seq_num = pdata[0] << 8 | pdata[1]; - // skip octets - pdata += 2; - - /* timestamp (32bits) */ - header->timestamp = pdata[0] << 24 | pdata[1] << 16 | pdata[2] << 8 | pdata[3]; - // skip octets - pdata += 4; - - /* synchronization source (SSRC) identifier (32bits) */ - header->ssrc = pdata[0] << 24 | pdata[1] << 16 | pdata[2] << 8 | pdata[3]; - // skip octets - pdata += 4; - - /* contributing source (CSRC) identifiers */ - for(i=0; icsrc[i] = pdata[0] << 24 | pdata[1] << 16 | pdata[2] << 8 | pdata[3]; - } - - return header; + trtp_rtp_header_t* header = tsk_null; + const uint8_t* pdata = (const uint8_t*)data; + uint8_t csrc_count, i; + + if(!data) { + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_null; + } + + if(size version = (*pdata >> 6); + /* Padding (1bit) */ + header->padding = ((*pdata >>5) & 0x01); + /* Extension (1bit) */ + header->extension = ((*pdata >>4) & 0x01); + /* CSRC Count (4bits) */ + header->csrc_count = csrc_count; + // skip octet + ++pdata; + + /* Marker (1bit) */ + header->marker = (*pdata >> 7); + /* Payload Type (7bits) */ + header->payload_type = (*pdata & 0x7F); + // skip octet + ++pdata; + + /* Sequence Number (16bits) */ + header->seq_num = pdata[0] << 8 | pdata[1]; + // skip octets + pdata += 2; + + /* timestamp (32bits) */ + header->timestamp = pdata[0] << 24 | pdata[1] << 16 | pdata[2] << 8 | pdata[3]; + // skip octets + pdata += 4; + + /* synchronization source (SSRC) identifier (32bits) */ + header->ssrc = pdata[0] << 24 | pdata[1] << 16 | pdata[2] << 8 | pdata[3]; + // skip octets + pdata += 4; + + /* contributing source (CSRC) identifiers */ + for(i=0; icsrc[i] = pdata[0] << 24 | pdata[1] << 16 | pdata[2] << 8 | pdata[3]; + } + + return header; } @@ -234,26 +234,25 @@ trtp_rtp_header_t* trtp_rtp_header_deserialize(const void *data, tsk_size_t size // static tsk_object_t* trtp_rtp_header_ctor(tsk_object_t * self, va_list * app) { - trtp_rtp_header_t *header = self; - if(header){ - } - return self; + trtp_rtp_header_t *header = self; + if(header) { + } + return self; } static tsk_object_t* trtp_rtp_header_dtor(tsk_object_t * self) -{ - trtp_rtp_header_t *header = self; - if(header){ - } +{ + trtp_rtp_header_t *header = self; + if(header) { + } - return self; + return self; } -static const tsk_object_def_t trtp_rtp_header_def_s = -{ - sizeof(trtp_rtp_header_t), - trtp_rtp_header_ctor, - trtp_rtp_header_dtor, - tsk_null, +static const tsk_object_def_t trtp_rtp_header_def_s = { + sizeof(trtp_rtp_header_t), + trtp_rtp_header_ctor, + trtp_rtp_header_dtor, + tsk_null, }; const tsk_object_def_t *trtp_rtp_header_def_t = &trtp_rtp_header_def_s; diff --git a/tinyRTP/src/rtp/trtp_rtp_packet.c b/tinyRTP/src/rtp/trtp_rtp_packet.c index dc5c7ea..4d10023 100755 --- a/tinyRTP/src/rtp/trtp_rtp_packet.c +++ b/tinyRTP/src/rtp/trtp_rtp_packet.c @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -38,46 +38,46 @@ /** Create new RTP packet */ trtp_rtp_packet_t* trtp_rtp_packet_create_null() { - return tsk_object_new(trtp_rtp_packet_def_t); + return tsk_object_new(trtp_rtp_packet_def_t); } trtp_rtp_packet_t* trtp_rtp_packet_create(uint32_t ssrc, uint16_t seq_num, uint32_t timestamp, uint8_t payload_type, tsk_bool_t marker) { - trtp_rtp_packet_t* packet; - if((packet = tsk_object_new(trtp_rtp_packet_def_t))){ - packet->header = trtp_rtp_header_create(ssrc, seq_num, timestamp, payload_type, marker); - } - return packet; + trtp_rtp_packet_t* packet; + if((packet = tsk_object_new(trtp_rtp_packet_def_t))) { + packet->header = trtp_rtp_header_create(ssrc, seq_num, timestamp, payload_type, marker); + } + return packet; } trtp_rtp_packet_t* trtp_rtp_packet_create_2(const trtp_rtp_header_t* header) { - trtp_rtp_packet_t* packet; - - if(!header){ - TSK_DEBUG_ERROR("Invalid parameter"); - return tsk_null; - } - if((packet = tsk_object_new(trtp_rtp_packet_def_t))){ - packet->header = tsk_object_ref(TSK_OBJECT(header)); - } - return packet; + trtp_rtp_packet_t* packet; + + if(!header) { + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_null; + } + if((packet = tsk_object_new(trtp_rtp_packet_def_t))) { + packet->header = tsk_object_ref(TSK_OBJECT(header)); + } + return packet; } /* guess what is the minimum required size to serialize the packet */ tsk_size_t trtp_rtp_packet_guess_serialbuff_size(const trtp_rtp_packet_t *self) -{ - tsk_size_t size = 0; - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return 0; - } - size += trtp_rtp_header_guess_serialbuff_size(self->header); - if(self->extension.data && self->extension.size && self->header->extension){ - size += self->extension.size; - } - size += self->payload.size; - return size; +{ + tsk_size_t size = 0; + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return 0; + } + size += trtp_rtp_header_guess_serialbuff_size(self->header); + if(self->extension.data && self->extension.size && self->header->extension) { + size += self->extension.size; + } + size += self->payload.size; + return size; } /* serialize the RTP packet to a buffer */ @@ -85,27 +85,27 @@ tsk_size_t trtp_rtp_packet_guess_serialbuff_size(const trtp_rtp_packet_t *self) // returns the number of written bytes tsk_size_t trtp_rtp_packet_serialize_to(const trtp_rtp_packet_t *self, void* buffer, tsk_size_t size) { - tsk_size_t ret; - tsk_size_t s; - uint8_t* pbuff = (uint8_t*)buffer; - - if(!buffer || (size < (ret = trtp_rtp_packet_guess_serialbuff_size(self)))){ - TSK_DEBUG_ERROR("Invalid parameter"); - return 0; - } - - s = trtp_rtp_header_serialize_to(self->header, pbuff, size); - pbuff += s; - - /* extension */ - if(self->extension.data && self->extension.size && self->header->extension){ - memcpy(pbuff, self->extension.data, self->extension.size); - pbuff += self->extension.size; - } - /* append payload */ - memcpy(pbuff, self->payload.data_const ? self->payload.data_const : self->payload.data, self->payload.size); - - return ret; + tsk_size_t ret; + tsk_size_t s; + uint8_t* pbuff = (uint8_t*)buffer; + + if(!buffer || (size < (ret = trtp_rtp_packet_guess_serialbuff_size(self)))) { + TSK_DEBUG_ERROR("Invalid parameter"); + return 0; + } + + s = trtp_rtp_header_serialize_to(self->header, pbuff, size); + pbuff += s; + + /* extension */ + if(self->extension.data && self->extension.size && self->header->extension) { + memcpy(pbuff, self->extension.data, self->extension.size); + pbuff += self->extension.size; + } + /* append payload */ + memcpy(pbuff, self->payload.data_const ? self->payload.data_const : self->payload.data, self->payload.size); + + return ret; } /** Serialize rtp packet object into binary buffer */ @@ -113,98 +113,100 @@ tsk_size_t trtp_rtp_packet_serialize_to(const trtp_rtp_packet_t *self, void* buf // the padding bytes will not be added to the final buffer size tsk_buffer_t* trtp_rtp_packet_serialize(const trtp_rtp_packet_t *self, tsk_size_t num_bytes_pad) { - tsk_buffer_t* buffer = tsk_null; - tsk_size_t size; - - if(!self || !self->header){ - TSK_DEBUG_ERROR("Invalid parameter"); - return tsk_null; - } - - size = (trtp_rtp_packet_guess_serialbuff_size(self) + num_bytes_pad); - if(size & 0x03) size += (4 - (size & 0x03)); - - if(!(buffer = tsk_buffer_create(tsk_null, size))){ - TSK_DEBUG_ERROR("Failed to create buffer with size = %u", (unsigned)size); - return tsk_null; - } - // shorten the buffer to hide the padding - buffer->size = trtp_rtp_packet_serialize_to(self, buffer->data, buffer->size); - return buffer; + tsk_buffer_t* buffer = tsk_null; + tsk_size_t size; + + if(!self || !self->header) { + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_null; + } + + size = (trtp_rtp_packet_guess_serialbuff_size(self) + num_bytes_pad); + if(size & 0x03) { + size += (4 - (size & 0x03)); + } + + if(!(buffer = tsk_buffer_create(tsk_null, size))) { + TSK_DEBUG_ERROR("Failed to create buffer with size = %u", (unsigned)size); + return tsk_null; + } + // shorten the buffer to hide the padding + buffer->size = trtp_rtp_packet_serialize_to(self, buffer->data, buffer->size); + return buffer; } /** Deserialize rtp packet object from binary buffer */ trtp_rtp_packet_t* trtp_rtp_packet_deserialize(const void *data, tsk_size_t size) { - trtp_rtp_packet_t* packet = tsk_null; - trtp_rtp_header_t *header; - tsk_size_t payload_size; - const uint8_t* pdata = data; - - if(!data){ - TSK_DEBUG_ERROR("Invalid parameter"); - return tsk_null; - } - - if(size< TRTP_RTP_HEADER_MIN_SIZE){ - TSK_DEBUG_ERROR("Too short to contain RTP message"); - return tsk_null; - } - - /* deserialize the RTP header (the packet itsel will be deserialized only if the header deserialization succeed) */ - if(!(header = trtp_rtp_header_deserialize(data, size))){ - TSK_DEBUG_ERROR("Failed to deserialize RTP header"); - return tsk_null; - } - else{ - /* create the packet */ - if(!(packet = trtp_rtp_packet_create_null())){ - TSK_DEBUG_ERROR("Failed to create new RTP packet"); - TSK_OBJECT_SAFE_FREE(header); - return tsk_null; - } - /* set the header */ - packet->header = header, - header = tsk_null; - - /* do not need to check overflow (have been done by trtp_rtp_header_deserialize()) */ - payload_size = (size - TRTP_RTP_HEADER_MIN_SIZE - (packet->header->csrc_count << 2)); - pdata = ((const uint8_t*)data) + (size - payload_size); - - /* RFC 3550 - 5.3.1 RTP Header Extension - If the X bit in the RTP header is one, a variable-length header - extension MUST be appended to the RTP header, following the CSRC list - if present. The header extension contains a 16-bit length field that - counts the number of 32-bit words in the extension, excluding the - four-octet extension header (therefore zero is a valid length). Only - a single extension can be appended to the RTP data header. - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | defined by profile | length | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | header extension | - | .... | - */ - if(packet->header->extension && payload_size>=4 /* extension min-size */){ - packet->extension.size = 4 /* first two 16-bit fields */ + (tnet_ntohs(*((uint16_t*)&pdata[2])) << 2/*words(32-bit)*/); - if((packet->extension.data = tsk_calloc(packet->extension.size, sizeof(uint8_t)))){ - memcpy(packet->extension.data, pdata, packet->extension.size); - } - payload_size -= packet->extension.size; - } - - packet->payload.size = payload_size; - if(payload_size && (packet->payload.data = tsk_calloc(packet->payload.size, sizeof(uint8_t)))){ - memcpy(packet->payload.data, (pdata + packet->extension.size), packet->payload.size); - } - else{ - TSK_DEBUG_ERROR("Failed to allocate new buffer"); - packet->payload.size = 0; - } - } - - return packet; + trtp_rtp_packet_t* packet = tsk_null; + trtp_rtp_header_t *header; + tsk_size_t payload_size; + const uint8_t* pdata = data; + + if(!data) { + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_null; + } + + if(size< TRTP_RTP_HEADER_MIN_SIZE) { + TSK_DEBUG_ERROR("Too short to contain RTP message"); + return tsk_null; + } + + /* deserialize the RTP header (the packet itsel will be deserialized only if the header deserialization succeed) */ + if(!(header = trtp_rtp_header_deserialize(data, size))) { + TSK_DEBUG_ERROR("Failed to deserialize RTP header"); + return tsk_null; + } + else { + /* create the packet */ + if(!(packet = trtp_rtp_packet_create_null())) { + TSK_DEBUG_ERROR("Failed to create new RTP packet"); + TSK_OBJECT_SAFE_FREE(header); + return tsk_null; + } + /* set the header */ + packet->header = header, + header = tsk_null; + + /* do not need to check overflow (have been done by trtp_rtp_header_deserialize()) */ + payload_size = (size - TRTP_RTP_HEADER_MIN_SIZE - (packet->header->csrc_count << 2)); + pdata = ((const uint8_t*)data) + (size - payload_size); + + /* RFC 3550 - 5.3.1 RTP Header Extension + If the X bit in the RTP header is one, a variable-length header + extension MUST be appended to the RTP header, following the CSRC list + if present. The header extension contains a 16-bit length field that + counts the number of 32-bit words in the extension, excluding the + four-octet extension header (therefore zero is a valid length). Only + a single extension can be appended to the RTP data header. + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | defined by profile | length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | header extension | + | .... | + */ + if(packet->header->extension && payload_size>=4 /* extension min-size */) { + packet->extension.size = 4 /* first two 16-bit fields */ + (tnet_ntohs(*((uint16_t*)&pdata[2])) << 2/*words(32-bit)*/); + if((packet->extension.data = tsk_calloc(packet->extension.size, sizeof(uint8_t)))) { + memcpy(packet->extension.data, pdata, packet->extension.size); + } + payload_size -= packet->extension.size; + } + + packet->payload.size = payload_size; + if(payload_size && (packet->payload.data = tsk_calloc(packet->payload.size, sizeof(uint8_t)))) { + memcpy(packet->payload.data, (pdata + packet->extension.size), packet->payload.size); + } + else { + TSK_DEBUG_ERROR("Failed to allocate new buffer"); + packet->payload.size = 0; + } + } + + return packet; } @@ -220,41 +222,44 @@ trtp_rtp_packet_t* trtp_rtp_packet_deserialize(const void *data, tsk_size_t size // static tsk_object_t* trtp_rtp_packet_ctor(tsk_object_t * self, va_list * app) { - trtp_rtp_packet_t *packet = self; - if(packet){ - } - return self; + trtp_rtp_packet_t *packet = self; + if(packet) { + } + return self; } static tsk_object_t* trtp_rtp_packet_dtor(tsk_object_t * self) -{ - trtp_rtp_packet_t *packet = self; - if(packet){ - TSK_OBJECT_SAFE_FREE(packet->header); - TSK_FREE(packet->payload.data); - TSK_FREE(packet->extension.data); - packet->payload.data_const = tsk_null; - } - - return self; +{ + trtp_rtp_packet_t *packet = self; + if(packet) { + TSK_OBJECT_SAFE_FREE(packet->header); + TSK_FREE(packet->payload.data); + TSK_FREE(packet->extension.data); + packet->payload.data_const = tsk_null; + } + + return self; } // comparison must be by sequence number because of the jb static int trtp_rtp_packet_cmp(const tsk_object_t *_p1, const tsk_object_t *_p2) { - const trtp_rtp_packet_t *p1 = _p1; - const trtp_rtp_packet_t *p2 = _p2; - - if(p1 && p1->header && p2 && p2->header){ - return (int)(p1->header->seq_num - p2->header->seq_num); - } - else if(!p1 && !p2) return 0; - else return -1; + const trtp_rtp_packet_t *p1 = _p1; + const trtp_rtp_packet_t *p2 = _p2; + + if(p1 && p1->header && p2 && p2->header) { + return (int)(p1->header->seq_num - p2->header->seq_num); + } + else if(!p1 && !p2) { + return 0; + } + else { + return -1; + } } -static const tsk_object_def_t trtp_rtp_packet_def_s = -{ - sizeof(trtp_rtp_packet_t), - trtp_rtp_packet_ctor, - trtp_rtp_packet_dtor, - trtp_rtp_packet_cmp, +static const tsk_object_def_t trtp_rtp_packet_def_s = { + sizeof(trtp_rtp_packet_t), + trtp_rtp_packet_ctor, + trtp_rtp_packet_dtor, + trtp_rtp_packet_cmp, }; const tsk_object_def_t *trtp_rtp_packet_def_t = &trtp_rtp_packet_def_s; diff --git a/tinyRTP/src/rtp/trtp_rtp_session.c b/tinyRTP/src/rtp/trtp_rtp_session.c index 3ebfe03..919a888 100755 --- a/tinyRTP/src/rtp/trtp_rtp_session.c +++ b/tinyRTP/src/rtp/trtp_rtp_session.c @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * diff --git a/tinyRTP/src/trtp.c b/tinyRTP/src/trtp.c index a0150d9..6581304 100755 --- a/tinyRTP/src/trtp.c +++ b/tinyRTP/src/trtp.c @@ -2,19 +2,19 @@ * Copyright (C) 2012 Doubango Telecom * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * diff --git a/tinyRTP/src/trtp_manager.c b/tinyRTP/src/trtp_manager.c index 70968d3..16aeab1 100755 --- a/tinyRTP/src/trtp_manager.c +++ b/tinyRTP/src/trtp_manager.c @@ -1,19 +1,19 @@ /* * Copyright (C) 2012 Mamadou Diop * Copyright (C) 2012-2013 Doubango Telecom -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -86,381 +86,388 @@ static int _trtp_manager_srtp_start(trtp_manager_t* self, tmedia_srtp_type_t srt /* ======================= Transport callback ========================== */ static int _trtp_transport_layer_cb(const tnet_transport_event_t* e) { - trtp_manager_t* manager = (trtp_manager_t*)e->callback_data; - - switch(e->type){ - case event_data: - { - return _trtp_manager_recv_data(manager, e->data, e->size, e->local_fd, &e->remote_addr); - } - case event_brokenpipe: - { - tnet_fd_t broken_fd; - tnet_socket_t* socket; - tsk_bool_t is_rtcp_socket; - - tsk_safeobj_lock(manager); - broken_fd = e->local_fd; - socket = tsk_null; - is_rtcp_socket = tsk_false; - - if (manager->transport && manager->transport->master && manager->transport->master->fd == broken_fd) { - socket = manager->transport->master; - } - else if (manager->rtcp.local_socket && manager->rtcp.local_socket->fd == broken_fd) { - socket = manager->rtcp.local_socket; - is_rtcp_socket = tsk_true; + trtp_manager_t* manager = (trtp_manager_t*)e->callback_data; + + switch(e->type) { + case event_data: { + return _trtp_manager_recv_data(manager, e->data, e->size, e->local_fd, &e->remote_addr); + } + case event_brokenpipe: { + tnet_fd_t broken_fd; + tnet_socket_t* socket; + tsk_bool_t is_rtcp_socket; + + tsk_safeobj_lock(manager); + broken_fd = e->local_fd; + socket = tsk_null; + is_rtcp_socket = tsk_false; + + if (manager->transport && manager->transport->master && manager->transport->master->fd == broken_fd) { + socket = manager->transport->master; + } + else if (manager->rtcp.local_socket && manager->rtcp.local_socket->fd == broken_fd) { + socket = manager->rtcp.local_socket; + is_rtcp_socket = tsk_true; + } + if (socket) { + tsk_bool_t registered_fd = !!tnet_transport_have_socket(manager->transport, broken_fd); + if (registered_fd) { + tnet_transport_remove_socket(manager->transport, &broken_fd); // broken_fd=-1 + broken_fd = e->local_fd; // restore + } + if (tnet_socket_handle_brokenpipe(socket) == 0) { + if (registered_fd) { + tnet_transport_add_socket(manager->transport, socket->fd, socket->type, tsk_false/* do not take ownership */, tsk_true/* only Meaningful for tls*/, tsk_null); } - if (socket) { - tsk_bool_t registered_fd = !!tnet_transport_have_socket(manager->transport, broken_fd); - if (registered_fd) { - tnet_transport_remove_socket(manager->transport, &broken_fd); // broken_fd=-1 - broken_fd = e->local_fd; // restore - } - if (tnet_socket_handle_brokenpipe(socket) == 0) { - if (registered_fd) { - tnet_transport_add_socket(manager->transport, socket->fd, socket->type, tsk_false/* do not take ownership */, tsk_true/* only Meaningful for tls*/, tsk_null); - } - if (manager->rtcp.session && trtp_rtcp_session_get_local_fd(manager->rtcp.session) == broken_fd) { - trtp_rtcp_session_set_local_fd(manager->rtcp.session, socket->fd); - } - } + if (manager->rtcp.session && trtp_rtcp_session_get_local_fd(manager->rtcp.session) == broken_fd) { + trtp_rtcp_session_set_local_fd(manager->rtcp.session, socket->fd); } - tsk_safeobj_unlock(manager); - return 0; } + } + tsk_safeobj_unlock(manager); + return 0; + } #if HAVE_SRTP - /* DTLS - SRTP events */ - case event_dtls_handshake_succeed: - { - const tnet_socket_t* socket = manager->transport && manager->transport->master && (manager->transport->master->fd == e->local_fd) - ? manager->transport->master - : ((manager->rtcp.local_socket && manager->rtcp.local_socket->fd == e->local_fd) ? manager->rtcp.local_socket : tsk_null); - if(!socket){ - TSK_DEBUG_ERROR("DTLS data from unknown socket"); - break; - } - - if (!manager->dtls.srtp_handshake_succeed) { - manager->dtls.srtp_handshake_succeed = (socket == manager->transport->master); - } - if (!manager->dtls.srtcp_handshake_succeed) { - manager->dtls.srtcp_handshake_succeed = (socket == manager->rtcp.local_socket) || _trtp_manager_is_rtcpmux_active(manager); - } - - TSK_DEBUG_INFO("dtls.srtp_handshake_succeed=%d, dtls.srtcp_handshake_succeed=%d", manager->dtls.srtp_handshake_succeed, manager->dtls.srtcp_handshake_succeed); - TSK_DEBUG_INFO("DTLS-DTLS-SRTP socket [%s]:%d handshake succeed", socket->ip, socket->port); - - if(manager->dtls.srtp_handshake_succeed && manager->dtls.srtcp_handshake_succeed){ - // alter listeners - if(manager->dtls.cb.fun){ - manager->dtls.cb.fun(manager->dtls.cb.usrdata, trtp_srtp_dtls_event_type_handshake_succeed, "DTLS handshake succeed"); - } - } - break; - } - case event_dtls_fingerprint_mismatch: - case event_dtls_handshake_failed: - case event_dtls_error: - { - // alter listeners - if(manager->dtls.cb.fun){ - const char* reason = (e->type == event_dtls_fingerprint_mismatch) - ? "DTLS-SRTP fingerprint mismatch" - : (e->type == event_dtls_handshake_failed ? "DTLS-SRTP handshake failed" : "DTLS error"); - manager->dtls.cb.fun(manager->dtls.cb.usrdata, trtp_srtp_dtls_event_type_handshake_failed, reason); - } - break; - } - case event_dtls_srtp_data: - { - /* KEY||SALT */ - /* rfc 5764 - 4.2. Key Derivation */ - tsk_bool_t is_rtp = (manager->transport->master && manager->transport->master->fd == e->local_fd); - tsk_bool_t is_rtcp = (manager->rtcp.local_socket && manager->rtcp.local_socket->fd == e->local_fd); - if(is_rtp || is_rtcp){ - unsigned int master_salt_length, master_key_length; - + /* DTLS - SRTP events */ + case event_dtls_handshake_succeed: { + const tnet_socket_t* socket = manager->transport && manager->transport->master && (manager->transport->master->fd == e->local_fd) + ? manager->transport->master + : ((manager->rtcp.local_socket && manager->rtcp.local_socket->fd == e->local_fd) ? manager->rtcp.local_socket : tsk_null); + if(!socket) { + TSK_DEBUG_ERROR("DTLS data from unknown socket"); + break; + } + + if (!manager->dtls.srtp_handshake_succeed) { + manager->dtls.srtp_handshake_succeed = (socket == manager->transport->master); + } + if (!manager->dtls.srtcp_handshake_succeed) { + manager->dtls.srtcp_handshake_succeed = (socket == manager->rtcp.local_socket) || _trtp_manager_is_rtcpmux_active(manager); + } + + TSK_DEBUG_INFO("dtls.srtp_handshake_succeed=%d, dtls.srtcp_handshake_succeed=%d", manager->dtls.srtp_handshake_succeed, manager->dtls.srtcp_handshake_succeed); + TSK_DEBUG_INFO("DTLS-DTLS-SRTP socket [%s]:%d handshake succeed", socket->ip, socket->port); + + if(manager->dtls.srtp_handshake_succeed && manager->dtls.srtcp_handshake_succeed) { + // alter listeners + if(manager->dtls.cb.fun) { + manager->dtls.cb.fun(manager->dtls.cb.usrdata, trtp_srtp_dtls_event_type_handshake_succeed, "DTLS handshake succeed"); + } + } + break; + } + case event_dtls_fingerprint_mismatch: + case event_dtls_handshake_failed: + case event_dtls_error: { + // alter listeners + if(manager->dtls.cb.fun) { + const char* reason = (e->type == event_dtls_fingerprint_mismatch) + ? "DTLS-SRTP fingerprint mismatch" + : (e->type == event_dtls_handshake_failed ? "DTLS-SRTP handshake failed" : "DTLS error"); + manager->dtls.cb.fun(manager->dtls.cb.usrdata, trtp_srtp_dtls_event_type_handshake_failed, reason); + } + break; + } + case event_dtls_srtp_data: { + /* KEY||SALT */ + /* rfc 5764 - 4.2. Key Derivation */ + tsk_bool_t is_rtp = (manager->transport->master && manager->transport->master->fd == e->local_fd); + tsk_bool_t is_rtcp = (manager->rtcp.local_socket && manager->rtcp.local_socket->fd == e->local_fd); + if(is_rtp || is_rtcp) { + unsigned int master_salt_length, master_key_length; + #if HAVE_SRTP_PROFILE_GET_MASTER_KEY_LENGTH - master_key_length = srtp_profile_get_master_key_length(manager->dtls.crypto_selected == HMAC_SHA1_32 ? srtp_profile_aes128_cm_sha1_32 : srtp_profile_aes128_cm_sha1_80); + master_key_length = srtp_profile_get_master_key_length(manager->dtls.crypto_selected == HMAC_SHA1_32 ? srtp_profile_aes128_cm_sha1_32 : srtp_profile_aes128_cm_sha1_80); #else - master_key_length = (128 >> 3); // cipher_key_length - rfc5764 4.1.2. SRTP Protection Profiles + master_key_length = (128 >> 3); // cipher_key_length - rfc5764 4.1.2. SRTP Protection Profiles #endif #if HAVE_SRTP_PROFILE_GET_MASTER_SALT_LENGTH - master_salt_length = srtp_profile_get_master_salt_length(manager->dtls.crypto_selected == HMAC_SHA1_32 ? srtp_profile_aes128_cm_sha1_32 : srtp_profile_aes128_cm_sha1_80); + master_salt_length = srtp_profile_get_master_salt_length(manager->dtls.crypto_selected == HMAC_SHA1_32 ? srtp_profile_aes128_cm_sha1_32 : srtp_profile_aes128_cm_sha1_80); #else - master_salt_length = (112 >> 3); // cipher_salt_length - rfc5764 4.1.2. SRTP Protection Profiles + master_salt_length = (112 >> 3); // cipher_salt_length - rfc5764 4.1.2. SRTP Protection Profiles #endif - if(((master_key_length + master_salt_length) << 1) > e->size){ - TSK_DEBUG_ERROR("%d not a valid size for this profile", (int)e->size); - } - else{ - int ret; - const uint8_t* data_ptr = e->data; - const uint8_t *lk, *ls, *rk, *rs; - if(manager->dtls.local.setup == tnet_dtls_setup_passive){ - rk = &data_ptr[0]; - lk = rk + master_key_length; - rs = (lk + master_key_length); - ls = (rs + master_salt_length); - } - else{ - lk = &data_ptr[0]; - rk = lk + master_key_length; - ls = (rk + master_key_length); - rs = (ls + master_salt_length); - } - // set key||salt - if((ret = trtp_srtp_set_key_and_salt_remote(manager, manager->dtls.crypto_selected, rk, master_key_length, rs, master_salt_length, is_rtp))){ - if(manager->dtls.cb.fun) manager->dtls.cb.fun(manager->dtls.cb.usrdata, trtp_srtp_dtls_event_type_fatal_error, "Failed to set remote DTSL-SRTP key||salt"); - return ret; - } - if((ret = trtp_srtp_set_key_and_salt_local(manager, manager->dtls.crypto_selected, lk, master_key_length, ls, master_salt_length, is_rtp))){ - if(manager->dtls.cb.fun) manager->dtls.cb.fun(manager->dtls.cb.usrdata, trtp_srtp_dtls_event_type_fatal_error, "Failed to set local DTSL-SRTP key||salt"); - return ret; - } - - if(is_rtp){ - manager->dtls.srtp_connected = manager->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][manager->dtls.crypto_selected].rtp.initialized; - if(_trtp_manager_is_rtcpmux_active(manager)){ - manager->dtls.srtcp_connected = tsk_true; - } - } - else{ // rtcp - manager->dtls.srtcp_connected = manager->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][manager->dtls.crypto_selected].rtcp.initialized; - } - TSK_DEBUG_INFO("dtls.srtp_connected=%d, dtls.srtcp_connected=%d", manager->dtls.srtp_connected, manager->dtls.srtcp_connected); - - if(manager->dtls.srtp_connected && manager->dtls.srtcp_connected){ - // start DTLS-SRTP - if((ret = _trtp_manager_srtp_start(manager, manager->srtp_type))){ - if(manager->dtls.cb.fun) manager->dtls.cb.fun(manager->dtls.cb.usrdata, trtp_srtp_dtls_event_type_fatal_error, "Failed to set start DTSL-SRTP engine"); - return ret; - } - - TSK_DEBUG_INFO("!!DTLS-SRTP started!!"); - - // alter listeners - if(manager->dtls.cb.fun){ - manager->dtls.cb.fun(manager->dtls.cb.usrdata, trtp_srtp_dtls_event_type_started, "DTLS started"); - } - } - } - } - - break; - } - case event_dtls_srtp_profile_selected: - { - if(manager->transport->master && manager->transport->master->fd == e->local_fd){ - /* Only (SRTP_AES128_CM_SHA1_80 | SRTP_AES128_CM_SHA1_32) because of _trtp_manager_srtp_activate() */ - TSK_DEBUG_INFO("event_dtls_srtp_profile_selected: %.*s", 22, (const char*)e->data); - manager->dtls.crypto_selected = HMAC_SHA1_80; - if(tsk_strnequals(e->data, "SRTP_AES128_CM_SHA1_32", 22)){ - manager->dtls.crypto_selected = HMAC_SHA1_32; - } - } - break; - } + if(((master_key_length + master_salt_length) << 1) > e->size) { + TSK_DEBUG_ERROR("%d not a valid size for this profile", (int)e->size); + } + else { + int ret; + const uint8_t* data_ptr = e->data; + const uint8_t *lk, *ls, *rk, *rs; + if(manager->dtls.local.setup == tnet_dtls_setup_passive) { + rk = &data_ptr[0]; + lk = rk + master_key_length; + rs = (lk + master_key_length); + ls = (rs + master_salt_length); + } + else { + lk = &data_ptr[0]; + rk = lk + master_key_length; + ls = (rk + master_key_length); + rs = (ls + master_salt_length); + } + // set key||salt + if((ret = trtp_srtp_set_key_and_salt_remote(manager, manager->dtls.crypto_selected, rk, master_key_length, rs, master_salt_length, is_rtp))) { + if(manager->dtls.cb.fun) { + manager->dtls.cb.fun(manager->dtls.cb.usrdata, trtp_srtp_dtls_event_type_fatal_error, "Failed to set remote DTSL-SRTP key||salt"); + } + return ret; + } + if((ret = trtp_srtp_set_key_and_salt_local(manager, manager->dtls.crypto_selected, lk, master_key_length, ls, master_salt_length, is_rtp))) { + if(manager->dtls.cb.fun) { + manager->dtls.cb.fun(manager->dtls.cb.usrdata, trtp_srtp_dtls_event_type_fatal_error, "Failed to set local DTSL-SRTP key||salt"); + } + return ret; + } + + if(is_rtp) { + manager->dtls.srtp_connected = manager->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][manager->dtls.crypto_selected].rtp.initialized; + if(_trtp_manager_is_rtcpmux_active(manager)) { + manager->dtls.srtcp_connected = tsk_true; + } + } + else { // rtcp + manager->dtls.srtcp_connected = manager->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][manager->dtls.crypto_selected].rtcp.initialized; + } + TSK_DEBUG_INFO("dtls.srtp_connected=%d, dtls.srtcp_connected=%d", manager->dtls.srtp_connected, manager->dtls.srtcp_connected); + + if(manager->dtls.srtp_connected && manager->dtls.srtcp_connected) { + // start DTLS-SRTP + if((ret = _trtp_manager_srtp_start(manager, manager->srtp_type))) { + if(manager->dtls.cb.fun) { + manager->dtls.cb.fun(manager->dtls.cb.usrdata, trtp_srtp_dtls_event_type_fatal_error, "Failed to set start DTSL-SRTP engine"); + } + return ret; + } + + TSK_DEBUG_INFO("!!DTLS-SRTP started!!"); + + // alter listeners + if(manager->dtls.cb.fun) { + manager->dtls.cb.fun(manager->dtls.cb.usrdata, trtp_srtp_dtls_event_type_started, "DTLS started"); + } + } + } + } + + break; + } + case event_dtls_srtp_profile_selected: { + if(manager->transport->master && manager->transport->master->fd == e->local_fd) { + /* Only (SRTP_AES128_CM_SHA1_80 | SRTP_AES128_CM_SHA1_32) because of _trtp_manager_srtp_activate() */ + TSK_DEBUG_INFO("event_dtls_srtp_profile_selected: %.*s", 22, (const char*)e->data); + manager->dtls.crypto_selected = HMAC_SHA1_80; + if(tsk_strnequals(e->data, "SRTP_AES128_CM_SHA1_32", 22)) { + manager->dtls.crypto_selected = HMAC_SHA1_32; + } + } + break; + } #endif /* HAVE_SRTP */ - case event_connected: - case event_closed: - { - - break; - } - default: - break; - } - return 0; + case event_connected: + case event_closed: { + + break; + } + default: + break; + } + return 0; } static int _trtp_transport_dtls_handshaking_timer_cb(const void* arg, tsk_timer_id_t timer_id) { - int ret = 0; + int ret = 0; #if HAVE_SRTP - trtp_manager_t* manager = (trtp_manager_t*)arg; - - tsk_safeobj_lock(manager); - if (manager->is_started && manager->dtls.timer_hanshaking.id == timer_id && manager->srtp_state == trtp_srtp_state_activated && manager->srtp_type == tmedia_srtp_type_dtls) { - // retry DTLS-SRTP handshaking if srtp-type is DTLS-SRTP and the engine is activated - struct tnet_socket_s* sockets[] = { manager->dtls.srtp_connected ? tsk_null : manager->transport->master , manager->dtls.srtcp_connected ? tsk_null : manager->rtcp.local_socket }; - const struct sockaddr_storage* remote_addrs[] = { &manager->rtp.remote_addr, &manager->rtcp.remote_addr }; - TSK_DEBUG_INFO("_trtp_transport_dtls_handshaking_timer_cb(timeout=%llu)", manager->dtls.timer_hanshaking.timeout); - tnet_transport_dtls_do_handshake(manager->transport, sockets, 2, remote_addrs, 2); - if (manager->is_ice_turn_active) { - // means TURN is active and handshaking data must be sent using this channel - const void* data[] = { tsk_null, tsk_null }; - tsk_size_t size[] = { 0, 0 }; - if ((ret = tnet_transport_dtls_get_handshakingdata(manager->transport, (const struct tnet_socket_s**)sockets, 2, data, size))) { - return ret; - } - if (data[0] && size[0]) { - ret = _trtp_manager_send_turn_dtls_rtp(manager->ice_ctx, data[0], size[0]); - } - if (data[1] && size[1]) { - ret = _trtp_manager_send_turn_dtls_rtcp(manager->ice_ctx, data[1], size[1]); - } - } - // increase timeout - manager->dtls.timer_hanshaking.timeout += (TRTP_DTLS_HANDSHAKING_TIMEOUT >> 1); - if ((manager->dtls.timer_hanshaking.timeout < TRTP_DTLS_HANDSHAKING_TIMEOUT_MAX) && !(manager->dtls.srtp_connected && manager->dtls.srtcp_connected)) { - manager->dtls.timer_hanshaking.id = tsk_timer_manager_schedule(manager->timer_mgr_global, manager->dtls.timer_hanshaking.timeout, _trtp_transport_dtls_handshaking_timer_cb, manager); - } - else { - manager->dtls.timer_hanshaking.id = TSK_INVALID_TIMER_ID; // invalidate timer id (not required but should be done by good citizen) - manager->dtls.timer_hanshaking.timeout = TRTP_DTLS_HANDSHAKING_TIMEOUT; // reset timeout - } - } - tsk_safeobj_unlock(manager); + trtp_manager_t* manager = (trtp_manager_t*)arg; + + tsk_safeobj_lock(manager); + if (manager->is_started && manager->dtls.timer_hanshaking.id == timer_id && manager->srtp_state == trtp_srtp_state_activated && manager->srtp_type == tmedia_srtp_type_dtls) { + // retry DTLS-SRTP handshaking if srtp-type is DTLS-SRTP and the engine is activated + struct tnet_socket_s* sockets[] = { manager->dtls.srtp_connected ? tsk_null : manager->transport->master , manager->dtls.srtcp_connected ? tsk_null : manager->rtcp.local_socket }; + const struct sockaddr_storage* remote_addrs[] = { &manager->rtp.remote_addr, &manager->rtcp.remote_addr }; + TSK_DEBUG_INFO("_trtp_transport_dtls_handshaking_timer_cb(timeout=%llu)", manager->dtls.timer_hanshaking.timeout); + tnet_transport_dtls_do_handshake(manager->transport, sockets, 2, remote_addrs, 2); + if (manager->is_ice_turn_active) { + // means TURN is active and handshaking data must be sent using this channel + const void* data[] = { tsk_null, tsk_null }; + tsk_size_t size[] = { 0, 0 }; + if ((ret = tnet_transport_dtls_get_handshakingdata(manager->transport, (const struct tnet_socket_s**)sockets, 2, data, size))) { + return ret; + } + if (data[0] && size[0]) { + ret = _trtp_manager_send_turn_dtls_rtp(manager->ice_ctx, data[0], size[0]); + } + if (data[1] && size[1]) { + ret = _trtp_manager_send_turn_dtls_rtcp(manager->ice_ctx, data[1], size[1]); + } + } + // increase timeout + manager->dtls.timer_hanshaking.timeout += (TRTP_DTLS_HANDSHAKING_TIMEOUT >> 1); + if ((manager->dtls.timer_hanshaking.timeout < TRTP_DTLS_HANDSHAKING_TIMEOUT_MAX) && !(manager->dtls.srtp_connected && manager->dtls.srtcp_connected)) { + manager->dtls.timer_hanshaking.id = tsk_timer_manager_schedule(manager->timer_mgr_global, manager->dtls.timer_hanshaking.timeout, _trtp_transport_dtls_handshaking_timer_cb, manager); + } + else { + manager->dtls.timer_hanshaking.id = TSK_INVALID_TIMER_ID; // invalidate timer id (not required but should be done by good citizen) + manager->dtls.timer_hanshaking.timeout = TRTP_DTLS_HANDSHAKING_TIMEOUT; // reset timeout + } + } + tsk_safeobj_unlock(manager); #endif - - return ret; + + return ret; } #if 0 static int _trtp_manager_enable_sockets(trtp_manager_t* self) { - int rcv_buf = tmedia_defaults_get_rtpbuff_size(); - int snd_buf = tmedia_defaults_get_rtpbuff_size(); - int ret; - - if(!self->socket_disabled){ - return 0; - } - - if(!self || !self->transport){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - if((ret = setsockopt(self->transport->master->fd, SOL_SOCKET, SO_RCVBUF, (char*)&rcv_buf, sizeof(rcv_buf)))){ - TNET_PRINT_LAST_ERROR("setsockopt(SOL_SOCKET, SO_RCVBUF) has failed with error code %d", ret); - return ret; - } - if((ret = setsockopt(self->transport->master->fd, SOL_SOCKET, SO_SNDBUF, (char*)&snd_buf, sizeof(snd_buf)))){ - TNET_PRINT_LAST_ERROR("setsockopt(SOL_SOCKET, SO_RCVBUF) has failed with error code %d", ret); - return ret; - } - - self->socket_disabled = tsk_false; - return 0; + int rcv_buf = tmedia_defaults_get_rtpbuff_size(); + int snd_buf = tmedia_defaults_get_rtpbuff_size(); + int ret; + + if(!self->socket_disabled) { + return 0; + } + + if(!self || !self->transport) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + if((ret = setsockopt(self->transport->master->fd, SOL_SOCKET, SO_RCVBUF, (char*)&rcv_buf, sizeof(rcv_buf)))) { + TNET_PRINT_LAST_ERROR("setsockopt(SOL_SOCKET, SO_RCVBUF) has failed with error code %d", ret); + return ret; + } + if((ret = setsockopt(self->transport->master->fd, SOL_SOCKET, SO_SNDBUF, (char*)&snd_buf, sizeof(snd_buf)))) { + TNET_PRINT_LAST_ERROR("setsockopt(SOL_SOCKET, SO_RCVBUF) has failed with error code %d", ret); + return ret; + } + + self->socket_disabled = tsk_false; + return 0; } #endif static trtp_manager_t* _trtp_manager_create(tsk_bool_t use_rtcp, const char* local_ip, tsk_bool_t ipv6, tmedia_srtp_type_t srtp_type, tmedia_srtp_mode_t srtp_mode) { - trtp_manager_t* manager; + trtp_manager_t* manager; #if HAVE_SRTP - static tsk_bool_t __strp_initialized = tsk_false; - err_status_t srtp_err; - if(!__strp_initialized){ - if((srtp_err = srtp_init()) != err_status_ok){ - TSK_DEBUG_ERROR("srtp_init() failed with error code = %d", srtp_err); - } - __strp_initialized = (srtp_err == err_status_ok); - } + static tsk_bool_t __strp_initialized = tsk_false; + err_status_t srtp_err; + if(!__strp_initialized) { + if((srtp_err = srtp_init()) != err_status_ok) { + TSK_DEBUG_ERROR("srtp_init() failed with error code = %d", srtp_err); + } + __strp_initialized = (srtp_err == err_status_ok); + } #endif - if((manager = tsk_object_new(trtp_manager_def_t))){ - manager->use_rtcp = use_rtcp; - manager->local_ip = tsk_strdup(local_ip); - manager->use_ipv6 = ipv6; + if((manager = tsk_object_new(trtp_manager_def_t))) { + manager->use_rtcp = use_rtcp; + manager->local_ip = tsk_strdup(local_ip); + manager->use_ipv6 = ipv6; #if HAVE_SRTP - manager->srtp_type = srtp_type; - manager->srtp_mode = srtp_mode; + manager->srtp_type = srtp_type; + manager->srtp_mode = srtp_mode; #endif - manager->rtp.payload_type = 127; - } - return manager; + manager->rtp.payload_type = 127; + } + return manager; } static int _trtp_manager_recv_data(const trtp_manager_t* self, const uint8_t* data_ptr, tsk_size_t data_size, tnet_fd_t local_fd, const struct sockaddr_storage* remote_addr) { - tsk_bool_t is_rtp_rtcp, is_rtcp = tsk_false, is_rtp = tsk_false, is_stun, is_dtls; - - if (!self->is_started) { - TSK_DEBUG_INFO("RTP manager not started yet"); - return 0; - } - - // defined when RTCP-MUX is disabled and RTCP port is equal to "RTP Port + 1" - - // rfc5764 - 5.1.2. Reception - // rfc5761 - 4. Distinguishable RTP and RTCP Packets - - is_rtp_rtcp = (127 < *data_ptr && *data_ptr < 192); - if(is_rtp_rtcp){ - is_stun = is_dtls = tsk_false; - is_rtcp = (self->rtcp.local_socket && self->rtcp.local_socket->fd == local_fd); - if(!is_rtcp && data_size >= 2 && (data_ptr[1] & 0x80)){ - if(is_rtp_rtcp){ - switch((data_ptr[1] & 0x7F)){ - case 64: case 65: - case 72: case 73: case 74: case 75: case 76: - case 77: case 78: - case 79: is_rtcp = tsk_true; break; - } - } - } - is_rtp = !is_rtcp; - } - else{ - is_dtls = !is_rtp_rtcp && (19 < *data_ptr && *data_ptr < 64); - is_stun = !is_dtls && TNET_STUN_BUFF_IS_STUN2(data_ptr, data_size); /* MUST NOT USE: "(*data_ptr < 2)" beacause of "Old VAT" which starts with "0x00" */; - } - - if(is_dtls){ - tnet_socket_t* socket = (self->transport && self->transport->master && self->transport->master->fd == local_fd) - ? self->transport->master - : ((self->rtcp.local_socket && self->rtcp.local_socket->fd == local_fd) ? self->rtcp.local_socket : tsk_null); - if (socket && socket->dtlshandle) { - TSK_DEBUG_INFO("Receive %s-DTLS data on ip=%s and port=%d", (socket == self->transport->master) ? "RTP" : "RTCP", socket->ip, socket->port); - // Handle incoming data then do handshaking - tnet_dtls_socket_handle_incoming_data(socket->dtlshandle, data_ptr, data_size); - if (self->is_ice_turn_active) { - // means TURN is active and handshaking data must be sent using the channel - const void* data = tsk_null; - tsk_size_t size = 0; - if (tnet_transport_dtls_get_handshakingdata(self->transport, (const struct tnet_socket_s**)&socket, 1, &data, &size) == 0) { - if (data && size > 0){ - if (self->rtcp.local_socket == socket) { - /*ret = */_trtp_manager_send_turn_dtls_rtcp(self->ice_ctx, data, size); - } - else { - /*ret = */_trtp_manager_send_turn_dtls_rtp(self->ice_ctx, data, size); - } - } - } - } - } - return 0; - } - - if(is_stun){ - static tsk_bool_t role_conflict = tsk_false; - if(self->ice_ctx){ - return tnet_ice_ctx_recv_stun_message(self->ice_ctx, data_ptr, data_size, local_fd, remote_addr, &role_conflict); - } - return 0; - } - if(is_rtcp){ - if(!self->is_symetric_rtcp_checked && self->is_force_symetric_rtp){ - ((trtp_manager_t*)self)->is_symetric_rtcp_checked = tsk_true; - if(!self->is_ice_neg_ok && remote_addr){ // do not force symetric RTCP is ICE negotiation succeed - TSK_DEBUG_INFO("Using symetric RTCP for [%s]:%d", self->rtcp.remote_ip, self->rtcp.remote_port); - ((trtp_manager_t*)self)->rtcp.remote_addr = *remote_addr; - } - } - - if(self->rtcp.session){ - #if HAVE_SRTP - err_status_t status; - if(self->srtp_ctx_neg_remote){ - srtp_t session = self->srtp_ctx_neg_remote->rtcp.initialized ? self->srtp_ctx_neg_remote->rtcp.session : self->srtp_ctx_neg_remote->rtp.session; - if((status = srtp_unprotect_rtcp(session, (void*)data_ptr, (int*)&data_size)) != err_status_ok){ + tsk_bool_t is_rtp_rtcp, is_rtcp = tsk_false, is_rtp = tsk_false, is_stun, is_dtls; + + if (!self->is_started) { + TSK_DEBUG_INFO("RTP manager not started yet"); + return 0; + } + + // defined when RTCP-MUX is disabled and RTCP port is equal to "RTP Port + 1" + + // rfc5764 - 5.1.2. Reception + // rfc5761 - 4. Distinguishable RTP and RTCP Packets + + is_rtp_rtcp = (127 < *data_ptr && *data_ptr < 192); + if(is_rtp_rtcp) { + is_stun = is_dtls = tsk_false; + is_rtcp = (self->rtcp.local_socket && self->rtcp.local_socket->fd == local_fd); + if(!is_rtcp && data_size >= 2 && (data_ptr[1] & 0x80)) { + if(is_rtp_rtcp) { + switch((data_ptr[1] & 0x7F)) { + case 64: + case 65: + case 72: + case 73: + case 74: + case 75: + case 76: + case 77: + case 78: + case 79: + is_rtcp = tsk_true; + break; + } + } + } + is_rtp = !is_rtcp; + } + else { + is_dtls = !is_rtp_rtcp && (19 < *data_ptr && *data_ptr < 64); + is_stun = !is_dtls && TNET_STUN_BUFF_IS_STUN2(data_ptr, data_size); /* MUST NOT USE: "(*data_ptr < 2)" beacause of "Old VAT" which starts with "0x00" */; + } + + if(is_dtls) { + tnet_socket_t* socket = (self->transport && self->transport->master && self->transport->master->fd == local_fd) + ? self->transport->master + : ((self->rtcp.local_socket && self->rtcp.local_socket->fd == local_fd) ? self->rtcp.local_socket : tsk_null); + if (socket && socket->dtlshandle) { + TSK_DEBUG_INFO("Receive %s-DTLS data on ip=%s and port=%d", (socket == self->transport->master) ? "RTP" : "RTCP", socket->ip, socket->port); + // Handle incoming data then do handshaking + tnet_dtls_socket_handle_incoming_data(socket->dtlshandle, data_ptr, data_size); + if (self->is_ice_turn_active) { + // means TURN is active and handshaking data must be sent using the channel + const void* data = tsk_null; + tsk_size_t size = 0; + if (tnet_transport_dtls_get_handshakingdata(self->transport, (const struct tnet_socket_s**)&socket, 1, &data, &size) == 0) { + if (data && size > 0) { + if (self->rtcp.local_socket == socket) { + /*ret = */_trtp_manager_send_turn_dtls_rtcp(self->ice_ctx, data, size); + } + else { + /*ret = */_trtp_manager_send_turn_dtls_rtp(self->ice_ctx, data, size); + } + } + } + } + } + return 0; + } + + if(is_stun) { + static tsk_bool_t role_conflict = tsk_false; + if(self->ice_ctx) { + return tnet_ice_ctx_recv_stun_message(self->ice_ctx, data_ptr, data_size, local_fd, remote_addr, &role_conflict); + } + return 0; + } + if(is_rtcp) { + if(!self->is_symetric_rtcp_checked && self->is_force_symetric_rtp) { + ((trtp_manager_t*)self)->is_symetric_rtcp_checked = tsk_true; + if(!self->is_ice_neg_ok && remote_addr) { // do not force symetric RTCP is ICE negotiation succeed + TSK_DEBUG_INFO("Using symetric RTCP for [%s]:%d", self->rtcp.remote_ip, self->rtcp.remote_port); + ((trtp_manager_t*)self)->rtcp.remote_addr = *remote_addr; + } + } + + if(self->rtcp.session) { +#if HAVE_SRTP + err_status_t status; + if(self->srtp_ctx_neg_remote) { + srtp_t session = self->srtp_ctx_neg_remote->rtcp.initialized ? self->srtp_ctx_neg_remote->rtcp.session : self->srtp_ctx_neg_remote->rtp.session; + if((status = srtp_unprotect_rtcp(session, (void*)data_ptr, (int*)&data_size)) != err_status_ok) { if (status == err_status_replay_fail) { // replay (because of RTCP-NACK nothing to worry about) TSK_DEBUG_INFO("srtp_unprotect(RTCP) returned 'err_status_replay_fail'"); @@ -470,29 +477,29 @@ static int _trtp_manager_recv_data(const trtp_manager_t* self, const uint8_t* da TSK_DEBUG_ERROR("srtp_unprotect(RTCP) failed with error code=%d", (int)status); return -1; } - } - } - #endif - return trtp_rtcp_session_process_rtcp_in(self->rtcp.session, data_ptr, data_size); - } - TSK_DEBUG_WARN("No RTCP session"); - return 0; - } - if(is_rtp){ - if(!self->is_symetric_rtp_checked && self->is_force_symetric_rtp){ - ((trtp_manager_t*)self)->is_symetric_rtp_checked = tsk_true; - if(!self->is_ice_neg_ok && remote_addr){ // do not force symetric RTP is ICE negotiation succeed - TSK_DEBUG_INFO("Using symetric RTP for [%s]:%d", self->rtp.remote_ip, self->rtp.remote_port); - ((trtp_manager_t*)self)->rtp.remote_addr = *remote_addr; - } - } - - if(self->rtp.cb.fun){ - trtp_rtp_packet_t* packet_rtp = tsk_null; - #if HAVE_SRTP - err_status_t status; - if(self->srtp_ctx_neg_remote){ - if((status = srtp_unprotect(self->srtp_ctx_neg_remote->rtp.session, (void*)data_ptr, (int*)&data_size)) != err_status_ok){ + } + } +#endif + return trtp_rtcp_session_process_rtcp_in(self->rtcp.session, data_ptr, data_size); + } + TSK_DEBUG_WARN("No RTCP session"); + return 0; + } + if(is_rtp) { + if(!self->is_symetric_rtp_checked && self->is_force_symetric_rtp) { + ((trtp_manager_t*)self)->is_symetric_rtp_checked = tsk_true; + if(!self->is_ice_neg_ok && remote_addr) { // do not force symetric RTP is ICE negotiation succeed + TSK_DEBUG_INFO("Using symetric RTP for [%s]:%d", self->rtp.remote_ip, self->rtp.remote_port); + ((trtp_manager_t*)self)->rtp.remote_addr = *remote_addr; + } + } + + if(self->rtp.cb.fun) { + trtp_rtp_packet_t* packet_rtp = tsk_null; +#if HAVE_SRTP + err_status_t status; + if(self->srtp_ctx_neg_remote) { + if((status = srtp_unprotect(self->srtp_ctx_neg_remote->rtp.session, (void*)data_ptr, (int*)&data_size)) != err_status_ok) { if (status == err_status_replay_fail) { // replay (because of RTCP-NACK nothing to worry about) TSK_DEBUG_INFO("srtp_unprotect(RTP) returned 'err_status_replay_fail'"); @@ -502,52 +509,52 @@ static int _trtp_manager_recv_data(const trtp_manager_t* self, const uint8_t* da TSK_DEBUG_ERROR("srtp_unprotect(RTP) failed with error code=%d, seq_num=%u", (int)status, (data_size > 4 ? tnet_ntohs_2(&data_ptr[2]) : 0x0000)); return -1; } - } - } - #endif - if((packet_rtp = trtp_rtp_packet_deserialize(data_ptr, data_size))){ - // update remote SSRC based on received RTP packet - ((trtp_manager_t*)self)->rtp.ssrc.remote = packet_rtp->header->ssrc; - // forward to the callback function (most likely "session_av") - self->rtp.cb.fun(self->rtp.cb.usrdata, packet_rtp); - // forward packet to the RTCP session - if(self->rtcp.session){ - trtp_rtcp_session_process_rtp_in(self->rtcp.session, packet_rtp, data_size); - } - TSK_OBJECT_SAFE_FREE(packet_rtp); - return 0; - } - else{ - TSK_DEBUG_ERROR("RTP packet === NOK"); - return -1; - } - } - return 0; - } - - TSK_DEBUG_INFO("Received unknown packet type"); - return 0; + } + } +#endif + if((packet_rtp = trtp_rtp_packet_deserialize(data_ptr, data_size))) { + // update remote SSRC based on received RTP packet + ((trtp_manager_t*)self)->rtp.ssrc.remote = packet_rtp->header->ssrc; + // forward to the callback function (most likely "session_av") + self->rtp.cb.fun(self->rtp.cb.usrdata, packet_rtp); + // forward packet to the RTCP session + if(self->rtcp.session) { + trtp_rtcp_session_process_rtp_in(self->rtcp.session, packet_rtp, data_size); + } + TSK_OBJECT_SAFE_FREE(packet_rtp); + return 0; + } + else { + TSK_DEBUG_ERROR("RTP packet === NOK"); + return -1; + } + } + return 0; + } + + TSK_DEBUG_INFO("Received unknown packet type"); + return 0; } // Sends DTLS handshaking data record by record to avoid UDP IP fragmentation issues (each record length will be < Length(MTU)) //!\ This is required even if the local transport is TCP/TLS because the relayed (TURN) transport could be UDP static int _trtp_manager_send_turn_dtls(struct tnet_ice_ctx_s* ice_ctx, const void* handshaking_data_ptr, tsk_size_t handshaking_data_size, tsk_bool_t use_rtcp_channel) { - const uint8_t *record_ptr, *records_ptr = handshaking_data_ptr; - tsk_size_t record_size; - int records_len = (int)handshaking_data_size, ret = 0; - int(*_ice_ctx_send_turn_data)(struct tnet_ice_ctx_s* self, const void* data, tsk_size_t size) = use_rtcp_channel ? tnet_ice_ctx_send_turn_rtcp : tnet_ice_ctx_send_turn_rtp; - if (!ice_ctx || !handshaking_data_ptr || !handshaking_data_size) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - while (records_len > 0 && (ret = tnet_dtls_socket_get_record_first(records_ptr, (tsk_size_t)records_len, &record_ptr, &record_size)) == 0) { - ret = _ice_ctx_send_turn_data(ice_ctx, record_ptr, record_size); - - records_len -= (int)record_size; - records_ptr += record_size; - } - return ret; + const uint8_t *record_ptr, *records_ptr = handshaking_data_ptr; + tsk_size_t record_size; + int records_len = (int)handshaking_data_size, ret = 0; + int(*_ice_ctx_send_turn_data)(struct tnet_ice_ctx_s* self, const void* data, tsk_size_t size) = use_rtcp_channel ? tnet_ice_ctx_send_turn_rtcp : tnet_ice_ctx_send_turn_rtp; + if (!ice_ctx || !handshaking_data_ptr || !handshaking_data_size) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + while (records_len > 0 && (ret = tnet_dtls_socket_get_record_first(records_ptr, (tsk_size_t)records_len, &record_ptr, &record_size)) == 0) { + ret = _ice_ctx_send_turn_data(ice_ctx, record_ptr, record_size); + + records_len -= (int)record_size; + records_ptr += record_size; + } + return ret; } #if HAVE_SRTP @@ -559,634 +566,634 @@ If ICE is enabled DTLS-SRTP will not be enabled as the transport is "null" */ static int _trtp_manager_srtp_set_enabled(trtp_manager_t* self, tmedia_srtp_type_t srtp_type, struct tnet_socket_s** sockets, tsk_size_t count, tsk_bool_t enabled) { - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if((self->srtp_mode == tmedia_srtp_mode_optional || self->srtp_mode == tmedia_srtp_mode_mandatory)){ - int ret; - if(enabled){ - if(srtp_type & tmedia_srtp_type_sdes){ - trtp_srtp_ctx_init( - &self->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_80], - 1, - HMAC_SHA1_80, - self->rtp.ssrc.local - ); - trtp_srtp_ctx_init( - &self->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_32], - 2, - HMAC_SHA1_32, - self->rtp.ssrc.local - ); - } - - if(srtp_type & tmedia_srtp_type_dtls){ - /* - Enables DTLS on the transport without activating it on the sockets - Enabling DTLS will allow us to get the certificate fingerprints for negotiation - At this stage the sockets are not ready to send DTLS datagrams -> Good for ICE negotiation - */ - if(self->transport){ - if((ret = tnet_transport_dtls_set_enabled(self->transport, enabled, tsk_null, 0))){ - return ret; - } - if((ret = trtp_manager_set_dtls_certs(self, self->dtls.file_ca, self->dtls.file_pbk, self->dtls.file_pvk, self->dtls.cert_verif))){ - return ret; - } - self->dtls.state = trtp_srtp_state_enabled; - } - else{ - self->dtls.enable_postponed = tsk_true; - } - } - self->srtp_state = trtp_srtp_state_enabled; - } - else { - if (srtp_type & tmedia_srtp_type_dtls) { - if (self->transport) { - ret = tnet_transport_dtls_set_enabled(self->transport, tsk_false, sockets, count); - } - self->dtls.state = trtp_srtp_state_none; - self->dtls.enable_postponed = tsk_false; - self->dtls.srtp_connected = self->dtls.srtp_handshake_succeed = tsk_false; - self->dtls.srtcp_connected = self->dtls.srtcp_handshake_succeed = tsk_false; - } - - // SRTP context is used by both DTLS and SDES -> only destroy them if requested to be disabled on both - if((~srtp_type & self->srtp_type) == tmedia_srtp_type_none){ - trtp_srtp_ctx_deinit(&self->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][0]); - trtp_srtp_ctx_deinit(&self->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][1]); - self->srtp_ctx_neg_local = tsk_null; - self->srtp_ctx_neg_remote = tsk_null; - self->srtp_state = trtp_srtp_state_none; - // Reset SRTP session to the RTCP session manager - if (self->rtcp.session) { - trtp_rtcp_session_set_srtp_sess(self->rtcp.session, tsk_null); - } - } - } - } - - return 0; + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if((self->srtp_mode == tmedia_srtp_mode_optional || self->srtp_mode == tmedia_srtp_mode_mandatory)) { + int ret; + if(enabled) { + if(srtp_type & tmedia_srtp_type_sdes) { + trtp_srtp_ctx_init( + &self->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_80], + 1, + HMAC_SHA1_80, + self->rtp.ssrc.local + ); + trtp_srtp_ctx_init( + &self->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_32], + 2, + HMAC_SHA1_32, + self->rtp.ssrc.local + ); + } + + if(srtp_type & tmedia_srtp_type_dtls) { + /* + Enables DTLS on the transport without activating it on the sockets + Enabling DTLS will allow us to get the certificate fingerprints for negotiation + At this stage the sockets are not ready to send DTLS datagrams -> Good for ICE negotiation + */ + if(self->transport) { + if((ret = tnet_transport_dtls_set_enabled(self->transport, enabled, tsk_null, 0))) { + return ret; + } + if((ret = trtp_manager_set_dtls_certs(self, self->dtls.file_ca, self->dtls.file_pbk, self->dtls.file_pvk, self->dtls.cert_verif))) { + return ret; + } + self->dtls.state = trtp_srtp_state_enabled; + } + else { + self->dtls.enable_postponed = tsk_true; + } + } + self->srtp_state = trtp_srtp_state_enabled; + } + else { + if (srtp_type & tmedia_srtp_type_dtls) { + if (self->transport) { + ret = tnet_transport_dtls_set_enabled(self->transport, tsk_false, sockets, count); + } + self->dtls.state = trtp_srtp_state_none; + self->dtls.enable_postponed = tsk_false; + self->dtls.srtp_connected = self->dtls.srtp_handshake_succeed = tsk_false; + self->dtls.srtcp_connected = self->dtls.srtcp_handshake_succeed = tsk_false; + } + + // SRTP context is used by both DTLS and SDES -> only destroy them if requested to be disabled on both + if((~srtp_type & self->srtp_type) == tmedia_srtp_type_none) { + trtp_srtp_ctx_deinit(&self->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][0]); + trtp_srtp_ctx_deinit(&self->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][1]); + self->srtp_ctx_neg_local = tsk_null; + self->srtp_ctx_neg_remote = tsk_null; + self->srtp_state = trtp_srtp_state_none; + // Reset SRTP session to the RTCP session manager + if (self->rtcp.session) { + trtp_rtcp_session_set_srtp_sess(self->rtcp.session, tsk_null); + } + } + } + } + + return 0; } static int _trtp_manager_srtp_activate(trtp_manager_t* self, tmedia_srtp_type_t srtp_type) { - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if(srtp_type != tmedia_srtp_type_none && (self->srtp_mode == tmedia_srtp_mode_optional || self->srtp_mode == tmedia_srtp_mode_mandatory)){ - int ret; - if(self->srtp_state < trtp_srtp_state_enabled){ - TSK_DEBUG_ERROR("SRTP engine not enabled yet"); - return -2; - } - if((srtp_type & tmedia_srtp_type_dtls) && (self->dtls.state >= trtp_srtp_state_enabled || self->dtls.enable_postponed)){ - /* - Activates DTLS on the transport and on both RTP and RTCP sockets - At this stage the sockets are ready to send/recv DTLS datagrams - */ - struct tnet_socket_s* sockets[] = { self->transport->master , self->rtcp.local_socket }; - const struct sockaddr_storage* remote_addrs[] = { &self->rtp.remote_addr, &self->rtcp.remote_addr }; - tsk_bool_t store_handshakingdata[] = { self->is_ice_turn_active, self->is_ice_turn_active }; - - // check if DTLS-SRTP enabling was postponed because the net transport was not ready (could happen if ICE is ON) - if(self->dtls.enable_postponed){ - if ((ret = _trtp_manager_srtp_set_enabled(self, self->srtp_type, sockets, sizeof(sockets) / sizeof(sockets[0]), tsk_true))) { - return ret; - } - self->dtls.enable_postponed = tsk_false; - } - - // activate "use_srtp" (rfc5764 section 4.1) on the transport - // this should be done before enabling DTLS sockets to be sure that newly created/enabled ones will use "use_srtp" extension - if((ret = tnet_transport_dtls_use_srtp(self->transport, "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32", sockets, 2))){ - return ret; - } - // enabling DTLS on the sockets will create the "dtlshandle" field and change the type from UDP to DTLS - if((ret = tnet_transport_dtls_set_enabled(self->transport, tsk_true, sockets, 2))){ - return ret; - } - - /* At this step the DTLS "dtlshandle" is created and the socket types changed from UDP to DTLS */ - - // pass the remote certificate fingerprint to both SRTP and SRTCP sockets - // the fingerprint will be verified if this option is enabled on the SSL context - // we'll be notified via the callback if there are fingerprint mismatch after the begining of the handshaking - if((ret = tnet_transport_dtls_set_remote_fingerprint(self->transport, &self->dtls.remote.fp, self->dtls.remote.fp_hash, sockets, 2))){ - return ret; - } - // setting the "setup" allow each DTLS socket to know if it's a client or server - // setup="active" means it's up to us to send the "DTLS client hello" message (otherwise "server hello" will be sent) - if((ret = tnet_transport_dtls_set_setup(self->transport, self->dtls.local.setup, sockets, 2))){ - return ret; - } - // whether to send DTLS handshaking data using the provided sockets or TURN session - if ((ret = tnet_transport_dtls_set_store_handshakingdata(self->transport, store_handshakingdata[0], sockets, 2))) { - return ret; - } - // start handshaking process (will do nothing if already completed) - if ((ret = tnet_transport_dtls_do_handshake(self->transport, sockets, 2, remote_addrs, 2))) { - return ret; - } - if (store_handshakingdata[0]) { - // means TURN is active and handshaking data must be sent using the channel - const void* data[] = { tsk_null, tsk_null }; - tsk_size_t size[] = { 0, 0 }; - if ((ret = tnet_transport_dtls_get_handshakingdata(self->transport, (const struct tnet_socket_s**)sockets, 2, data, size))) { - return ret; - } - if (data[0] && size[0]) { - ret = tnet_ice_ctx_send_turn_rtp(self->ice_ctx, data[0], size[0]); - } - if (data[1] && size[1]) { - ret = tnet_ice_ctx_send_turn_rtcp(self->ice_ctx, data[1], size[1]); - } - } - - self->dtls.state = trtp_srtp_state_activated; - } - - self->srtp_state = trtp_srtp_state_activated; - - // SDES-SRTP could be started right now while DTLS requires the handshaking to terminate - if (srtp_type & tmedia_srtp_type_sdes) { - return _trtp_manager_srtp_start(self, self->srtp_type); - } - } - return 0; + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if(srtp_type != tmedia_srtp_type_none && (self->srtp_mode == tmedia_srtp_mode_optional || self->srtp_mode == tmedia_srtp_mode_mandatory)) { + int ret; + if(self->srtp_state < trtp_srtp_state_enabled) { + TSK_DEBUG_ERROR("SRTP engine not enabled yet"); + return -2; + } + if((srtp_type & tmedia_srtp_type_dtls) && (self->dtls.state >= trtp_srtp_state_enabled || self->dtls.enable_postponed)) { + /* + Activates DTLS on the transport and on both RTP and RTCP sockets + At this stage the sockets are ready to send/recv DTLS datagrams + */ + struct tnet_socket_s* sockets[] = { self->transport->master , self->rtcp.local_socket }; + const struct sockaddr_storage* remote_addrs[] = { &self->rtp.remote_addr, &self->rtcp.remote_addr }; + tsk_bool_t store_handshakingdata[] = { self->is_ice_turn_active, self->is_ice_turn_active }; + + // check if DTLS-SRTP enabling was postponed because the net transport was not ready (could happen if ICE is ON) + if(self->dtls.enable_postponed) { + if ((ret = _trtp_manager_srtp_set_enabled(self, self->srtp_type, sockets, sizeof(sockets) / sizeof(sockets[0]), tsk_true))) { + return ret; + } + self->dtls.enable_postponed = tsk_false; + } + + // activate "use_srtp" (rfc5764 section 4.1) on the transport + // this should be done before enabling DTLS sockets to be sure that newly created/enabled ones will use "use_srtp" extension + if((ret = tnet_transport_dtls_use_srtp(self->transport, "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32", sockets, 2))) { + return ret; + } + // enabling DTLS on the sockets will create the "dtlshandle" field and change the type from UDP to DTLS + if((ret = tnet_transport_dtls_set_enabled(self->transport, tsk_true, sockets, 2))) { + return ret; + } + + /* At this step the DTLS "dtlshandle" is created and the socket types changed from UDP to DTLS */ + + // pass the remote certificate fingerprint to both SRTP and SRTCP sockets + // the fingerprint will be verified if this option is enabled on the SSL context + // we'll be notified via the callback if there are fingerprint mismatch after the begining of the handshaking + if((ret = tnet_transport_dtls_set_remote_fingerprint(self->transport, &self->dtls.remote.fp, self->dtls.remote.fp_hash, sockets, 2))) { + return ret; + } + // setting the "setup" allow each DTLS socket to know if it's a client or server + // setup="active" means it's up to us to send the "DTLS client hello" message (otherwise "server hello" will be sent) + if((ret = tnet_transport_dtls_set_setup(self->transport, self->dtls.local.setup, sockets, 2))) { + return ret; + } + // whether to send DTLS handshaking data using the provided sockets or TURN session + if ((ret = tnet_transport_dtls_set_store_handshakingdata(self->transport, store_handshakingdata[0], sockets, 2))) { + return ret; + } + // start handshaking process (will do nothing if already completed) + if ((ret = tnet_transport_dtls_do_handshake(self->transport, sockets, 2, remote_addrs, 2))) { + return ret; + } + if (store_handshakingdata[0]) { + // means TURN is active and handshaking data must be sent using the channel + const void* data[] = { tsk_null, tsk_null }; + tsk_size_t size[] = { 0, 0 }; + if ((ret = tnet_transport_dtls_get_handshakingdata(self->transport, (const struct tnet_socket_s**)sockets, 2, data, size))) { + return ret; + } + if (data[0] && size[0]) { + ret = tnet_ice_ctx_send_turn_rtp(self->ice_ctx, data[0], size[0]); + } + if (data[1] && size[1]) { + ret = tnet_ice_ctx_send_turn_rtcp(self->ice_ctx, data[1], size[1]); + } + } + + self->dtls.state = trtp_srtp_state_activated; + } + + self->srtp_state = trtp_srtp_state_activated; + + // SDES-SRTP could be started right now while DTLS requires the handshaking to terminate + if (srtp_type & tmedia_srtp_type_sdes) { + return _trtp_manager_srtp_start(self, self->srtp_type); + } + } + return 0; } static int _trtp_manager_srtp_start(trtp_manager_t* self, tmedia_srtp_type_t srtp_type) { - const trtp_srtp_ctx_xt *ctx_remote, *ctx_local; - tsk_bool_t use_different_keys; - - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - if(self->srtp_state < trtp_srtp_state_activated){ - TSK_DEBUG_ERROR("SRTP engine not activated yet"); - return -2; - } - - ctx_remote = self->srtp_contexts[TRTP_SRTP_LINE_IDX_REMOTE][HMAC_SHA1_80].rtp.initialized - ? &self->srtp_contexts[TRTP_SRTP_LINE_IDX_REMOTE][HMAC_SHA1_80] - : &self->srtp_contexts[TRTP_SRTP_LINE_IDX_REMOTE][HMAC_SHA1_32]; - - // dtls uses different keys for rtp and srtp which is not the case for sdes - use_different_keys = !_trtp_manager_is_rtcpmux_active(self) && ((srtp_type & tmedia_srtp_type_dtls) == tmedia_srtp_type_dtls); - TSK_DEBUG_INFO("srtp_use_different_keys=%s", use_different_keys ? "true" : "false"); - - if(!ctx_remote->rtp.initialized || (use_different_keys && !ctx_remote->rtcp.initialized)){ - TSK_DEBUG_ERROR("SRTP remote context not initialized: Not expected at this state"); - return -2; - } - - // use same crypto type on both sides - ctx_local = &self->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][(int32_t)ctx_remote->rtp.crypto_type]; - if(!ctx_local->rtp.initialized || (use_different_keys && !ctx_local->rtcp.initialized)){ - TSK_DEBUG_ERROR("SRTP local context not initialized: Not expected at this state"); - return -2; - } - - // update negotiated crypto contexts used to encrypt()/decrypt() SRTP data - self->srtp_ctx_neg_remote = ctx_remote; - self->srtp_ctx_neg_local = ctx_local; - - self->srtp_state = trtp_srtp_state_started; - if(self->dtls.state >= trtp_srtp_state_activated){ - // this means the DTLS-SRTP is the active type intead of SDES - self->dtls.state = trtp_srtp_state_started; - } - - // Pass SRTP session to the RTCP session manager - trtp_rtcp_session_set_srtp_sess( - self->rtcp.session, - self->srtp_ctx_neg_local ? (use_different_keys ? &self->srtp_ctx_neg_local->rtcp.session : &self->srtp_ctx_neg_local->rtp.session) : tsk_null - ); - - /* At this step we are able to encrypt()/decrypt() SRTP data */ - - return 0; + const trtp_srtp_ctx_xt *ctx_remote, *ctx_local; + tsk_bool_t use_different_keys; + + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + if(self->srtp_state < trtp_srtp_state_activated) { + TSK_DEBUG_ERROR("SRTP engine not activated yet"); + return -2; + } + + ctx_remote = self->srtp_contexts[TRTP_SRTP_LINE_IDX_REMOTE][HMAC_SHA1_80].rtp.initialized + ? &self->srtp_contexts[TRTP_SRTP_LINE_IDX_REMOTE][HMAC_SHA1_80] + : &self->srtp_contexts[TRTP_SRTP_LINE_IDX_REMOTE][HMAC_SHA1_32]; + + // dtls uses different keys for rtp and srtp which is not the case for sdes + use_different_keys = !_trtp_manager_is_rtcpmux_active(self) && ((srtp_type & tmedia_srtp_type_dtls) == tmedia_srtp_type_dtls); + TSK_DEBUG_INFO("srtp_use_different_keys=%s", use_different_keys ? "true" : "false"); + + if(!ctx_remote->rtp.initialized || (use_different_keys && !ctx_remote->rtcp.initialized)) { + TSK_DEBUG_ERROR("SRTP remote context not initialized: Not expected at this state"); + return -2; + } + + // use same crypto type on both sides + ctx_local = &self->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][(int32_t)ctx_remote->rtp.crypto_type]; + if(!ctx_local->rtp.initialized || (use_different_keys && !ctx_local->rtcp.initialized)) { + TSK_DEBUG_ERROR("SRTP local context not initialized: Not expected at this state"); + return -2; + } + + // update negotiated crypto contexts used to encrypt()/decrypt() SRTP data + self->srtp_ctx_neg_remote = ctx_remote; + self->srtp_ctx_neg_local = ctx_local; + + self->srtp_state = trtp_srtp_state_started; + if(self->dtls.state >= trtp_srtp_state_activated) { + // this means the DTLS-SRTP is the active type intead of SDES + self->dtls.state = trtp_srtp_state_started; + } + + // Pass SRTP session to the RTCP session manager + trtp_rtcp_session_set_srtp_sess( + self->rtcp.session, + self->srtp_ctx_neg_local ? (use_different_keys ? &self->srtp_ctx_neg_local->rtcp.session : &self->srtp_ctx_neg_local->rtp.session) : tsk_null + ); + + /* At this step we are able to encrypt()/decrypt() SRTP data */ + + return 0; } #endif /* HAVE_SRTP */ static int _trtp_manager_ice_init(trtp_manager_t* self) { - int ret = 0; - const tnet_ice_candidate_t *candidate_offer, *candidate_answer_src, *candidate_answer_dest; - struct tnet_socket_s *rtp_socket = tsk_null; - - if (!self || !self->ice_ctx) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - if (!self->transport) { - // get rtp nominated symetric candidates - ret = tnet_ice_ctx_get_nominated_symetric_candidates(self->ice_ctx, TNET_ICE_CANDIDATE_COMPID_RTP, - &candidate_offer, &candidate_answer_src, &candidate_answer_dest); - self->is_ice_neg_ok = (ret == 0 && candidate_offer && candidate_answer_src && candidate_answer_dest); - self->is_ice_turn_active = self->is_ice_neg_ok && tnet_ice_ctx_is_turn_rtp_active(self->ice_ctx); - if (!self->is_ice_neg_ok) { - // If this code is called this means that ICE negotiation has failed - // This is not really an error because it could happen if the remote peer is not an ICE agent or is an ICE-lite - // in this case, use the first offered candidate which is the best one and already used in the "c=" line - if (!(candidate_offer = tnet_ice_ctx_get_local_candidate_first(self->ice_ctx))) { - // Must never happen as we always have at least one local "host" candidate - TSK_DEBUG_ERROR("ICE context not ready"); - ret = -3; - goto bail; - } - } - - // Get RTP socket - if (self->is_ice_turn_active && candidate_offer->turn.ss) { - if ((ret = tnet_turn_session_get_socket_local(candidate_offer->turn.ss, &rtp_socket))) { - goto bail; - } - } - else { - rtp_socket = tsk_object_ref(candidate_offer->socket); - } - - // create transport - if (!(self->transport = tnet_transport_create_2(rtp_socket, TRTP_TRANSPORT_NAME))) { - TSK_DEBUG_ERROR("Failed to create transport(%s:%u)", rtp_socket->ip, rtp_socket->port); - ret = -4; - goto bail; - } - // set rtp local and remote IPs and ports - if (candidate_answer_dest) { // could be "null" if remote peer is ICE-lite - tsk_strupdate(&self->rtp.remote_ip, candidate_answer_dest->connection_addr); - self->rtp.remote_port = candidate_answer_dest->port; - tsk_strupdate(&self->rtp.public_ip, candidate_offer->connection_addr); - self->rtp.public_port = candidate_offer->port; - } - - // get rtp nominated symetric candidates - if (self->use_rtcp) { - ret = tnet_ice_ctx_get_nominated_symetric_candidates(self->ice_ctx, TNET_ICE_CANDIDATE_COMPID_RTCP, - &candidate_offer, &candidate_answer_src, &candidate_answer_dest); - if (ret == 0 && candidate_offer && candidate_answer_src && candidate_answer_dest) { - // set rtp local and remote IPs and ports - tsk_strupdate(&self->rtcp.remote_ip, candidate_answer_dest->connection_addr); - self->rtcp.remote_port = candidate_answer_dest->port; - tsk_strupdate(&self->rtcp.public_ip, candidate_offer->connection_addr); - self->rtcp.public_port = candidate_offer->port; - TSK_OBJECT_SAFE_FREE(self->rtcp.local_socket); - // Get RTCP socket - if (self->is_ice_turn_active && candidate_offer->turn.ss) { - ret = tnet_turn_session_get_socket_local(candidate_offer->turn.ss, &self->rtcp.local_socket); - if (ret) { - goto bail; - } - } - else { - self->rtcp.local_socket = tsk_object_ref(candidate_offer->socket); - } - } - } - } - - // set callback functions - ret = tnet_transport_set_callback(self->transport, _trtp_transport_layer_cb, self); // NetTransport -> RtpManager - ret = tnet_ice_ctx_rtp_callback(self->ice_ctx, (tnet_ice_rtp_callback_f)_trtp_manager_recv_data, self); // ICE -> RtpManager + int ret = 0; + const tnet_ice_candidate_t *candidate_offer, *candidate_answer_src, *candidate_answer_dest; + struct tnet_socket_s *rtp_socket = tsk_null; + + if (!self || !self->ice_ctx) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + if (!self->transport) { + // get rtp nominated symetric candidates + ret = tnet_ice_ctx_get_nominated_symetric_candidates(self->ice_ctx, TNET_ICE_CANDIDATE_COMPID_RTP, + &candidate_offer, &candidate_answer_src, &candidate_answer_dest); + self->is_ice_neg_ok = (ret == 0 && candidate_offer && candidate_answer_src && candidate_answer_dest); + self->is_ice_turn_active = self->is_ice_neg_ok && tnet_ice_ctx_is_turn_rtp_active(self->ice_ctx); + if (!self->is_ice_neg_ok) { + // If this code is called this means that ICE negotiation has failed + // This is not really an error because it could happen if the remote peer is not an ICE agent or is an ICE-lite + // in this case, use the first offered candidate which is the best one and already used in the "c=" line + if (!(candidate_offer = tnet_ice_ctx_get_local_candidate_first(self->ice_ctx))) { + // Must never happen as we always have at least one local "host" candidate + TSK_DEBUG_ERROR("ICE context not ready"); + ret = -3; + goto bail; + } + } + + // Get RTP socket + if (self->is_ice_turn_active && candidate_offer->turn.ss) { + if ((ret = tnet_turn_session_get_socket_local(candidate_offer->turn.ss, &rtp_socket))) { + goto bail; + } + } + else { + rtp_socket = tsk_object_ref(candidate_offer->socket); + } + + // create transport + if (!(self->transport = tnet_transport_create_2(rtp_socket, TRTP_TRANSPORT_NAME))) { + TSK_DEBUG_ERROR("Failed to create transport(%s:%u)", rtp_socket->ip, rtp_socket->port); + ret = -4; + goto bail; + } + // set rtp local and remote IPs and ports + if (candidate_answer_dest) { // could be "null" if remote peer is ICE-lite + tsk_strupdate(&self->rtp.remote_ip, candidate_answer_dest->connection_addr); + self->rtp.remote_port = candidate_answer_dest->port; + tsk_strupdate(&self->rtp.public_ip, candidate_offer->connection_addr); + self->rtp.public_port = candidate_offer->port; + } + + // get rtp nominated symetric candidates + if (self->use_rtcp) { + ret = tnet_ice_ctx_get_nominated_symetric_candidates(self->ice_ctx, TNET_ICE_CANDIDATE_COMPID_RTCP, + &candidate_offer, &candidate_answer_src, &candidate_answer_dest); + if (ret == 0 && candidate_offer && candidate_answer_src && candidate_answer_dest) { + // set rtp local and remote IPs and ports + tsk_strupdate(&self->rtcp.remote_ip, candidate_answer_dest->connection_addr); + self->rtcp.remote_port = candidate_answer_dest->port; + tsk_strupdate(&self->rtcp.public_ip, candidate_offer->connection_addr); + self->rtcp.public_port = candidate_offer->port; + TSK_OBJECT_SAFE_FREE(self->rtcp.local_socket); + // Get RTCP socket + if (self->is_ice_turn_active && candidate_offer->turn.ss) { + ret = tnet_turn_session_get_socket_local(candidate_offer->turn.ss, &self->rtcp.local_socket); + if (ret) { + goto bail; + } + } + else { + self->rtcp.local_socket = tsk_object_ref(candidate_offer->socket); + } + } + } + } + + // set callback functions + ret = tnet_transport_set_callback(self->transport, _trtp_transport_layer_cb, self); // NetTransport -> RtpManager + ret = tnet_ice_ctx_rtp_callback(self->ice_ctx, (tnet_ice_rtp_callback_f)_trtp_manager_recv_data, self); // ICE -> RtpManager bail: - TSK_OBJECT_SAFE_FREE(rtp_socket); - return ret; + TSK_OBJECT_SAFE_FREE(rtp_socket); + return ret; } /** Create RTP/RTCP manager */ trtp_manager_t* trtp_manager_create(tsk_bool_t use_rtcp, const char* local_ip, tsk_bool_t ipv6, tmedia_srtp_type_t srtp_type, tmedia_srtp_mode_t srtp_mode) { - trtp_manager_t* manager; - if((manager = _trtp_manager_create(use_rtcp, local_ip, ipv6, srtp_type, srtp_mode))){ - } - return manager; + trtp_manager_t* manager; + if((manager = _trtp_manager_create(use_rtcp, local_ip, ipv6, srtp_type, srtp_mode))) { + } + return manager; } /** Create RTP/RTCP manager */ trtp_manager_t* trtp_manager_create_2(struct tnet_ice_ctx_s* ice_ctx, tmedia_srtp_type_t srtp_type, tmedia_srtp_mode_t srtp_mode) { - trtp_manager_t* manager; - const char* local_ip; - tsk_bool_t use_ipv6, use_rtcp; - - if(!ice_ctx){ - TSK_DEBUG_ERROR("Invalid parameter"); - return tsk_null; - } - - local_ip = (use_ipv6 = tnet_ice_ctx_use_ipv6(ice_ctx)) ? "::1" : "127.0.0.1"; - use_rtcp = tnet_ice_ctx_use_rtcp(ice_ctx); - - if((manager = _trtp_manager_create(use_rtcp, local_ip, use_ipv6, srtp_type, srtp_mode))){ - manager->ice_ctx = tsk_object_ref(ice_ctx); - } - return manager; + trtp_manager_t* manager; + const char* local_ip; + tsk_bool_t use_ipv6, use_rtcp; + + if(!ice_ctx) { + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_null; + } + + local_ip = (use_ipv6 = tnet_ice_ctx_use_ipv6(ice_ctx)) ? "::1" : "127.0.0.1"; + use_rtcp = tnet_ice_ctx_use_rtcp(ice_ctx); + + if((manager = _trtp_manager_create(use_rtcp, local_ip, use_ipv6, srtp_type, srtp_mode))) { + manager->ice_ctx = tsk_object_ref(ice_ctx); + } + return manager; } int trtp_manager_set_ice_ctx(trtp_manager_t* self, struct tnet_ice_ctx_s* ice_ctx) { - if(!self){ - TSK_DEBUG_ERROR("Invalid ICE context"); - return -1; - } - TSK_OBJECT_SAFE_FREE(self->ice_ctx); - self->ice_ctx = tsk_object_ref(ice_ctx); - return 0; + if(!self) { + TSK_DEBUG_ERROR("Invalid ICE context"); + return -1; + } + TSK_OBJECT_SAFE_FREE(self->ice_ctx); + self->ice_ctx = tsk_object_ref(ice_ctx); + return 0; } /** Prepares the RTP/RTCP manager */ int trtp_manager_prepare(trtp_manager_t* self) { - const char *rtp_local_ip = tsk_null, *rtcp_local_ip = tsk_null; - tnet_port_t rtp_local_port = 0, rtcp_local_port = 0; - - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if(self->transport){ - TSK_DEBUG_ERROR("RTP/RTCP manager already prepared"); - return -2; - } - - if(self->ice_ctx){ - TSK_DEBUG_INFO("ICE enabled on RTP manager"); - // Get Sockets when the transport is started - rtp_local_ip = rtcp_local_ip = self->use_ipv6 ? "::1" : "127.0.0.1"; - rtp_local_port = 2; // ICE default rtp port, do not use zero which is reserved to disabled medias - rtcp_local_port = 1; // ICE default rtcp port, do not use zero which is reserved to disabled medias - } - else{ - #define __retry_count_max 5 - #define __retry_count_max_minus1 (__retry_count_max - 1) - uint8_t retry_count = __retry_count_max; - tnet_socket_type_t socket_type = self->use_ipv6 ? tnet_socket_type_udp_ipv6 : tnet_socket_type_udp_ipv4; - - /* Creates local rtp and rtcp sockets */ - while(retry_count--){ - /* random number in the range 1024 to 65535 */ - static int counter = 0; + const char *rtp_local_ip = tsk_null, *rtcp_local_ip = tsk_null; + tnet_port_t rtp_local_port = 0, rtcp_local_port = 0; + + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if(self->transport) { + TSK_DEBUG_ERROR("RTP/RTCP manager already prepared"); + return -2; + } + + if(self->ice_ctx) { + TSK_DEBUG_INFO("ICE enabled on RTP manager"); + // Get Sockets when the transport is started + rtp_local_ip = rtcp_local_ip = self->use_ipv6 ? "::1" : "127.0.0.1"; + rtp_local_port = 2; // ICE default rtp port, do not use zero which is reserved to disabled medias + rtcp_local_port = 1; // ICE default rtcp port, do not use zero which is reserved to disabled medias + } + else { +#define __retry_count_max 5 +#define __retry_count_max_minus1 (__retry_count_max - 1) + uint8_t retry_count = __retry_count_max; + tnet_socket_type_t socket_type = self->use_ipv6 ? tnet_socket_type_udp_ipv6 : tnet_socket_type_udp_ipv4; + + /* Creates local rtp and rtcp sockets */ + while(retry_count--) { + /* random number in the range 1024 to 65535 */ + static int counter = 0; #if 0 - tnet_port_t local_port = 6060; + tnet_port_t local_port = 6060; #else - // first check => try to use port from latest active session if exist - tnet_port_t local_port = (retry_count == __retry_count_max_minus1 && (self->port_range.start <= self->rtp.public_port && self->rtp.public_port <= self->port_range.stop)) - ? self->rtp.public_port - : (((rand() ^ ++counter) % (self->port_range.stop - self->port_range.start)) + self->port_range.start); + // first check => try to use port from latest active session if exist + tnet_port_t local_port = (retry_count == __retry_count_max_minus1 && (self->port_range.start <= self->rtp.public_port && self->rtp.public_port <= self->port_range.stop)) + ? self->rtp.public_port + : (((rand() ^ ++counter) % (self->port_range.stop - self->port_range.start)) + self->port_range.start); #endif - local_port = (local_port & 0xFFFE); /* turn to even number */ - - /* beacuse failure will cause errors in the log, print a message to alert that there is - * nothing to worry about */ - TSK_DEBUG_INFO("RTP/RTCP manager[Begin]: Trying to bind to random ports"); - - /* RTP */ - if(!(self->transport = tnet_transport_create(self->local_ip, local_port, socket_type, TRTP_TRANSPORT_NAME))){ - TSK_DEBUG_ERROR("Failed to create RTP/RTCP Transport"); - return -3; - } - - /* RTCP */ - if (self->use_rtcp) { - if(!(self->rtcp.local_socket = tnet_socket_create(self->local_ip, local_port+1, socket_type))){ - TSK_DEBUG_WARN("Failed to bind to %d", local_port+1); - TSK_OBJECT_SAFE_FREE(self->transport); - continue; - } - } - - TSK_DEBUG_INFO("RTP/RTCP manager[End]: Trying to bind to random ports"); - break; - }// end-of-while(retry_count) - - rtp_local_ip = self->transport->master->ip; - rtp_local_port = self->transport->master->port; - if(self->rtcp.local_socket){ - rtcp_local_ip = self->rtcp.local_socket->ip; - rtcp_local_port = self->rtcp.local_socket->port; - - } - }// end-of-else(!ice) - - tsk_strupdate(&self->rtp.public_ip, rtp_local_ip); - self->rtp.public_port = rtp_local_port; - - tsk_strupdate(&self->rtcp.public_ip, rtcp_local_ip); - self->rtcp.public_port = rtcp_local_port; - - if(self->transport){ - /* set callback function */ - tnet_transport_set_callback(self->transport, _trtp_transport_layer_cb, self); - /* Disable receiving until we start the transport (To avoid buffering) */ + local_port = (local_port & 0xFFFE); /* turn to even number */ + + /* beacuse failure will cause errors in the log, print a message to alert that there is + * nothing to worry about */ + TSK_DEBUG_INFO("RTP/RTCP manager[Begin]: Trying to bind to random ports"); + + /* RTP */ + if(!(self->transport = tnet_transport_create(self->local_ip, local_port, socket_type, TRTP_TRANSPORT_NAME))) { + TSK_DEBUG_ERROR("Failed to create RTP/RTCP Transport"); + return -3; + } + + /* RTCP */ + if (self->use_rtcp) { + if(!(self->rtcp.local_socket = tnet_socket_create(self->local_ip, local_port+1, socket_type))) { + TSK_DEBUG_WARN("Failed to bind to %d", local_port+1); + TSK_OBJECT_SAFE_FREE(self->transport); + continue; + } + } + + TSK_DEBUG_INFO("RTP/RTCP manager[End]: Trying to bind to random ports"); + break; + }// end-of-while(retry_count) + + rtp_local_ip = self->transport->master->ip; + rtp_local_port = self->transport->master->port; + if(self->rtcp.local_socket) { + rtcp_local_ip = self->rtcp.local_socket->ip; + rtcp_local_port = self->rtcp.local_socket->port; + + } + }// end-of-else(!ice) + + tsk_strupdate(&self->rtp.public_ip, rtp_local_ip); + self->rtp.public_port = rtp_local_port; + + tsk_strupdate(&self->rtcp.public_ip, rtcp_local_ip); + self->rtcp.public_port = rtcp_local_port; + + if(self->transport) { + /* set callback function */ + tnet_transport_set_callback(self->transport, _trtp_transport_layer_cb, self); + /* Disable receiving until we start the transport (To avoid buffering) */ #if TRTP_DISABLE_SOCKETS_BEFORE_START - if(!self->socket_disabled){ - int err, optval = TRTP_TINY_RCVBUF; - if((err = setsockopt(self->transport->master->fd, SOL_SOCKET, SO_RCVBUF, (char*)&optval, sizeof(optval)))){ - TNET_PRINT_LAST_ERROR("setsockopt(SOL_SOCKET, SO_RCVBUF) has failed with error code %d", err); - } - self->socket_disabled = (err == 0); - } + if(!self->socket_disabled) { + int err, optval = TRTP_TINY_RCVBUF; + if((err = setsockopt(self->transport->master->fd, SOL_SOCKET, SO_RCVBUF, (char*)&optval, sizeof(optval)))) { + TNET_PRINT_LAST_ERROR("setsockopt(SOL_SOCKET, SO_RCVBUF) has failed with error code %d", err); + } + self->socket_disabled = (err == 0); + } #endif - } + } - /* SRTP */ + /* SRTP */ #if HAVE_SRTP - { - // enable SRTP to allow negotiation - if (self->srtp_type != tmedia_srtp_mode_none) { - struct tnet_socket_s* sockets[] = { self->transport ? self->transport->master : tsk_null, self->rtcp.local_socket }; - _trtp_manager_srtp_set_enabled(self, self->srtp_type, sockets, sizeof(sockets)/sizeof(sockets[0]), tsk_true); - } - } + { + // enable SRTP to allow negotiation + if (self->srtp_type != tmedia_srtp_mode_none) { + struct tnet_socket_s* sockets[] = { self->transport ? self->transport->master : tsk_null, self->rtcp.local_socket }; + _trtp_manager_srtp_set_enabled(self, self->srtp_type, sockets, sizeof(sockets)/sizeof(sockets[0]), tsk_true); + } + } #endif - return 0; + return 0; } #if HAVE_SRTP int trtp_manager_set_dtls_certs(trtp_manager_t* self, const char* ca, const char* pbk, const char* pvk, tsk_bool_t verify) { - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - // always save certificates even if not DTLS-SRTP transport - tsk_strupdate(&self->dtls.file_ca, ca); - tsk_strupdate(&self->dtls.file_pbk, pbk); - tsk_strupdate(&self->dtls.file_pvk, pvk); - self->dtls.cert_verif = verify; - - if((self->srtp_type & tmedia_srtp_type_dtls) && (self->srtp_mode == tmedia_srtp_mode_optional || self->srtp_mode == tmedia_srtp_mode_mandatory)){ - if(self->transport && tnet_transport_dtls_is_enabled(self->transport)){ - return tnet_transport_dtls_srtp_set_certs(self->transport, self->dtls.file_ca, self->dtls.file_pbk, self->dtls.file_pvk, self->dtls.cert_verif); - } - } - else{ - TSK_DEBUG_ERROR("DTLS certificates setting ignored for non-DTLS-SRTP transport"); - return -2; - } - - return 0; + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + // always save certificates even if not DTLS-SRTP transport + tsk_strupdate(&self->dtls.file_ca, ca); + tsk_strupdate(&self->dtls.file_pbk, pbk); + tsk_strupdate(&self->dtls.file_pvk, pvk); + self->dtls.cert_verif = verify; + + if((self->srtp_type & tmedia_srtp_type_dtls) && (self->srtp_mode == tmedia_srtp_mode_optional || self->srtp_mode == tmedia_srtp_mode_mandatory)) { + if(self->transport && tnet_transport_dtls_is_enabled(self->transport)) { + return tnet_transport_dtls_srtp_set_certs(self->transport, self->dtls.file_ca, self->dtls.file_pbk, self->dtls.file_pvk, self->dtls.cert_verif); + } + } + else { + TSK_DEBUG_ERROR("DTLS certificates setting ignored for non-DTLS-SRTP transport"); + return -2; + } + + return 0; } int trtp_manager_set_dtls_callback(trtp_manager_t* self, const void* usrdata, trtp_srtp_dtls_cb_f fun) { - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - self->dtls.cb.usrdata = usrdata; - self->dtls.cb.fun = fun; - - return 0; + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + self->dtls.cb.usrdata = usrdata; + self->dtls.cb.fun = fun; + + return 0; } int trtp_manager_set_dtls_remote_fingerprint(trtp_manager_t* self, const tnet_fingerprint_t* fp, const char* fp_hash) { - tnet_dtls_hash_type_t hash; - if(!self || !fp || !fp_hash){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - hash = tnet_dtls_get_hash_from_string(fp_hash); - if(hash != tnet_dtls_hash_type_sha1 && hash != tnet_dtls_hash_type_sha256){ - TSK_DEBUG_ERROR("%s not supported as fingerprint hash", fp_hash); - return -2; - } - self->dtls.remote.fp_hash = hash; - memcpy(self->dtls.remote.fp, &(*fp)[0], sizeof(tnet_fingerprint_t)); - return 0; + tnet_dtls_hash_type_t hash; + if(!self || !fp || !fp_hash) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + hash = tnet_dtls_get_hash_from_string(fp_hash); + if(hash != tnet_dtls_hash_type_sha1 && hash != tnet_dtls_hash_type_sha256) { + TSK_DEBUG_ERROR("%s not supported as fingerprint hash", fp_hash); + return -2; + } + self->dtls.remote.fp_hash = hash; + memcpy(self->dtls.remote.fp, &(*fp)[0], sizeof(tnet_fingerprint_t)); + return 0; } enum tnet_dtls_hash_type_e trtp_manager_get_dtls_remote_fingerprint_hash(trtp_manager_t* self) { - return (self ? self->dtls.remote.fp_hash : tnet_dtls_hash_type_none); + return (self ? self->dtls.remote.fp_hash : tnet_dtls_hash_type_none); } int trtp_manager_set_dtls_local_setup(trtp_manager_t* self, tnet_dtls_setup_t setup, tsk_bool_t connection_new) { - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - self->dtls.local.setup = setup; - self->dtls.local.connection_new = connection_new; - return 0; + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + self->dtls.local.setup = setup; + self->dtls.local.connection_new = connection_new; + return 0; } const char* trtp_manager_get_dtls_local_fingerprint(trtp_manager_t* self, enum tnet_dtls_hash_type_e hash) { - if(!self || (int32_t)hash < 0 || (int32_t)hash >= TNET_DTLS_HASH_TYPE_MAX){ - TSK_DEBUG_ERROR("Invalid parameter"); - return tsk_null; - } - if(!self->transport && self->dtls.file_pbk){ - static tnet_fingerprint_t fingerprint[TNET_DTLS_HASH_TYPE_MAX]; - if(tnet_dtls_get_fingerprint(self->dtls.file_pbk, &fingerprint[hash], hash) == 0){ - return (const char*)fingerprint[hash]; - } - } - return tnet_transport_dtls_get_local_fingerprint(self->transport, hash); + if(!self || (int32_t)hash < 0 || (int32_t)hash >= TNET_DTLS_HASH_TYPE_MAX) { + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_null; + } + if(!self->transport && self->dtls.file_pbk) { + static tnet_fingerprint_t fingerprint[TNET_DTLS_HASH_TYPE_MAX]; + if(tnet_dtls_get_fingerprint(self->dtls.file_pbk, &fingerprint[hash], hash) == 0) { + return (const char*)fingerprint[hash]; + } + } + return tnet_transport_dtls_get_local_fingerprint(self->transport, hash); } tsk_bool_t trtp_manager_is_dtls_enabled(trtp_manager_t* self) { - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return tsk_false; - } - return (self->dtls.state >= trtp_srtp_state_enabled); + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_false; + } + return (self->dtls.state >= trtp_srtp_state_enabled); } tsk_bool_t trtp_manager_is_dtls_activated(trtp_manager_t* self) { - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return tsk_false; - } - return (self->dtls.state >= trtp_srtp_state_activated); + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_false; + } + return (self->dtls.state >= trtp_srtp_state_activated); } tsk_bool_t trtp_manager_is_dtls_started(trtp_manager_t* self) { - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return tsk_false; - } - return (self->dtls.state >= trtp_srtp_state_started); + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_false; + } + return (self->dtls.state >= trtp_srtp_state_started); } tsk_bool_t trtp_manager_is_srtp_activated(trtp_manager_t* self) { - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return tsk_false; - } - return (self->srtp_state >= trtp_srtp_state_activated); + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_false; + } + return (self->srtp_state >= trtp_srtp_state_activated); } tsk_bool_t trtp_manager_is_srtp_started(trtp_manager_t* self) { - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return tsk_false; - } - return (self->srtp_state >= trtp_srtp_state_started); + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_false; + } + return (self->srtp_state >= trtp_srtp_state_started); } /** Sets SRTP type used by the remote party */ int trtp_manager_set_srtp_type_remote(trtp_manager_t* self, tmedia_srtp_type_t srtp_type_remote) { - tsk_size_t i; - int ret; - - if (!self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - for(i = 0; i < sizeof(__srtp_types)/sizeof(__srtp_types[i]); ++i) { - if ((self->srtp_type & __srtp_types[i]) && !(srtp_type_remote & __srtp_types[i])) { - struct tnet_socket_s* sockets[] = { self->transport ? self->transport->master : tsk_null, self->rtcp.local_socket }; - if ((ret = _trtp_manager_srtp_set_enabled(self, __srtp_types[i], sockets, sizeof(sockets) / sizeof(sockets[0]), tsk_false))) { - return ret; - } - self->srtp_type &= ~__srtp_types[i]; - } - } - return 0; + tsk_size_t i; + int ret; + + if (!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + for(i = 0; i < sizeof(__srtp_types)/sizeof(__srtp_types[i]); ++i) { + if ((self->srtp_type & __srtp_types[i]) && !(srtp_type_remote & __srtp_types[i])) { + struct tnet_socket_s* sockets[] = { self->transport ? self->transport->master : tsk_null, self->rtcp.local_socket }; + if ((ret = _trtp_manager_srtp_set_enabled(self, __srtp_types[i], sockets, sizeof(sockets) / sizeof(sockets[0]), tsk_false))) { + return ret; + } + self->srtp_type &= ~__srtp_types[i]; + } + } + return 0; } int trtp_manager_set_srtp_type_local(trtp_manager_t* self, enum tmedia_srtp_type_e srtp_type, enum tmedia_srtp_mode_e srtp_mode) { - if (!self) { - TSK_DEBUG_ERROR("Invalid ICE context"); - return -1; - } - if (srtp_mode == tmedia_srtp_mode_none || srtp_type == tmedia_srtp_type_none) { - struct tnet_socket_s* sockets[] = { self->transport ? self->transport->master : tsk_null, self->rtcp.local_socket }; - _trtp_manager_srtp_set_enabled(self, self->srtp_type, sockets, sizeof(sockets) / sizeof(sockets[0]), tsk_false); - self->srtp_type = srtp_type; - self->srtp_mode = srtp_mode; - return 0; - } - - self->srtp_mode = srtp_mode; - return trtp_manager_set_srtp_type_remote(self, srtp_type); + if (!self) { + TSK_DEBUG_ERROR("Invalid ICE context"); + return -1; + } + if (srtp_mode == tmedia_srtp_mode_none || srtp_type == tmedia_srtp_type_none) { + struct tnet_socket_s* sockets[] = { self->transport ? self->transport->master : tsk_null, self->rtcp.local_socket }; + _trtp_manager_srtp_set_enabled(self, self->srtp_type, sockets, sizeof(sockets) / sizeof(sockets[0]), tsk_false); + self->srtp_type = srtp_type; + self->srtp_mode = srtp_mode; + return 0; + } + + self->srtp_mode = srtp_mode; + return trtp_manager_set_srtp_type_remote(self, srtp_type); } #endif /* HAVE_SRTP */ @@ -1194,152 +1201,152 @@ int trtp_manager_set_srtp_type_local(trtp_manager_t* self, enum tmedia_srtp_type /** Indicates whether the manager is already ready or not */ tsk_bool_t trtp_manager_is_ready(trtp_manager_t* self) { - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return tsk_false; - } - return (self->transport != tsk_null); + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_false; + } + return (self->transport != tsk_null); } /** Sets NAT Traversal context */ int trtp_manager_set_natt_ctx(trtp_manager_t* self, struct tnet_nat_ctx_s* natt_ctx) { - int ret; - - if(!self || !self->transport || !natt_ctx){ - if(self && self->ice_ctx){ - return 0; // Nat context is not needed when ICE is enabled - } - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if(!(ret = tnet_transport_set_natt_ctx(self->transport, natt_ctx))){ - tnet_ip_t public_ip = {0}; - tnet_port_t public_port = 0; - // get RTP public IP and Port - if(!tnet_transport_get_public_ip_n_port(self->transport, self->transport->master->fd, &public_ip, &public_port)){ - tsk_strupdate(&self->rtp.public_ip, public_ip); - self->rtp.public_port = public_port; - } - // get RTCP public IP and Port - memset(public_ip, 0, sizeof(public_ip)); - public_port = 0; - if(self->rtcp.local_socket && !tnet_transport_get_public_ip_n_port(self->transport, self->rtcp.local_socket->fd, &public_ip, &public_port)){ - tsk_strupdate(&self->rtcp.public_ip, public_ip); - self->rtcp.public_port = public_port; - } - // re-enable sockets to be able to receive STUN packets + int ret; + + if(!self || !self->transport || !natt_ctx) { + if(self && self->ice_ctx) { + return 0; // Nat context is not needed when ICE is enabled + } + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if(!(ret = tnet_transport_set_natt_ctx(self->transport, natt_ctx))) { + tnet_ip_t public_ip = {0}; + tnet_port_t public_port = 0; + // get RTP public IP and Port + if(!tnet_transport_get_public_ip_n_port(self->transport, self->transport->master->fd, &public_ip, &public_port)) { + tsk_strupdate(&self->rtp.public_ip, public_ip); + self->rtp.public_port = public_port; + } + // get RTCP public IP and Port + memset(public_ip, 0, sizeof(public_ip)); + public_port = 0; + if(self->rtcp.local_socket && !tnet_transport_get_public_ip_n_port(self->transport, self->rtcp.local_socket->fd, &public_ip, &public_port)) { + tsk_strupdate(&self->rtcp.public_ip, public_ip); + self->rtcp.public_port = public_port; + } + // re-enable sockets to be able to receive STUN packets #if 0 - _trtp_manager_enable_sockets(self); + _trtp_manager_enable_sockets(self); #endif - } - return ret; + } + return ret; } /** Sets RTP callback */ int trtp_manager_set_rtp_callback(trtp_manager_t* self, trtp_rtp_cb_f fun, const void* usrdata) { - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - self->rtp.cb.fun = fun; - self->rtp.cb.usrdata = usrdata; + self->rtp.cb.fun = fun; + self->rtp.cb.usrdata = usrdata; - return 0; + return 0; } /** Sets RTCP callback */ int trtp_manager_set_rtcp_callback(trtp_manager_t* self, trtp_rtcp_cb_f fun, const void* usrdata) { - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - self->rtcp.cb.fun = fun; - self->rtcp.cb.usrdata = usrdata; - if(self->rtcp.session){ - return trtp_rtcp_session_set_callback(self->rtcp.session, fun, usrdata); - } - - return 0; + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + self->rtcp.cb.fun = fun; + self->rtcp.cb.usrdata = usrdata; + if(self->rtcp.session) { + return trtp_rtcp_session_set_callback(self->rtcp.session, fun, usrdata); + } + + return 0; } /** Sets the payload type */ int trtp_manager_set_payload_type(trtp_manager_t* self, uint8_t payload_type) { - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - self->rtp.payload_type = payload_type; - return 0; + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + self->rtp.payload_type = payload_type; + return 0; } int trtp_manager_set_rtp_dscp(trtp_manager_t* self, int32_t dscp) { - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - self->rtp.dscp = dscp; - return 0; + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + self->rtp.dscp = dscp; + return 0; } /** Sets remote parameters for rtp session */ int trtp_manager_set_rtp_remote(trtp_manager_t* self, const char* remote_ip, tnet_port_t remote_port) { - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - // if ICE is enabled then, these values will be updated when the manager start()s and call ice_init() - tsk_strupdate(&self->rtp.remote_ip, remote_ip); - self->rtp.remote_port = remote_port; - return 0; + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + // if ICE is enabled then, these values will be updated when the manager start()s and call ice_init() + tsk_strupdate(&self->rtp.remote_ip, remote_ip); + self->rtp.remote_port = remote_port; + return 0; } /** Sets remote parameters for rtcp session */ int trtp_manager_set_rtcp_remote(trtp_manager_t* self, const char* remote_ip, tnet_port_t remote_port) { - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if(self->ice_ctx){ - TSK_DEBUG_WARN("Manually setting RTCP remote IP and Port while ICE is enabled"); - } - tsk_strupdate(&self->rtcp.remote_ip, remote_ip); - self->rtcp.remote_port = remote_port; - return 0; + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if(self->ice_ctx) { + TSK_DEBUG_WARN("Manually setting RTCP remote IP and Port while ICE is enabled"); + } + tsk_strupdate(&self->rtcp.remote_ip, remote_ip); + self->rtcp.remote_port = remote_port; + return 0; } int trtp_manager_set_port_range(trtp_manager_t* self, uint16_t start, uint16_t stop) { - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - self->port_range.start = start; - self->port_range.stop = stop; - return 0; + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + self->port_range.start = start; + self->port_range.stop = stop; + return 0; } int trtp_manager_set_rtcweb_type_remote(trtp_manager_t* self, tmedia_rtcweb_type_t rtcweb_type) { - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - self->rtcweb_type.remote = rtcweb_type; - return 0; + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + self->rtcweb_type.remote = rtcweb_type; + return 0; } int trtp_manager_set_proxy_auto_detect(trtp_manager_t* self, tsk_bool_t auto_detect) { - if (!self){ + if (!self) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } @@ -1349,7 +1356,7 @@ int trtp_manager_set_proxy_auto_detect(trtp_manager_t* self, tsk_bool_t auto_det int trtp_manager_set_proxy_info(trtp_manager_t* self, enum tnet_proxy_type_e type, const char* host, tnet_port_t port, const char* login, const char* password) { - if (!self){ + if (!self) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } @@ -1367,41 +1374,41 @@ int trtp_manager_set_proxy_info(trtp_manager_t* self, enum tnet_proxy_type_e typ /** Starts the RTP/RTCP manager */ int trtp_manager_start(trtp_manager_t* self) { - int ret = 0; - int rcv_buf = (int)tmedia_defaults_get_rtpbuff_size(); - int snd_buf = (int)tmedia_defaults_get_rtpbuff_size(); + int ret = 0; + int rcv_buf = (int)tmedia_defaults_get_rtpbuff_size(); + int snd_buf = (int)tmedia_defaults_get_rtpbuff_size(); #if !TRTP_UNDER_WINDOWS_CE int32_t dscp_rtp; #endif - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - tsk_safeobj_lock(self); - - if (self->is_started) { - goto bail; - } - - // Initialize transport with ICE context - if (self->ice_ctx && (ret = _trtp_manager_ice_init(self)) != 0) { - TSK_DEBUG_ERROR("_trtp_manager_ice_init() failed"); - goto bail; - } - - if(!self->transport && (ret = trtp_manager_prepare(self))){ - TSK_DEBUG_ERROR("Failed to prepare RTP/RTCP mamanger"); - goto bail; - } - - if(!self->transport || !self->transport->master){ - TSK_DEBUG_ERROR("RTP/RTCP manager not prepared"); - ret = -2; - goto bail; - } - + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + tsk_safeobj_lock(self); + + if (self->is_started) { + goto bail; + } + + // Initialize transport with ICE context + if (self->ice_ctx && (ret = _trtp_manager_ice_init(self)) != 0) { + TSK_DEBUG_ERROR("_trtp_manager_ice_init() failed"); + goto bail; + } + + if(!self->transport && (ret = trtp_manager_prepare(self))) { + TSK_DEBUG_ERROR("Failed to prepare RTP/RTCP mamanger"); + goto bail; + } + + if(!self->transport || !self->transport->master) { + TSK_DEBUG_ERROR("RTP/RTCP manager not prepared"); + ret = -2; + goto bail; + } + /* Proxy */ // Proxy info if ((ret = tnet_transport_set_proxy_auto_detect(self->transport, self->proxy.auto_detect))) { @@ -1415,289 +1422,291 @@ int trtp_manager_start(trtp_manager_t* self) } } - /* Flush buffers and re-enable sockets */ - if(self->transport->master && self->is_socket_disabled){ - static char buff[1024]; - tsk_size_t guard_count = 0; + /* Flush buffers and re-enable sockets */ + if(self->transport->master && self->is_socket_disabled) { + static char buff[1024]; + tsk_size_t guard_count = 0; #if 0 - // re-enable sockets - _trtp_manager_enable_sockets(self); + // re-enable sockets + _trtp_manager_enable_sockets(self); #endif - TSK_DEBUG_INFO("Start flushing RTP socket..."); - // Buffer should be empty ...but who know? - // rcv() should never block() as we are always using non-blocking sockets - while ((ret = (int)recv(self->transport->master->fd, buff, sizeof(buff), 0)) > 0 && ++guard_count < 0xF0){ - TSK_DEBUG_INFO("Flushing RTP Buffer %d", ret); - } - TSK_DEBUG_INFO("End flushing RTP socket"); - } + TSK_DEBUG_INFO("Start flushing RTP socket..."); + // Buffer should be empty ...but who know? + // rcv() should never block() as we are always using non-blocking sockets + while ((ret = (int)recv(self->transport->master->fd, buff, sizeof(buff), 0)) > 0 && ++guard_count < 0xF0) { + TSK_DEBUG_INFO("Flushing RTP Buffer %d", ret); + } + TSK_DEBUG_INFO("End flushing RTP socket"); + } - /* enlarge socket buffer */ + /* enlarge socket buffer */ #if !TRTP_UNDER_WINDOWS_CE - TSK_DEBUG_INFO("SO_RCVBUF = %d, SO_SNDBUF = %d", rcv_buf, snd_buf); - if ((ret = setsockopt(self->transport->master->fd, SOL_SOCKET, SO_RCVBUF, (char*)&rcv_buf, sizeof(rcv_buf)))) { - TNET_PRINT_LAST_ERROR("setsockopt(SOL_SOCKET, SO_RCVBUF, %d) has failed with error code %d", rcv_buf, ret); - } - if ((ret = setsockopt(self->transport->master->fd, SOL_SOCKET, SO_SNDBUF, (char*)&snd_buf, sizeof(snd_buf)))) { - TNET_PRINT_LAST_ERROR("setsockopt(SOL_SOCKET, SO_SNDBUF, %d) has failed with error code %d", snd_buf, ret); - } - dscp_rtp = (self->rtp.dscp << 2); - if ((ret = setsockopt(self->transport->master->fd, IPPROTO_IP, IP_TOS, (char*)&dscp_rtp, sizeof(dscp_rtp)))) { - TNET_PRINT_LAST_ERROR("setsockopt(IPPROTO_IP, IP_TOS) has failed with error code %d", ret); - } + TSK_DEBUG_INFO("SO_RCVBUF = %d, SO_SNDBUF = %d", rcv_buf, snd_buf); + if ((ret = setsockopt(self->transport->master->fd, SOL_SOCKET, SO_RCVBUF, (char*)&rcv_buf, sizeof(rcv_buf)))) { + TNET_PRINT_LAST_ERROR("setsockopt(SOL_SOCKET, SO_RCVBUF, %d) has failed with error code %d", rcv_buf, ret); + } + if ((ret = setsockopt(self->transport->master->fd, SOL_SOCKET, SO_SNDBUF, (char*)&snd_buf, sizeof(snd_buf)))) { + TNET_PRINT_LAST_ERROR("setsockopt(SOL_SOCKET, SO_SNDBUF, %d) has failed with error code %d", snd_buf, ret); + } + dscp_rtp = (self->rtp.dscp << 2); + if ((ret = setsockopt(self->transport->master->fd, IPPROTO_IP, IP_TOS, (char*)&dscp_rtp, sizeof(dscp_rtp)))) { + TNET_PRINT_LAST_ERROR("setsockopt(IPPROTO_IP, IP_TOS) has failed with error code %d", ret); + } #endif /* !TRTP_UNDER_WINDOWS_CE */ - /* RTP */ - - // check remote IP address validity - if((tsk_striequals(self->rtp.remote_ip, "0.0.0.0") || tsk_striequals(self->rtp.remote_ip, "::"))) { // most likely loopback testing - tnet_ip_t source = {0}; - tsk_bool_t updated = tsk_false; - if(self->transport && self->transport->master){ - updated = (tnet_getbestsource(self->transport->master->ip, self->transport->master->port, self->transport->master->type, &source) == 0); - } - // Not allowed to send data to "0.0.0.0" - TSK_DEBUG_INFO("RTP remote IP contains not allowed value ...changing to '%s'", updated ? source : "oops"); - if(updated){ - tsk_strupdate(&self->rtp.remote_ip, source); - } - } - if((ret = tnet_sockaddr_init(self->rtp.remote_ip, self->rtp.remote_port, self->transport->master->type, &self->rtp.remote_addr))){ - tnet_transport_shutdown(self->transport); - TSK_OBJECT_SAFE_FREE(self->transport); - TSK_DEBUG_ERROR("Invalid RTP host:port [%s:%u]", self->rtp.remote_ip, self->rtp.remote_port); - goto bail; - } - TSK_DEBUG_INFO("rtp.remote_ip=%s, rtp.remote_port=%d, rtp.local_fd=%d", self->rtp.remote_ip, self->rtp.remote_port, self->transport->master->fd); - - /* RTCP */ - if(self->use_rtcp){ - tnet_fd_t local_rtcp_fd = self->rtcp.local_socket ? self->rtcp.local_socket->fd : -1; - if(local_rtcp_fd < 0 || self->use_rtcpmux){ // use RTP local port to send RTCP packets - local_rtcp_fd = self->transport->master->fd; - } - - if(!self->rtcp.remote_ip){ - self->rtcp.remote_ip = tsk_strdup(self->rtcp.remote_ip ? self->rtcp.remote_ip : self->rtp.remote_ip); - } - if(!self->rtcp.remote_port){ - self->rtcp.remote_port = self->rtcp.remote_port ? self->rtcp.remote_port : (self->use_rtcpmux ? self->rtp.remote_port : (self->rtp.remote_port + 1)); - } - - TSK_DEBUG_INFO("rtcp.remote_ip=%s, rtcp.remote_port=%d, rtcp.local_fd=%d", self->rtcp.remote_ip, self->rtcp.remote_port, local_rtcp_fd); - if((ret = tnet_sockaddr_init(self->rtcp.remote_ip, self->rtcp.remote_port, self->transport->master->type, &self->rtcp.remote_addr))){ - TSK_DEBUG_ERROR("Invalid RTCP host:port [%s:%u]", self->rtcp.remote_ip, self->rtcp.remote_port); - /* do not exit */ - } - - /* add RTCP socket to the transport */ - if(self->rtcp.local_socket){ - TSK_DEBUG_INFO("rtcp.local_ip=%s, rtcp.local_port=%d, rtcp.local_fd=%d", self->rtcp.local_socket->ip, self->rtcp.local_socket->port, self->rtcp.local_socket->fd); - if(ret == 0 && (ret = tnet_transport_add_socket(self->transport, self->rtcp.local_socket->fd, self->rtcp.local_socket->type, tsk_false/* do not take ownership */, tsk_true/* only Meaningful for tls*/, tsk_null))){ - TSK_DEBUG_ERROR("Failed to add RTCP socket"); - /* do not exit */ - } - } - /* create and start RTCP session */ - if(!self->rtcp.session && ret == 0){ - self->rtcp.session = trtp_rtcp_session_create_2(self->ice_ctx, self->rtp.ssrc.local, self->rtcp.cname); - } - if(self->rtcp.session){ - ret = trtp_rtcp_session_set_callback(self->rtcp.session, self->rtcp.cb.fun, self->rtcp.cb.usrdata); - ret = trtp_rtcp_session_set_app_bandwidth_max(self->rtcp.session, self->app_bw_max_upload, self->app_bw_max_download); + /* RTP */ + + // check remote IP address validity + if((tsk_striequals(self->rtp.remote_ip, "0.0.0.0") || tsk_striequals(self->rtp.remote_ip, "::"))) { // most likely loopback testing + tnet_ip_t source = {0}; + tsk_bool_t updated = tsk_false; + if(self->transport && self->transport->master) { + updated = (tnet_getbestsource(self->transport->master->ip, self->transport->master->port, self->transport->master->type, &source) == 0); + } + // Not allowed to send data to "0.0.0.0" + TSK_DEBUG_INFO("RTP remote IP contains not allowed value ...changing to '%s'", updated ? source : "oops"); + if(updated) { + tsk_strupdate(&self->rtp.remote_ip, source); + } + } + if((ret = tnet_sockaddr_init(self->rtp.remote_ip, self->rtp.remote_port, self->transport->master->type, &self->rtp.remote_addr))) { + tnet_transport_shutdown(self->transport); + TSK_OBJECT_SAFE_FREE(self->transport); + TSK_DEBUG_ERROR("Invalid RTP host:port [%s:%u]", self->rtp.remote_ip, self->rtp.remote_port); + goto bail; + } + TSK_DEBUG_INFO("rtp.remote_ip=%s, rtp.remote_port=%d, rtp.local_fd=%d", self->rtp.remote_ip, self->rtp.remote_port, self->transport->master->fd); + + /* RTCP */ + if(self->use_rtcp) { + tnet_fd_t local_rtcp_fd = self->rtcp.local_socket ? self->rtcp.local_socket->fd : -1; + if(local_rtcp_fd < 0 || self->use_rtcpmux) { // use RTP local port to send RTCP packets + local_rtcp_fd = self->transport->master->fd; + } + + if(!self->rtcp.remote_ip) { + self->rtcp.remote_ip = tsk_strdup(self->rtcp.remote_ip ? self->rtcp.remote_ip : self->rtp.remote_ip); + } + if(!self->rtcp.remote_port) { + self->rtcp.remote_port = self->rtcp.remote_port ? self->rtcp.remote_port : (self->use_rtcpmux ? self->rtp.remote_port : (self->rtp.remote_port + 1)); + } + + TSK_DEBUG_INFO("rtcp.remote_ip=%s, rtcp.remote_port=%d, rtcp.local_fd=%d", self->rtcp.remote_ip, self->rtcp.remote_port, local_rtcp_fd); + if((ret = tnet_sockaddr_init(self->rtcp.remote_ip, self->rtcp.remote_port, self->transport->master->type, &self->rtcp.remote_addr))) { + TSK_DEBUG_ERROR("Invalid RTCP host:port [%s:%u]", self->rtcp.remote_ip, self->rtcp.remote_port); + /* do not exit */ + } + + /* add RTCP socket to the transport */ + if(self->rtcp.local_socket) { + TSK_DEBUG_INFO("rtcp.local_ip=%s, rtcp.local_port=%d, rtcp.local_fd=%d", self->rtcp.local_socket->ip, self->rtcp.local_socket->port, self->rtcp.local_socket->fd); + if(ret == 0 && (ret = tnet_transport_add_socket(self->transport, self->rtcp.local_socket->fd, self->rtcp.local_socket->type, tsk_false/* do not take ownership */, tsk_true/* only Meaningful for tls*/, tsk_null))) { + TSK_DEBUG_ERROR("Failed to add RTCP socket"); + /* do not exit */ + } + } + /* create and start RTCP session */ + if(!self->rtcp.session && ret == 0) { + self->rtcp.session = trtp_rtcp_session_create_2(self->ice_ctx, self->rtp.ssrc.local, self->rtcp.cname); + } + if(self->rtcp.session) { + ret = trtp_rtcp_session_set_callback(self->rtcp.session, self->rtcp.cb.fun, self->rtcp.cb.usrdata); + ret = trtp_rtcp_session_set_app_bw_and_jcng(self->rtcp.session, self->app_bw_max_upload, self->app_bw_max_download, self->app_jitter_cng); ret = trtp_rtcp_session_set_net_transport(self->rtcp.session, self->transport); - if((ret = trtp_rtcp_session_start(self->rtcp.session, local_rtcp_fd, (const struct sockaddr *)&self->rtcp.remote_addr))){ - TSK_DEBUG_ERROR("Failed to start RTCP session"); - goto bail; - } - } - } - - /*SRTP*/ + if((ret = trtp_rtcp_session_start(self->rtcp.session, local_rtcp_fd, (const struct sockaddr *)&self->rtcp.remote_addr))) { + TSK_DEBUG_ERROR("Failed to start RTCP session"); + goto bail; + } + } + } + + /*SRTP*/ #if HAVE_SRTP - { - // activate SRTP (nothing will be done is srtp_mode is # "optional/mandatory") - // will also start the manager if we're using SDES mode - if((ret = _trtp_manager_srtp_activate(self, self->srtp_type))){ - goto bail; - } - - /* DTLS handshaking Timer */ - if (self->timer_mgr_global && self->srtp_state == trtp_srtp_state_activated && (self->srtp_type & tmedia_srtp_type_dtls) == tmedia_srtp_type_dtls) { - ret = tsk_timer_manager_start(self->timer_mgr_global); - self->dtls.timer_hanshaking.timeout = TRTP_DTLS_HANDSHAKING_TIMEOUT; - // start handshaking timer - // never mind if net work transport not started yet: the DTLS sockets will send the handshaking data by themself - self->dtls.timer_hanshaking.id = tsk_timer_manager_schedule(self->timer_mgr_global, self->dtls.timer_hanshaking.timeout, _trtp_transport_dtls_handshaking_timer_cb, self); - } - } + { + // activate SRTP (nothing will be done is srtp_mode is # "optional/mandatory") + // will also start the manager if we're using SDES mode + if((ret = _trtp_manager_srtp_activate(self, self->srtp_type))) { + goto bail; + } + + /* DTLS handshaking Timer */ + if (self->timer_mgr_global && self->srtp_state == trtp_srtp_state_activated && (self->srtp_type & tmedia_srtp_type_dtls) == tmedia_srtp_type_dtls) { + ret = tsk_timer_manager_start(self->timer_mgr_global); + self->dtls.timer_hanshaking.timeout = TRTP_DTLS_HANDSHAKING_TIMEOUT; + // start handshaking timer + // never mind if net work transport not started yet: the DTLS sockets will send the handshaking data by themself + self->dtls.timer_hanshaking.id = tsk_timer_manager_schedule(self->timer_mgr_global, self->dtls.timer_hanshaking.timeout, _trtp_transport_dtls_handshaking_timer_cb, self); + } + } #endif /* HAVE_SRTP */ - /* start the transport if TURN is not active (otherwise TURN data will be received directly on RTP manager with channel headers) */ - if (!self->is_ice_turn_active && (ret = tnet_transport_start(self->transport))) { - TSK_DEBUG_ERROR("Failed to start the RTP/RTCP transport"); - goto bail; - } + /* start the transport if TURN is not active (otherwise TURN data will be received directly on RTP manager with channel headers) */ + if (!self->is_ice_turn_active && (ret = tnet_transport_start(self->transport))) { + TSK_DEBUG_ERROR("Failed to start the RTP/RTCP transport"); + goto bail; + } - self->is_started = tsk_true; + self->is_started = tsk_true; bail: - tsk_safeobj_unlock(self); + tsk_safeobj_unlock(self); - return ret; + return ret; } -/* Encapsulate raw data into RTP packet and send it over the network +/* Encapsulate raw data into RTP packet and send it over the network * Very IMPORTANT: For voice packets, the marker bits indicates the beginning of a talkspurt */ tsk_size_t trtp_manager_send_rtp(trtp_manager_t* self, const void* data, tsk_size_t size, uint32_t duration, tsk_bool_t marker, tsk_bool_t last_packet) { - trtp_rtp_packet_t* packet; - tsk_size_t ret; - - if(!self || !self->transport || !data || !size){ - TSK_DEBUG_ERROR("Invalid parameter"); - return 0; - } - - /* check if transport is started */ - if(!self->is_started || !self->transport->master){ - TSK_DEBUG_WARN("RTP engine not ready yet"); - return 0; - } + trtp_rtp_packet_t* packet; + tsk_size_t ret; + + if(!self || !self->transport || !data || !size) { + TSK_DEBUG_ERROR("Invalid parameter"); + return 0; + } + + /* check if transport is started */ + if(!self->is_started || !self->transport->master) { + TSK_DEBUG_WARN("RTP engine not ready yet"); + return 0; + } #if HAVE_SRTP - /* check that SRTP engine is ready or disabled */ - if(self->srtp_state != trtp_srtp_state_none && self->srtp_state != trtp_srtp_state_started){ - TSK_DEBUG_WARN("SRTP engine not ready yet"); - return 0; - } + /* check that SRTP engine is ready or disabled */ + if(self->srtp_state != trtp_srtp_state_none && self->srtp_state != trtp_srtp_state_started) { + TSK_DEBUG_WARN("SRTP engine not ready yet"); + return 0; + } #endif - /* create packet with header */ - if(!(packet = trtp_rtp_packet_create(self->rtp.ssrc.local, ++self->rtp.seq_num, self->rtp.timestamp, self->rtp.payload_type, marker))){ - return 0; - } - if(last_packet){ - self->rtp.timestamp += duration; - } - - /* set data */ + /* create packet with header */ + if(!(packet = trtp_rtp_packet_create(self->rtp.ssrc.local, ++self->rtp.seq_num, self->rtp.timestamp, self->rtp.payload_type, marker))) { + return 0; + } + if(last_packet) { + self->rtp.timestamp += duration; + } + + /* set data */ #if 0 - if((packet->payload.data = tsk_calloc(size, sizeof(uint8_t)))){ - memcpy(packet->payload.data, data, size); - packet->payload.size = size; - } + if((packet->payload.data = tsk_calloc(size, sizeof(uint8_t)))) { + memcpy(packet->payload.data, data, size); + packet->payload.size = size; + } #else - packet->payload.data_const = data; - packet->payload.size = size; + packet->payload.data_const = data; + packet->payload.size = size; #endif - ret = trtp_manager_send_rtp_packet(self, packet, tsk_false); - TSK_OBJECT_SAFE_FREE(packet); - return ret; + ret = trtp_manager_send_rtp_packet(self, packet, tsk_false); + TSK_OBJECT_SAFE_FREE(packet); + return ret; } // serialize, encrypt then send the data tsk_size_t trtp_manager_send_rtp_packet(trtp_manager_t* self, const struct trtp_rtp_packet_s* packet, tsk_bool_t bypass_encrypt) { - int ret = 0; - tsk_size_t rtp_buff_pad_count = 0; - tsk_size_t xsize; - - /* check validity */ - if(!self || !packet){ - TSK_DEBUG_ERROR("Invalid parameter"); - return 0; - } - - tsk_safeobj_lock(self); - + int ret = 0; + tsk_size_t rtp_buff_pad_count = 0; + tsk_size_t xsize; + + /* check validity */ + if(!self || !packet) { + TSK_DEBUG_ERROR("Invalid parameter"); + return 0; + } + + tsk_safeobj_lock(self); + // reset index self->rtp.serial_buffer.index = 0; - /* check if transport is started */ - if(!self->is_started || !self->transport || !self->transport->master){ - TSK_DEBUG_WARN("RTP engine not ready yet"); - ret = 0; - goto bail; - } + /* check if transport is started */ + if(!self->is_started || !self->transport || !self->transport->master) { + TSK_DEBUG_WARN("RTP engine not ready yet"); + ret = 0; + goto bail; + } #if HAVE_SRTP - /* check that SRTP engine is ready or disabled */ - if(self->srtp_state != trtp_srtp_state_none && self->srtp_state != trtp_srtp_state_started){ - TSK_DEBUG_WARN("SRTP engine not ready yet"); - ret = 0; - goto bail; - } - if(self->srtp_ctx_neg_local && !bypass_encrypt){ - rtp_buff_pad_count = (SRTP_MAX_TRAILER_LEN + 0x04); - } + /* check that SRTP engine is ready or disabled */ + if(self->srtp_state != trtp_srtp_state_none && self->srtp_state != trtp_srtp_state_started) { + TSK_DEBUG_WARN("SRTP engine not ready yet"); + ret = 0; + goto bail; + } + if(self->srtp_ctx_neg_local && !bypass_encrypt) { + rtp_buff_pad_count = (SRTP_MAX_TRAILER_LEN + 0x04); + } #endif /* HAVE_SRTP */ - xsize = (trtp_rtp_packet_guess_serialbuff_size(packet) + rtp_buff_pad_count); - if(self->rtp.serial_buffer.size < xsize){ - if(!(self->rtp.serial_buffer.ptr = tsk_realloc(self->rtp.serial_buffer.ptr, xsize))){ - TSK_DEBUG_ERROR("Failed to allocate buffer with size = %d", (int)xsize); - self->rtp.serial_buffer.size = 0; - goto bail; - } - self->rtp.serial_buffer.size = xsize; - } - - /* serialize and send over the network */ - if ((ret = (int)trtp_rtp_packet_serialize_to(packet, self->rtp.serial_buffer.ptr, xsize))) { - void* data_ptr = self->rtp.serial_buffer.ptr; - int data_size = ret; + xsize = (trtp_rtp_packet_guess_serialbuff_size(packet) + rtp_buff_pad_count); + if(self->rtp.serial_buffer.size < xsize) { + if(!(self->rtp.serial_buffer.ptr = tsk_realloc(self->rtp.serial_buffer.ptr, xsize))) { + TSK_DEBUG_ERROR("Failed to allocate buffer with size = %d", (int)xsize); + self->rtp.serial_buffer.size = 0; + goto bail; + } + self->rtp.serial_buffer.size = xsize; + } + + /* serialize and send over the network */ + if ((ret = (int)trtp_rtp_packet_serialize_to(packet, self->rtp.serial_buffer.ptr, xsize))) { + void* data_ptr = self->rtp.serial_buffer.ptr; + int data_size = ret; #if HAVE_SRTP - err_status_t status; - if(self->srtp_ctx_neg_local && !bypass_encrypt){ - if((status = srtp_protect(self->srtp_ctx_neg_local->rtp.session, data_ptr, &data_size)) != err_status_ok){ - TSK_DEBUG_ERROR("srtp_protect() failed with error code =%d", (int)status); - goto bail; - } - } + err_status_t status; + if(self->srtp_ctx_neg_local && !bypass_encrypt) { + if((status = srtp_protect(self->srtp_ctx_neg_local->rtp.session, data_ptr, &data_size)) != err_status_ok) { + TSK_DEBUG_ERROR("srtp_protect() failed with error code =%d", (int)status); + goto bail; + } + } #endif self->rtp.serial_buffer.index = data_size; // update index - if (/* number of bytes sent */(ret = (int)trtp_manager_send_rtp_raw(self, data_ptr, data_size)) > 0) { - // forward packet to the RTCP session - if (self->rtcp.session) { - trtp_rtcp_session_process_rtp_out(self->rtcp.session, packet, data_size); - } - } - else ret = 0; - } - else{ - TSK_DEBUG_ERROR("Failed to serialize RTP packet"); - } + if (/* number of bytes sent */(ret = (int)trtp_manager_send_rtp_raw(self, data_ptr, data_size)) > 0) { + // forward packet to the RTCP session + if (self->rtcp.session) { + trtp_rtcp_session_process_rtp_out(self->rtcp.session, packet, data_size); + } + } + else { + ret = 0; + } + } + else { + TSK_DEBUG_ERROR("Failed to serialize RTP packet"); + } bail: - tsk_safeobj_unlock(self); - return ret; + tsk_safeobj_unlock(self); + return ret; } // send raw data "as is" without adding any RTP header or SRTP encryption tsk_size_t trtp_manager_send_rtp_raw(trtp_manager_t* self, const void* data, tsk_size_t size) { - tsk_size_t ret = 0; - - if(!self || !self->transport || !self->transport->master || !data || !size){ - TSK_DEBUG_ERROR("Invalid parameter"); - return 0; - } - tsk_safeobj_lock(self); - if (self->is_ice_turn_active) { - // Send UDP/TCP/TLS buffer using TURN sockets - ret = (tnet_ice_ctx_send_turn_rtp(self->ice_ctx, data, size) == 0) ? size : 0; // returns #0 if ok - } - else { + tsk_size_t ret = 0; + + if(!self || !self->transport || !self->transport->master || !data || !size) { + TSK_DEBUG_ERROR("Invalid parameter"); + return 0; + } + tsk_safeobj_lock(self); + if (self->is_ice_turn_active) { + // Send UDP/TCP/TLS buffer using TURN sockets + ret = (tnet_ice_ctx_send_turn_rtp(self->ice_ctx, data, size) == 0) ? size : 0; // returns #0 if ok + } + else { #if 1 ret = tnet_transport_sendto(self->transport, self->transport->master->fd, (const struct sockaddr *)&self->rtp.remote_addr, data, size); // returns number of sent bytes #else - ret = tnet_sockfd_sendto(self->transport->master->fd, (const struct sockaddr *)&self->rtp.remote_addr, data, size); // returns number of sent bytes + ret = tnet_sockfd_sendto(self->transport->master->fd, (const struct sockaddr *)&self->rtp.remote_addr, data, size); // returns number of sent bytes #endif - } - tsk_safeobj_unlock(self); - return ret; + } + tsk_safeobj_unlock(self); + return ret; } int trtp_manager_get_bytes_count(trtp_manager_t* self, uint64_t* bytes_in, uint64_t* bytes_out) @@ -1708,125 +1717,130 @@ int trtp_manager_get_bytes_count(trtp_manager_t* self, uint64_t* bytes_in, uint6 } if (!self->is_started) { TSK_DEBUG_INFO("trtp_manager_get_bytes_count() called before starting RTP manager... returning zeros"); - if (bytes_in) *bytes_in = 0; - if (bytes_out) *bytes_out = 0; + if (bytes_in) { + *bytes_in = 0; + } + if (bytes_out) { + *bytes_out = 0; + } return 0; } - + if (self->is_ice_turn_active) { return tnet_ice_ctx_turn_get_bytes_count(self->ice_ctx, bytes_in, bytes_out); } return tnet_transport_get_bytes_count(self->transport, bytes_in, bytes_out); } -int trtp_manager_set_app_bandwidth_max(trtp_manager_t* self, int32_t bw_upload_kbps, int32_t bw_download_kbps) +int trtp_manager_set_app_bw_and_jcng(trtp_manager_t* self, int32_t bw_upload_kbps, int32_t bw_download_kbps, float q_jcng) { - if(self){ - self->app_bw_max_upload = bw_upload_kbps; - self->app_bw_max_download = bw_download_kbps; - if(self->rtcp.session){ - return trtp_rtcp_session_set_app_bandwidth_max(self->rtcp.session, bw_upload_kbps, bw_download_kbps); - } - return 0; - } - return -1; + if(self) { + self->app_bw_max_upload = bw_upload_kbps; + self->app_bw_max_download = bw_download_kbps; + self->app_jitter_cng = q_jcng; + if(self->rtcp.session) { + return trtp_rtcp_session_set_app_bw_and_jcng(self->rtcp.session, bw_upload_kbps, bw_download_kbps, q_jcng); + } + return 0; + } + return -1; } int trtp_manager_signal_pkt_loss(trtp_manager_t* self, uint32_t ssrc_media, const uint16_t* seq_nums, tsk_size_t count) { - if(self && self->rtcp.session){ - return trtp_rtcp_session_signal_pkt_loss(self->rtcp.session, ssrc_media, seq_nums, count); - } - return -1; + if(self && self->rtcp.session) { + return trtp_rtcp_session_signal_pkt_loss(self->rtcp.session, ssrc_media, seq_nums, count); + } + return -1; } int trtp_manager_signal_frame_corrupted(trtp_manager_t* self, uint32_t ssrc_media) { - if(self && self->rtcp.session){ - return trtp_rtcp_session_signal_frame_corrupted(self->rtcp.session, ssrc_media); - } - return -1; + if(self && self->rtcp.session) { + return trtp_rtcp_session_signal_frame_corrupted(self->rtcp.session, ssrc_media); + } + return -1; } int trtp_manager_signal_jb_error(trtp_manager_t* self, uint32_t ssrc_media) { - if(self && self->rtcp.session){ - return trtp_rtcp_session_signal_jb_error(self->rtcp.session, ssrc_media); - } - return -1; + if(self && self->rtcp.session) { + return trtp_rtcp_session_signal_jb_error(self->rtcp.session, ssrc_media); + } + return -1; } /** Stops the RTP/RTCP manager */ int trtp_manager_stop(trtp_manager_t* self) { - int ret = 0; + int ret = 0; - if (!self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if (!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - TSK_DEBUG_INFO("trtp_manager_stop()"); + TSK_DEBUG_INFO("trtp_manager_stop()"); - tsk_safeobj_lock(self); + tsk_safeobj_lock(self); - // We haven't started the ICE context which means we must not stop it - //if(self->ice_ctx){ - // ret = tnet_ice_ctx_stop(self->ice_ctx); - //} + // We haven't started the ICE context which means we must not stop it + //if(self->ice_ctx){ + // ret = tnet_ice_ctx_stop(self->ice_ctx); + //} - // callbacks - if (self->transport) { - ret = tnet_transport_set_callback(self->transport, tsk_null, tsk_null); - } - if (self->ice_ctx) { - ret = tnet_ice_ctx_rtp_callback(self->ice_ctx, tsk_null, tsk_null); - } + // callbacks + if (self->transport) { + ret = tnet_transport_set_callback(self->transport, tsk_null, tsk_null); + } + if (self->ice_ctx) { + ret = tnet_ice_ctx_rtp_callback(self->ice_ctx, tsk_null, tsk_null); + } - // Stop the RTCP session first (will send BYE) - if(self->rtcp.session){ - ret = trtp_rtcp_session_stop(self->rtcp.session); + // Stop the RTCP session first (will send BYE) + if(self->rtcp.session) { + ret = trtp_rtcp_session_stop(self->rtcp.session); ret = trtp_rtcp_session_set_net_transport(self->rtcp.session, tsk_null); - } + } - // Free transport to force next call to start() to create new one with new sockets - if (self->transport) { - tnet_socket_t *master_copy = tsk_object_ref(self->transport->master); // "tnet_transport_shutdown" will free the master - tnet_transport_shutdown(self->transport); + // Free transport to force next call to start() to create new one with new sockets + if (self->transport) { + tnet_socket_t *master_copy = tsk_object_ref(self->transport->master); // "tnet_transport_shutdown" will free the master + tnet_transport_shutdown(self->transport); #if HAVE_SRTP - { - struct tnet_socket_s* sockets[] = { master_copy, self->rtcp.local_socket }; - // cancel DTLS handshaking timer - if (self->timer_mgr_global && self->dtls.timer_hanshaking.id != TSK_INVALID_TIMER_ID) { - tsk_timer_manager_cancel(self->timer_mgr_global, self->dtls.timer_hanshaking.id); - self->dtls.timer_hanshaking.id = TSK_INVALID_TIMER_ID; // invalidate timer id - self->dtls.timer_hanshaking.timeout = TRTP_DTLS_HANDSHAKING_TIMEOUT; // reset timeout - } - // destroy all SRTP contexts - _trtp_manager_srtp_set_enabled(self, self->srtp_type, sockets, sizeof(sockets) / sizeof(sockets[0]), tsk_false); - } + { + struct tnet_socket_s* sockets[] = { master_copy, self->rtcp.local_socket }; + // cancel DTLS handshaking timer + if (self->timer_mgr_global && self->dtls.timer_hanshaking.id != TSK_INVALID_TIMER_ID) { + tsk_timer_manager_cancel(self->timer_mgr_global, self->dtls.timer_hanshaking.id); + self->dtls.timer_hanshaking.id = TSK_INVALID_TIMER_ID; // invalidate timer id + self->dtls.timer_hanshaking.timeout = TRTP_DTLS_HANDSHAKING_TIMEOUT; // reset timeout + } + // destroy all SRTP contexts + _trtp_manager_srtp_set_enabled(self, self->srtp_type, sockets, sizeof(sockets) / sizeof(sockets[0]), tsk_false); + } #endif /* HAVE_SRTP */ - TSK_OBJECT_SAFE_FREE(master_copy); - TSK_OBJECT_SAFE_FREE(self->transport); - } - // Free RTCP info to make sure these values will be updated in next start() - TSK_OBJECT_SAFE_FREE(self->rtcp.local_socket); + TSK_OBJECT_SAFE_FREE(master_copy); + TSK_OBJECT_SAFE_FREE(self->transport); + } + // Free RTCP info to make sure these values will be updated in next start() + TSK_OBJECT_SAFE_FREE(self->rtcp.local_socket); TSK_OBJECT_SAFE_FREE(self->rtcp.session); self->rtcp.public_port = self->rtcp.remote_port = 0; TSK_FREE(self->rtcp.public_ip); TSK_FREE(self->rtcp.remote_ip); - // reset default values - self->is_symetric_rtp_checked = self->is_symetric_rtcp_checked = tsk_false; - self->is_ice_neg_ok = tsk_false; - self->is_ice_turn_active = tsk_false; - self->is_socket_disabled = tsk_false; + // reset default values + self->is_symetric_rtp_checked = self->is_symetric_rtcp_checked = tsk_false; + self->is_ice_neg_ok = tsk_false; + self->is_ice_turn_active = tsk_false; + self->is_socket_disabled = tsk_false; - self->is_started = tsk_false; + self->is_started = tsk_false; - tsk_safeobj_unlock(self); + tsk_safeobj_unlock(self); - return ret; + return ret; } @@ -1837,29 +1851,30 @@ int trtp_manager_stop(trtp_manager_t* self) // static tsk_object_t* trtp_manager_ctor(tsk_object_t * self, va_list * app) { - trtp_manager_t *manager = (trtp_manager_t*)self; - if(manager){ - manager->port_range.start = tmedia_defaults_get_rtp_port_range_start(); - manager->port_range.stop = tmedia_defaults_get_rtp_port_range_stop(); - manager->is_force_symetric_rtp = tmedia_defaults_get_rtp_symetric_enabled(); - manager->app_bw_max_upload = INT_MAX; // INT_MAX or <=0 means undefined - manager->app_bw_max_download = INT_MAX; // INT_MAX or <=0 means undefined - - /* srtp */ + trtp_manager_t *manager = (trtp_manager_t*)self; + if(manager) { + manager->port_range.start = tmedia_defaults_get_rtp_port_range_start(); + manager->port_range.stop = tmedia_defaults_get_rtp_port_range_stop(); + manager->is_force_symetric_rtp = tmedia_defaults_get_rtp_symetric_enabled(); + manager->app_bw_max_upload = INT_MAX; // INT_MAX or <=0 means undefined + manager->app_bw_max_download = INT_MAX; // INT_MAX or <=0 means undefined + manager->app_jitter_cng = 1.f; // Within [0, 1], in quality metric unit: 1 is best, 0 worst + + /* srtp */ #if HAVE_SRTP - manager->srtp_type = tmedia_defaults_get_srtp_type(); - manager->srtp_mode = tmedia_defaults_get_srtp_mode(); - manager->dtls.timer_hanshaking.id = TSK_INVALID_TIMER_ID; - manager->dtls.timer_hanshaking.timeout = TRTP_DTLS_HANDSHAKING_TIMEOUT; + manager->srtp_type = tmedia_defaults_get_srtp_type(); + manager->srtp_mode = tmedia_defaults_get_srtp_mode(); + manager->dtls.timer_hanshaking.id = TSK_INVALID_TIMER_ID; + manager->dtls.timer_hanshaking.timeout = TRTP_DTLS_HANDSHAKING_TIMEOUT; #endif /* HAVE_SRTP */ - /* rtp */ - manager->rtp.timestamp = rand()^rand(); - manager->rtp.seq_num = rand()^rand(); - manager->rtp.ssrc.local = rand()^rand()^(int)tsk_time_epoch(); + /* rtp */ + manager->rtp.timestamp = rand()^rand(); + manager->rtp.seq_num = rand()^rand(); + manager->rtp.ssrc.local = rand()^rand()^(int)tsk_time_epoch(); manager->rtp.dscp = TRTP_DSCP_RTP_DEFAULT; - /* rtcp */ + /* rtcp */ { // use MD5 string to avoid padding issues tsk_md5string_t md5 = { 0 }; @@ -1868,97 +1883,96 @@ static tsk_object_t* trtp_manager_ctor(tsk_object_t * self, va_list * app) tsk_strupdate(&manager->rtcp.cname, md5); } - /* timer */ - manager->timer_mgr_global = tsk_timer_mgr_global_ref(); + /* timer */ + manager->timer_mgr_global = tsk_timer_mgr_global_ref(); - tsk_safeobj_init(manager); - } - return self; + tsk_safeobj_init(manager); + } + return self; } static tsk_object_t* trtp_manager_dtor(tsk_object_t * self) -{ - trtp_manager_t *manager = self; - if(manager){ - /* callbacks */ - if (manager->ice_ctx) { - tnet_ice_ctx_rtp_callback(manager->ice_ctx, tsk_null, tsk_null); - } - if (manager->transport) { - - } - - /* stop */ - if (manager->is_started) { - trtp_manager_stop(manager); - } - - TSK_OBJECT_SAFE_FREE(manager->transport); - - TSK_FREE(manager->local_ip); - - /* rtp */ - TSK_FREE(manager->rtp.remote_ip); - TSK_FREE(manager->rtp.public_ip); - TSK_FREE(manager->rtp.serial_buffer.ptr); - - /* rtcp */ - TSK_OBJECT_SAFE_FREE(manager->rtcp.session); - TSK_FREE(manager->rtcp.remote_ip); - TSK_FREE(manager->rtcp.public_ip); - TSK_FREE(manager->rtcp.cname); - TSK_OBJECT_SAFE_FREE(manager->rtcp.local_socket); - - /* SRTP */ +{ + trtp_manager_t *manager = self; + if(manager) { + /* callbacks */ + if (manager->ice_ctx) { + tnet_ice_ctx_rtp_callback(manager->ice_ctx, tsk_null, tsk_null); + } + if (manager->transport) { + + } + + /* stop */ + if (manager->is_started) { + trtp_manager_stop(manager); + } + + TSK_OBJECT_SAFE_FREE(manager->transport); + + TSK_FREE(manager->local_ip); + + /* rtp */ + TSK_FREE(manager->rtp.remote_ip); + TSK_FREE(manager->rtp.public_ip); + TSK_FREE(manager->rtp.serial_buffer.ptr); + + /* rtcp */ + TSK_OBJECT_SAFE_FREE(manager->rtcp.session); + TSK_FREE(manager->rtcp.remote_ip); + TSK_FREE(manager->rtcp.public_ip); + TSK_FREE(manager->rtcp.cname); + TSK_OBJECT_SAFE_FREE(manager->rtcp.local_socket); + + /* SRTP */ #if HAVE_SRTP - { - int i; - - /* Timer */ - // cancel DTLS handshaking timer - if(manager->timer_mgr_global && manager->dtls.timer_hanshaking.id != TSK_INVALID_TIMER_ID){ - tsk_timer_manager_cancel(manager->timer_mgr_global, manager->dtls.timer_hanshaking.id); - manager->dtls.timer_hanshaking.id = TSK_INVALID_TIMER_ID; - } - - for(i = 0; i < 2; ++i){ - trtp_srtp_ctx_deinit(&manager->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][i]); - trtp_srtp_ctx_deinit(&manager->srtp_contexts[TRTP_SRTP_LINE_IDX_REMOTE][i]); - } - - /* SRTP-DTLS */ - TSK_FREE(manager->dtls.file_ca); - TSK_FREE(manager->dtls.file_pbk); - TSK_FREE(manager->dtls.file_pvk); - } + { + int i; + + /* Timer */ + // cancel DTLS handshaking timer + if(manager->timer_mgr_global && manager->dtls.timer_hanshaking.id != TSK_INVALID_TIMER_ID) { + tsk_timer_manager_cancel(manager->timer_mgr_global, manager->dtls.timer_hanshaking.id); + manager->dtls.timer_hanshaking.id = TSK_INVALID_TIMER_ID; + } + + for(i = 0; i < 2; ++i) { + trtp_srtp_ctx_deinit(&manager->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][i]); + trtp_srtp_ctx_deinit(&manager->srtp_contexts[TRTP_SRTP_LINE_IDX_REMOTE][i]); + } + + /* SRTP-DTLS */ + TSK_FREE(manager->dtls.file_ca); + TSK_FREE(manager->dtls.file_pbk); + TSK_FREE(manager->dtls.file_pvk); + } #endif /* HAVE_SRTP */ - /* Timer manager */ - if(manager->timer_mgr_global){ - tsk_timer_mgr_global_unref(&manager->timer_mgr_global); - } + /* Timer manager */ + if(manager->timer_mgr_global) { + tsk_timer_mgr_global_unref(&manager->timer_mgr_global); + } + + /* ICE */ + if (manager->ice_ctx) { + TSK_OBJECT_SAFE_FREE(manager->ice_ctx); + } - /* ICE */ - if (manager->ice_ctx) { - TSK_OBJECT_SAFE_FREE(manager->ice_ctx); - } - /* Proxy */ TSK_OBJECT_SAFE_FREE(manager->proxy.info); - tsk_safeobj_deinit(manager); + tsk_safeobj_deinit(manager); - TSK_DEBUG_INFO("*** RTP manager destroyed ***"); - } + TSK_DEBUG_INFO("*** RTP manager destroyed ***"); + } - return self; + return self; } -static const tsk_object_def_t trtp_manager_def_s = -{ - sizeof(trtp_manager_t), - trtp_manager_ctor, - trtp_manager_dtor, - tsk_null, +static const tsk_object_def_t trtp_manager_def_s = { + sizeof(trtp_manager_t), + trtp_manager_ctor, + trtp_manager_dtor, + tsk_null, }; const tsk_object_def_t *trtp_manager_def_t = &trtp_manager_def_s; diff --git a/tinyRTP/src/trtp_srtp.c b/tinyRTP/src/trtp_srtp.c index 5e2d033..e754a59 100755 --- a/tinyRTP/src/trtp_srtp.c +++ b/tinyRTP/src/trtp_srtp.c @@ -33,16 +33,16 @@ int trtp_srtp_ctx_internal_init(struct trtp_srtp_ctx_internal_xs* ctx, int32_t t char* key_str = ctx->key_str; err_status_t srtp_err; tsk_size_t size; - + if (!ctx) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - + if (ctx->initialized) { trtp_srtp_ctx_internal_deinit(ctx); } - + ctx->tag = tag; ctx->crypto_type = type; if (!ctx->have_valid_key) { // use same key to avoid unseless SRTP re-negs (also fix interop-issues against buggy clients -reINVITEs-) @@ -54,23 +54,21 @@ int trtp_srtp_ctx_internal_init(struct trtp_srtp_ctx_internal_xs* ctx, int32_t t key_str[size] = '\0'; ctx->have_valid_key = tsk_true; } - - switch(ctx->crypto_type){ - case HMAC_SHA1_80: - { - crypto_policy_set_aes_cm_128_hmac_sha1_80(&ctx->policy.rtp); - crypto_policy_set_aes_cm_128_hmac_sha1_80(&ctx->policy.rtcp); - break; - } - case HMAC_SHA1_32: - default: - { - crypto_policy_set_aes_cm_128_hmac_sha1_32(&ctx->policy.rtp); - crypto_policy_set_aes_cm_128_hmac_sha1_80(&ctx->policy.rtcp); // RTCP always 80 - break; - } + + switch(ctx->crypto_type) { + case HMAC_SHA1_80: { + crypto_policy_set_aes_cm_128_hmac_sha1_80(&ctx->policy.rtp); + crypto_policy_set_aes_cm_128_hmac_sha1_80(&ctx->policy.rtcp); + break; + } + case HMAC_SHA1_32: + default: { + crypto_policy_set_aes_cm_128_hmac_sha1_32(&ctx->policy.rtp); + crypto_policy_set_aes_cm_128_hmac_sha1_80(&ctx->policy.rtcp); // RTCP always 80 + break; } - + } + ctx->policy.key = (unsigned char*)ctx->key_bin; ctx->policy.ssrc.type = ssrc_any_outbound; ctx->policy.ssrc.value = ssrc; @@ -86,11 +84,11 @@ int trtp_srtp_ctx_internal_init(struct trtp_srtp_ctx_internal_xs* ctx, int32_t t int trtp_srtp_ctx_internal_deinit(struct trtp_srtp_ctx_internal_xs* ctx) { - if(!ctx){ + if(!ctx) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - if(ctx->initialized){ + if(ctx->initialized) { /*err_status_t srtp_err =*/ srtp_dealloc(ctx->session); memset(&ctx->policy, 0, sizeof(ctx->policy)); ctx->initialized = tsk_false; @@ -101,11 +99,11 @@ int trtp_srtp_ctx_internal_deinit(struct trtp_srtp_ctx_internal_xs* ctx) int trtp_srtp_ctx_init(trtp_srtp_ctx_xt* ctx, int32_t tag, trtp_srtp_crypto_type_t type, uint32_t ssrc) { int ret; - if(!ctx){ + if(!ctx) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - if((ret = trtp_srtp_ctx_internal_init(&ctx->rtp, tag, type, ssrc))){ + if((ret = trtp_srtp_ctx_internal_init(&ctx->rtp, tag, type, ssrc))) { return ret; } return trtp_srtp_ctx_internal_init(&ctx->rtcp, tag, type, ssrc); @@ -114,11 +112,11 @@ int trtp_srtp_ctx_init(trtp_srtp_ctx_xt* ctx, int32_t tag, trtp_srtp_crypto_type int trtp_srtp_ctx_deinit(trtp_srtp_ctx_xt* ctx) { int ret; - if(!ctx){ + if(!ctx) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - if((ret = trtp_srtp_ctx_internal_deinit(&ctx->rtp))){ + if((ret = trtp_srtp_ctx_internal_deinit(&ctx->rtp))) { return ret; } return trtp_srtp_ctx_internal_deinit(&ctx->rtcp); @@ -131,47 +129,46 @@ int trtp_srtp_match_line(const char* crypto_line, int32_t* tag, int32_t* crypto_ char* v = tsk_strtok_r(copyptr, " :|;", &saveptr); int32_t k = 0; int ret = -0xF0; - while(v){ - switch(k){ - case 0: - { - if(tag){ - *tag = atoi(v); - } - break; + while(v) { + switch(k) { + case 0: { + if(tag) { + *tag = atoi(v); } - case 1: - { - if(tsk_striequals(v, TRTP_SRTP_AES_CM_128_HMAC_SHA1_80)){ - if(crypto_type){ - *crypto_type = HMAC_SHA1_80; - } - } - else if(tsk_striequals(v, TRTP_SRTP_AES_CM_128_HMAC_SHA1_32)){ - if(crypto_type){ - *crypto_type = HMAC_SHA1_32; - } - } - else { - ret = -0xFF; goto bail; + break; + } + case 1: { + if(tsk_striequals(v, TRTP_SRTP_AES_CM_128_HMAC_SHA1_80)) { + if(crypto_type) { + *crypto_type = HMAC_SHA1_80; } - break; } - case 2: - { - if(!tsk_striequals(v, "inline")){ - ret = -0xFF; goto bail; + else if(tsk_striequals(v, TRTP_SRTP_AES_CM_128_HMAC_SHA1_32)) { + if(crypto_type) { + *crypto_type = HMAC_SHA1_32; } - break; } - case 3: - { - if(key && key_size){ - memset(key, 0, key_size); - memcpy(key, v, TSK_MIN(key_size, tsk_strlen(v))); - } - ret = 0; goto bail; + else { + ret = -0xFF; + goto bail; + } + break; + } + case 2: { + if(!tsk_striequals(v, "inline")) { + ret = -0xFF; + goto bail; + } + break; + } + case 3: { + if(key && key_size) { + memset(key, 0, key_size); + memcpy(key, v, TSK_MIN(key_size, tsk_strlen(v))); } + ret = 0; + goto bail; + } } ++k; v = tsk_strtok_r(tsk_null, " :|;", &saveptr); @@ -184,11 +181,11 @@ bail: tsk_size_t trtp_srtp_get_local_contexts(trtp_manager_t* rtp_mgr, const struct trtp_srtp_ctx_xs ** contexts, tsk_size_t contexts_count) { tsk_size_t ret = 0; - if(!rtp_mgr || !contexts){ + if(!rtp_mgr || !contexts) { TSK_DEBUG_ERROR("Invalid parameter"); return 0; } - + if (contexts_count > ret && rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_80].rtp.initialized) { contexts[ret++] = &rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_80]; } @@ -207,46 +204,45 @@ int trtp_srtp_set_crypto(struct trtp_manager_s* rtp_mgr, const char* crypto_line err_status_t srtp_err; int32_t tag, crypto_type; char key_str[SRTP_MAX_KEY_LEN + 1]; - + memset(key_str, 0, sizeof(key_str)); - + if ((ret = trtp_srtp_match_line(crypto_line, &tag, &crypto_type, key_str, sizeof(key_str) - 1))) { return ret; } - + srtp_ctx = &rtp_mgr->srtp_contexts[idx][crypto_type]; ret = trtp_srtp_ctx_deinit(srtp_ctx); - + srtp_ctx->rtp.tag = tag; srtp_ctx->rtp.crypto_type = (trtp_srtp_crypto_type_t)crypto_type; memcpy(srtp_ctx->rtp.key_str, key_str, sizeof(srtp_ctx->rtp.key_str)); - - switch(srtp_ctx->rtp.crypto_type){ - case HMAC_SHA1_80: - { - crypto_policy_set_aes_cm_128_hmac_sha1_80(&srtp_ctx->rtp.policy.rtp); - crypto_policy_set_aes_cm_128_hmac_sha1_80(&srtp_ctx->rtp.policy.rtcp); - if (idx == TRTP_SRTP_LINE_IDX_REMOTE) { - trtp_srtp_ctx_deinit(&rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_32]); - rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_80].rtp.tag = + + switch(srtp_ctx->rtp.crypto_type) { + case HMAC_SHA1_80: { + crypto_policy_set_aes_cm_128_hmac_sha1_80(&srtp_ctx->rtp.policy.rtp); + crypto_policy_set_aes_cm_128_hmac_sha1_80(&srtp_ctx->rtp.policy.rtcp); + if (idx == TRTP_SRTP_LINE_IDX_REMOTE) { + trtp_srtp_ctx_deinit(&rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_32]); + rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_80].rtp.tag = rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_80].rtcp.tag = srtp_ctx->rtp.tag; - } - break; } - case HMAC_SHA1_32: - { - crypto_policy_set_aes_cm_128_hmac_sha1_32(&srtp_ctx->rtp.policy.rtp); - crypto_policy_set_aes_cm_128_hmac_sha1_80(&srtp_ctx->rtp.policy.rtcp); // RTCP always 80 - if (idx == TRTP_SRTP_LINE_IDX_REMOTE) { - trtp_srtp_ctx_deinit(&rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_80]); - rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_32].rtp.tag = + break; + } + case HMAC_SHA1_32: { + crypto_policy_set_aes_cm_128_hmac_sha1_32(&srtp_ctx->rtp.policy.rtp); + crypto_policy_set_aes_cm_128_hmac_sha1_80(&srtp_ctx->rtp.policy.rtcp); // RTCP always 80 + if (idx == TRTP_SRTP_LINE_IDX_REMOTE) { + trtp_srtp_ctx_deinit(&rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_80]); + rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_32].rtp.tag = rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][HMAC_SHA1_32].rtcp.tag = srtp_ctx->rtp.tag; - } - break; } - default: break; + break; + } + default: + break; } - + key_bin = (unsigned char*)srtp_ctx->rtp.key_bin; tsk_base64_decode((const uint8_t*)srtp_ctx->rtp.key_str, (tsk_size_t)tsk_strlen(srtp_ctx->rtp.key_str), (char**)&key_bin); srtp_ctx->rtp.policy.key = key_bin; @@ -270,40 +266,38 @@ int trtp_srtp_set_key_and_salt(trtp_manager_t* rtp_mgr, trtp_srtp_crypto_type_t TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - + srtp_ctx = is_rtp ? &rtp_mgr->srtp_contexts[idx][crypto_type].rtp : &rtp_mgr->srtp_contexts[idx][crypto_type].rtcp; if ((ret = trtp_srtp_ctx_internal_deinit(srtp_ctx))) { return ret; } - + switch ((srtp_ctx->crypto_type = crypto_type)) { - case HMAC_SHA1_80: - default: - { - crypto_policy_set_aes_cm_128_hmac_sha1_80(&srtp_ctx->policy.rtp); - crypto_policy_set_aes_cm_128_hmac_sha1_80(&srtp_ctx->policy.rtcp); - break; - } - case HMAC_SHA1_32: - { - crypto_policy_set_aes_cm_128_hmac_sha1_32(&srtp_ctx->policy.rtp); - crypto_policy_set_aes_cm_128_hmac_sha1_80(&srtp_ctx->policy.rtcp); // always 80 - break; - } + case HMAC_SHA1_80: + default: { + crypto_policy_set_aes_cm_128_hmac_sha1_80(&srtp_ctx->policy.rtp); + crypto_policy_set_aes_cm_128_hmac_sha1_80(&srtp_ctx->policy.rtcp); + break; + } + case HMAC_SHA1_32: { + crypto_policy_set_aes_cm_128_hmac_sha1_32(&srtp_ctx->policy.rtp); + crypto_policy_set_aes_cm_128_hmac_sha1_80(&srtp_ctx->policy.rtcp); // always 80 + break; + } } - + memcpy(srtp_ctx->key_bin, key, key_size); #if HAVE_APPEND_SALT_TO_KEY append_salt_to_key(srtp_ctx->key_bin, key_size, (void*)salt, salt_size); #else memcpy(&srtp_ctx->key_bin[key_size], salt, salt_size); #endif - + srtp_ctx->policy.key = (unsigned char *)srtp_ctx->key_bin; srtp_ctx->policy.ssrc.type = idx == TRTP_SRTP_LINE_IDX_REMOTE ? ssrc_any_inbound : ssrc_any_outbound; srtp_ctx->policy.window_size = 2048; srtp_ctx->policy.allow_repeat_tx = 1; - if((srtp_err = srtp_create(&srtp_ctx->session, &srtp_ctx->policy)) != err_status_ok){ + if((srtp_err = srtp_create(&srtp_ctx->session, &srtp_ctx->policy)) != err_status_ok) { TSK_DEBUG_ERROR("srtp_create() failed: %d", srtp_err); return -3; } @@ -316,7 +310,7 @@ tsk_bool_t trtp_srtp_is_initialized(trtp_manager_t* rtp_mgr) if (!rtp_mgr) { return tsk_false; } - return ((rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][0].rtp.initialized || rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][1].rtp.initialized) + return ((rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][0].rtp.initialized || rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_LOCAL][1].rtp.initialized) && rtp_mgr->srtp_contexts[TRTP_SRTP_LINE_IDX_REMOTE][0].rtp.initialized); } diff --git a/tinyRTP/test/test.c b/tinyRTP/test/test.c index f0f15f6..dc5f9e2 100755 --- a/tinyRTP/test/test.c +++ b/tinyRTP/test/test.c @@ -2,19 +2,19 @@ * Copyright (C) 2009 Mamadou Diop. * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -41,25 +41,25 @@ int _tmain(int argc, _TCHAR* argv[]) int main() #endif { - tnet_startup(); + tnet_startup(); - do{ - /* Print copyright information */ - printf("Doubango Project\nCopyright (C) 2009-2010 Mamadou Diop \n\n"); + do { + /* Print copyright information */ + printf("Doubango Project\nCopyright (C) 2009-2010 Mamadou Diop \n\n"); #if RUN_TEST_PARSER || RUN_TEST_ALL - test_parser(); + test_parser(); #endif #if RUN_TEST_MANAGER || RUN_TEST_ALL - test_manager(); + test_manager(); #endif - } - while(LOOP); + } + while(LOOP); - tnet_cleanup(); + tnet_cleanup(); - return 0; + return 0; } diff --git a/tinyRTP/test/test_manager.h b/tinyRTP/test/test_manager.h index 29c2dcc..bbe406c 100755 --- a/tinyRTP/test/test_manager.h +++ b/tinyRTP/test/test_manager.h @@ -2,19 +2,19 @@ * Copyright (C) 2009 Mamadou Diop. * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -24,45 +24,45 @@ void test_manager() { - tsk_size_t i; - trtp_manager_t* manager; + tsk_size_t i; + trtp_manager_t* manager; + + if(!(manager = trtp_manager_create(tsk_true, "192.168.0.12", tsk_false))) { + goto bail; + } + + trtp_manager_set_payload_type(manager, 8); - if(!(manager = trtp_manager_create(tsk_true, "192.168.0.12", tsk_false))){ - goto bail; - } + /* Prepare: this will allow you to generate local port and ip */ + if(trtp_manager_prepare(manager)) { + goto bail; + } - trtp_manager_set_payload_type(manager, 8); + /* set remote parameters (rtcp ip:port not mandator, could be retrieved from rtp values) */ + if(trtp_manager_set_rtp_remote(manager, "192.168.0.13", 5081)) { + goto bail; + } + if(trtp_manager_set_rtcp_remote(manager, "192.168.0.13", 2861)) { + goto bail; + } - /* Prepare: this will allow you to generate local port and ip */ - if(trtp_manager_prepare(manager)){ - goto bail; - } + /* start */ + if(trtp_manager_start(manager)) { + goto bail; + } - /* set remote parameters (rtcp ip:port not mandator, could be retrieved from rtp values) */ - if(trtp_manager_set_rtp_remote(manager, "192.168.0.13", 5081)){ - goto bail; - } - if(trtp_manager_set_rtcp_remote(manager, "192.168.0.13", 2861)){ - goto bail; - } + /* send data */ + for(i=0; i<2; i++) { + if(trtp_manager_send_rtp(manager, "test", tsk_strlen("test"), 160, tsk_true)) { + goto bail; + } + } - /* start */ - if(trtp_manager_start(manager)){ - goto bail; - } - - /* send data */ - for(i=0;i<2; i++){ - if(trtp_manager_send_rtp(manager, "test", tsk_strlen("test"), 160, tsk_true)){ - goto bail; - } - } - - getchar(); + getchar(); bail: - /* stop and destroy */ - TSK_OBJECT_SAFE_FREE(manager); + /* stop and destroy */ + TSK_OBJECT_SAFE_FREE(manager); } #endif /* _TEST_MANAGER_H_ */ diff --git a/tinyRTP/test/test_parser.h b/tinyRTP/test/test_parser.h index a65b816..0d63215 100755 --- a/tinyRTP/test/test_parser.h +++ b/tinyRTP/test/test_parser.h @@ -2,19 +2,19 @@ * Copyright (C) 2009 Mamadou Diop. * * Contact: Mamadou Diop -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -23,258 +23,269 @@ #define _TEST_PARSER_H_ char packet_0[] = { -0x80, 0x88, 0x00, 0x01, 0x00, 0x00, 0x00, 0xa0, -0xd2, 0xbd, 0x4e, 0x3e, 0xdc, 0xde, 0xc4, 0xc5, -0xdc, 0xd0, 0xd5, 0x51, 0x53, 0x5d, 0x5f, 0x5b, -0x46, 0x46, 0x46, 0x5b, 0x44, 0x41, 0x42, 0x4f, -0x42, 0x47, 0x42, 0x43, 0x59, 0x58, 0x59, 0x5f, -0x5f, 0x52, 0x59, 0x44, 0x44, 0x5f, 0x51, 0x54, -0x55, 0x55, 0x51, 0x56, 0x50, 0x52, 0x5e, 0x58, -0x5d, 0x52, 0x52, 0x50, 0x57, 0x54, 0xd4, 0xd6, -0xd5, 0x51, 0x53, 0x57, 0xd6, 0xd6, 0xd0, 0xd7, -0x57, 0x56, 0x57, 0xd0, 0xd3, 0xd6, 0xd5, 0x55, -0x51, 0x50, 0xd6, 0xdf, 0xd2, 0xd1, 0xd4, 0xd6, -0xdc, 0xdb, 0xda, 0xdd, 0xd6, 0x55, 0xdc, 0xd0, -0xd4, 0x5d, 0x44, 0x5c, 0x56, 0xd6, 0xd5, 0xd4, -0xd5, 0xd7, 0x50, 0xd4, 0x51, 0xd0, 0x61, 0x6f, -0x76, 0xfe, 0xef, 0xf7, 0x77, 0x66, 0x50, 0xff, -0xe5, 0xd7, 0x74, 0x4a, 0xc9, 0xf9, 0xf7, 0x5c, -0x76, 0x5f, 0xf5, 0xf3, 0xdd, 0x4e, 0x42, 0xd8, -0xf7, 0xc9, 0x50, 0x44, 0x50, 0xcd, 0xc9, 0xd4, -0x4d, 0x41, 0x57, 0xd1, 0x51, 0x58, 0x44, 0x52, -0xd3, 0xd1, 0x50, 0x58, 0x5b, 0x55, 0xd4, 0x53, -0x59, 0x43, 0x47, 0x5f, 0x51, 0x5d, 0x56, 0xd2, -0xde, 0xd7, 0x52, 0xd5 }; + 0x80, 0x88, 0x00, 0x01, 0x00, 0x00, 0x00, 0xa0, + 0xd2, 0xbd, 0x4e, 0x3e, 0xdc, 0xde, 0xc4, 0xc5, + 0xdc, 0xd0, 0xd5, 0x51, 0x53, 0x5d, 0x5f, 0x5b, + 0x46, 0x46, 0x46, 0x5b, 0x44, 0x41, 0x42, 0x4f, + 0x42, 0x47, 0x42, 0x43, 0x59, 0x58, 0x59, 0x5f, + 0x5f, 0x52, 0x59, 0x44, 0x44, 0x5f, 0x51, 0x54, + 0x55, 0x55, 0x51, 0x56, 0x50, 0x52, 0x5e, 0x58, + 0x5d, 0x52, 0x52, 0x50, 0x57, 0x54, 0xd4, 0xd6, + 0xd5, 0x51, 0x53, 0x57, 0xd6, 0xd6, 0xd0, 0xd7, + 0x57, 0x56, 0x57, 0xd0, 0xd3, 0xd6, 0xd5, 0x55, + 0x51, 0x50, 0xd6, 0xdf, 0xd2, 0xd1, 0xd4, 0xd6, + 0xdc, 0xdb, 0xda, 0xdd, 0xd6, 0x55, 0xdc, 0xd0, + 0xd4, 0x5d, 0x44, 0x5c, 0x56, 0xd6, 0xd5, 0xd4, + 0xd5, 0xd7, 0x50, 0xd4, 0x51, 0xd0, 0x61, 0x6f, + 0x76, 0xfe, 0xef, 0xf7, 0x77, 0x66, 0x50, 0xff, + 0xe5, 0xd7, 0x74, 0x4a, 0xc9, 0xf9, 0xf7, 0x5c, + 0x76, 0x5f, 0xf5, 0xf3, 0xdd, 0x4e, 0x42, 0xd8, + 0xf7, 0xc9, 0x50, 0x44, 0x50, 0xcd, 0xc9, 0xd4, + 0x4d, 0x41, 0x57, 0xd1, 0x51, 0x58, 0x44, 0x52, + 0xd3, 0xd1, 0x50, 0x58, 0x5b, 0x55, 0xd4, 0x53, + 0x59, 0x43, 0x47, 0x5f, 0x51, 0x5d, 0x56, 0xd2, + 0xde, 0xd7, 0x52, 0xd5 +}; char packet_1[] = { -0x80, 0x08, 0x00, 0x02, 0x00, 0x00, 0x01, 0x40, -0xd2, 0xbd, 0x4e, 0x3e, 0xd2, 0xc7, 0xc5, 0xd3, -0xd1, 0xd6, 0xd5, 0x55, 0xd2, 0xd2, 0xd3, 0xdf, -0xc4, 0xd9, 0xdb, 0xc6, 0xc6, 0xc9, 0xc1, 0xf5, -0xcf, 0xf0, 0xcb, 0xe4, 0x7d, 0x14, 0x7a, 0xfd, -0xfd, 0x62, 0x63, 0x41, 0xee, 0xe7, 0x40, 0x6c, -0x46, 0xf8, 0xf3, 0x74, 0x7b, 0x58, 0xf3, 0xf1, -0xd6, 0x5d, 0xc7, 0xfd, 0xff, 0xf5, 0x55, 0xd9, -0xcb, 0xcb, 0xde, 0xd1, 0xda, 0xca, 0xcd, 0xc5, -0xc4, 0x41, 0x72, 0x41, 0x55, 0xda, 0x54, 0x5c, -0x40, 0x59, 0xd1, 0x5f, 0x4b, 0x40, 0x51, 0x52, -0x45, 0x4b, 0x77, 0x49, 0x4e, 0x4e, 0x48, 0x4a, -0x75, 0x47, 0x75, 0x7b, 0x72, 0x42, 0x58, 0x4c, -0x46, 0xd5, 0xc2, 0xd1, 0x5d, 0x44, 0x50, 0xd0, -0x53, 0x43, 0x41, 0x52, 0x53, 0x5a, 0x44, 0x50, -0xdd, 0x45, 0x65, 0x7d, 0x74, 0x4c, 0x70, 0x43, -0x53, 0xc4, 0xc5, 0x5b, 0x5a, 0x5c, 0x51, 0x4f, -0x70, 0x4a, 0x58, 0x5e, 0x75, 0x76, 0x40, 0x57, -0x51, 0x46, 0x5e, 0x5c, 0xd5, 0x5c, 0x5c, 0x5e, -0x5e, 0x4d, 0x41, 0x44, 0xd4, 0xd6, 0xd5, 0x52, -0x54, 0xdd, 0xd7, 0xd3, 0x56, 0x51, 0x55, 0xdf, -0x54, 0xd1, 0xd2, 0xda }; + 0x80, 0x08, 0x00, 0x02, 0x00, 0x00, 0x01, 0x40, + 0xd2, 0xbd, 0x4e, 0x3e, 0xd2, 0xc7, 0xc5, 0xd3, + 0xd1, 0xd6, 0xd5, 0x55, 0xd2, 0xd2, 0xd3, 0xdf, + 0xc4, 0xd9, 0xdb, 0xc6, 0xc6, 0xc9, 0xc1, 0xf5, + 0xcf, 0xf0, 0xcb, 0xe4, 0x7d, 0x14, 0x7a, 0xfd, + 0xfd, 0x62, 0x63, 0x41, 0xee, 0xe7, 0x40, 0x6c, + 0x46, 0xf8, 0xf3, 0x74, 0x7b, 0x58, 0xf3, 0xf1, + 0xd6, 0x5d, 0xc7, 0xfd, 0xff, 0xf5, 0x55, 0xd9, + 0xcb, 0xcb, 0xde, 0xd1, 0xda, 0xca, 0xcd, 0xc5, + 0xc4, 0x41, 0x72, 0x41, 0x55, 0xda, 0x54, 0x5c, + 0x40, 0x59, 0xd1, 0x5f, 0x4b, 0x40, 0x51, 0x52, + 0x45, 0x4b, 0x77, 0x49, 0x4e, 0x4e, 0x48, 0x4a, + 0x75, 0x47, 0x75, 0x7b, 0x72, 0x42, 0x58, 0x4c, + 0x46, 0xd5, 0xc2, 0xd1, 0x5d, 0x44, 0x50, 0xd0, + 0x53, 0x43, 0x41, 0x52, 0x53, 0x5a, 0x44, 0x50, + 0xdd, 0x45, 0x65, 0x7d, 0x74, 0x4c, 0x70, 0x43, + 0x53, 0xc4, 0xc5, 0x5b, 0x5a, 0x5c, 0x51, 0x4f, + 0x70, 0x4a, 0x58, 0x5e, 0x75, 0x76, 0x40, 0x57, + 0x51, 0x46, 0x5e, 0x5c, 0xd5, 0x5c, 0x5c, 0x5e, + 0x5e, 0x4d, 0x41, 0x44, 0xd4, 0xd6, 0xd5, 0x52, + 0x54, 0xdd, 0xd7, 0xd3, 0x56, 0x51, 0x55, 0xdf, + 0x54, 0xd1, 0xd2, 0xda +}; char packet_2[] = { -0x80, 0x08, 0x00, 0x03, 0x00, 0x00, 0x01, 0xe0, -0xd2, 0xbd, 0x4e, 0x3e, 0xdb, 0xd1, 0xd5, 0xd0, -0xd2, 0xd3, 0x57, 0xd5, 0xd6, 0xd6, 0xd1, 0xd5, -0xd1, 0xdd, 0xd5, 0xd1, 0xd1, 0xd4, 0x5f, 0x56, -0x5f, 0x5a, 0x53, 0x59, 0x5c, 0x5f, 0x5d, 0x5d, -0xd6, 0xd0, 0xd8, 0x54, 0xc4, 0xd9, 0xc6, 0xdc, -0x57, 0x56, 0x56, 0x57, 0x51, 0x54, 0x53, 0x57, -0x59, 0x44, 0x44, 0x5e, 0x45, 0x45, 0x5a, 0x5e, -0x53, 0x58, 0x4c, 0x45, 0x59, 0x45, 0x5b, 0x57, -0x52, 0x5e, 0x5e, 0x59, 0x5c, 0x51, 0xd7, 0xd0, -0xc5, 0xc1, 0xd8, 0xc1, 0xcd, 0xcd, 0xc2, 0xcd, -0xc6, 0xcc, 0xc0, 0xc6, 0xc1, 0xc9, 0xcb, 0xdb, -0xd0, 0xdd, 0xc6, 0xd8, 0xd5, 0x5f, 0x41, 0x46, -0x4f, 0x74, 0x76, 0x70, 0x72, 0x7f, 0x72, 0x77, -0x49, 0x4a, 0x76, 0x4a, 0x44, 0x45, 0x44, 0x59, -0x50, 0x55, 0xd3, 0xd9, 0xcc, 0xf7, 0xf1, 0xca, -0xc2, 0xf7, 0xf8, 0xe7, 0xe7, 0xe2, 0xee, 0xe9, -0xed, 0xe4, 0xc2, 0xcb, 0xf7, 0xd2, 0x48, 0x76, -0x45, 0x77, 0x64, 0x64, 0x4a, 0x51, 0x46, 0x41, -0xdd, 0xc2, 0xd4, 0x51, 0x50, 0x4a, 0x74, 0x71, -0x7e, 0x61, 0x67, 0x7e, 0x67, 0x60, 0x67, 0x77, -0x45, 0x43, 0x5f, 0xc8 }; + 0x80, 0x08, 0x00, 0x03, 0x00, 0x00, 0x01, 0xe0, + 0xd2, 0xbd, 0x4e, 0x3e, 0xdb, 0xd1, 0xd5, 0xd0, + 0xd2, 0xd3, 0x57, 0xd5, 0xd6, 0xd6, 0xd1, 0xd5, + 0xd1, 0xdd, 0xd5, 0xd1, 0xd1, 0xd4, 0x5f, 0x56, + 0x5f, 0x5a, 0x53, 0x59, 0x5c, 0x5f, 0x5d, 0x5d, + 0xd6, 0xd0, 0xd8, 0x54, 0xc4, 0xd9, 0xc6, 0xdc, + 0x57, 0x56, 0x56, 0x57, 0x51, 0x54, 0x53, 0x57, + 0x59, 0x44, 0x44, 0x5e, 0x45, 0x45, 0x5a, 0x5e, + 0x53, 0x58, 0x4c, 0x45, 0x59, 0x45, 0x5b, 0x57, + 0x52, 0x5e, 0x5e, 0x59, 0x5c, 0x51, 0xd7, 0xd0, + 0xc5, 0xc1, 0xd8, 0xc1, 0xcd, 0xcd, 0xc2, 0xcd, + 0xc6, 0xcc, 0xc0, 0xc6, 0xc1, 0xc9, 0xcb, 0xdb, + 0xd0, 0xdd, 0xc6, 0xd8, 0xd5, 0x5f, 0x41, 0x46, + 0x4f, 0x74, 0x76, 0x70, 0x72, 0x7f, 0x72, 0x77, + 0x49, 0x4a, 0x76, 0x4a, 0x44, 0x45, 0x44, 0x59, + 0x50, 0x55, 0xd3, 0xd9, 0xcc, 0xf7, 0xf1, 0xca, + 0xc2, 0xf7, 0xf8, 0xe7, 0xe7, 0xe2, 0xee, 0xe9, + 0xed, 0xe4, 0xc2, 0xcb, 0xf7, 0xd2, 0x48, 0x76, + 0x45, 0x77, 0x64, 0x64, 0x4a, 0x51, 0x46, 0x41, + 0xdd, 0xc2, 0xd4, 0x51, 0x50, 0x4a, 0x74, 0x71, + 0x7e, 0x61, 0x67, 0x7e, 0x67, 0x60, 0x67, 0x77, + 0x45, 0x43, 0x5f, 0xc8 +}; char packet_3[] = { -0x80, 0x08, 0x2c, 0x43, 0x11, 0x47, 0x31, 0xa2, -0x58, 0xf3, 0x3d, 0xea, 0x53, 0x45, 0x56, 0x47, -0x5f, 0xd4, 0xd4, 0x55, 0x56, 0x58, 0x40, 0x53, -0x54, 0xd5, 0xc7, 0xc4, 0x57, 0xd5, 0xdd, 0xd9, -0xde, 0xdd, 0xdc, 0xd4, 0x55, 0x54, 0xdc, 0xcf, -0xc7, 0x5e, 0x43, 0x5a, 0x5a, 0x43, 0x5b, 0x51, -0x54, 0x51, 0xd6, 0xd4, 0x5b, 0x53, 0xd3, 0x57, -0xd5, 0xc0, 0xc7, 0x53, 0x5d, 0xd1, 0xc5, 0xc1, -0xd9, 0x5d, 0x57, 0xdc, 0xd0, 0xd0, 0x54, 0x45, -0x44, 0x42, 0x45, 0xd0, 0xd4, 0xd5, 0xd9, 0xc7, -0x57, 0x5e, 0x5f, 0x47, 0x56, 0xc5, 0xca, 0xc5, -0xd3, 0xdf, 0x57, 0x43, 0x4b, 0x5a, 0x5c, 0x5f, -0x45, 0x52, 0xd0, 0xc7, 0xcb, 0xc9, 0xc5, 0x5f, -0x47, 0x57, 0x55, 0xdc, 0xc7, 0x5d, 0x4b, 0x5a, -0xdb, 0xcf, 0xc5, 0x52, 0x43, 0x5a, 0x56, 0xde, -0xdf, 0xd6, 0xd5, 0x45, 0x5b, 0xdc, 0xdb, 0x55, -0x52, 0x54, 0x51, 0xd5, 0xc4, 0xdf, 0xd1, 0x56, -0x51, 0xd5, 0xd3, 0xde, 0x54, 0x44, 0x46, 0x52, -0x56, 0x5b, 0x5a, 0xd3, 0xc3, 0xdf, 0x57, 0xd1, -0xd9, 0xd6, 0x5f, 0x5f, 0xd4, 0xd6, 0xd5, 0xd1, -0x53, 0xd4, 0xc1, 0xdb, 0xdd, 0xd8, 0xd7, 0x47, -0x4b, 0x75, 0x4c, 0x5c }; + 0x80, 0x08, 0x2c, 0x43, 0x11, 0x47, 0x31, 0xa2, + 0x58, 0xf3, 0x3d, 0xea, 0x53, 0x45, 0x56, 0x47, + 0x5f, 0xd4, 0xd4, 0x55, 0x56, 0x58, 0x40, 0x53, + 0x54, 0xd5, 0xc7, 0xc4, 0x57, 0xd5, 0xdd, 0xd9, + 0xde, 0xdd, 0xdc, 0xd4, 0x55, 0x54, 0xdc, 0xcf, + 0xc7, 0x5e, 0x43, 0x5a, 0x5a, 0x43, 0x5b, 0x51, + 0x54, 0x51, 0xd6, 0xd4, 0x5b, 0x53, 0xd3, 0x57, + 0xd5, 0xc0, 0xc7, 0x53, 0x5d, 0xd1, 0xc5, 0xc1, + 0xd9, 0x5d, 0x57, 0xdc, 0xd0, 0xd0, 0x54, 0x45, + 0x44, 0x42, 0x45, 0xd0, 0xd4, 0xd5, 0xd9, 0xc7, + 0x57, 0x5e, 0x5f, 0x47, 0x56, 0xc5, 0xca, 0xc5, + 0xd3, 0xdf, 0x57, 0x43, 0x4b, 0x5a, 0x5c, 0x5f, + 0x45, 0x52, 0xd0, 0xc7, 0xcb, 0xc9, 0xc5, 0x5f, + 0x47, 0x57, 0x55, 0xdc, 0xc7, 0x5d, 0x4b, 0x5a, + 0xdb, 0xcf, 0xc5, 0x52, 0x43, 0x5a, 0x56, 0xde, + 0xdf, 0xd6, 0xd5, 0x45, 0x5b, 0xdc, 0xdb, 0x55, + 0x52, 0x54, 0x51, 0xd5, 0xc4, 0xdf, 0xd1, 0x56, + 0x51, 0xd5, 0xd3, 0xde, 0x54, 0x44, 0x46, 0x52, + 0x56, 0x5b, 0x5a, 0xd3, 0xc3, 0xdf, 0x57, 0xd1, + 0xd9, 0xd6, 0x5f, 0x5f, 0xd4, 0xd6, 0xd5, 0xd1, + 0x53, 0xd4, 0xc1, 0xdb, 0xdd, 0xd8, 0xd7, 0x47, + 0x4b, 0x75, 0x4c, 0x5c +}; char packet_4[] = { -0x80, 0x08, 0x00, 0x04, 0x00, 0x00, 0x02, 0x80, -0xd2, 0xbd, 0x4e, 0x3e, 0xff, 0xf3, 0xff, 0xe1, -0xe7, 0xe4, 0xe5, 0xe2, 0xec, 0xef, 0xeb, 0xe9, -0x95, 0x97, 0xf8, 0xcc, 0xe4, 0xf9, 0x58, 0x6d, -0x72, 0x46, 0x7c, 0x62, 0x60, 0x42, 0x40, 0x70, -0x4e, 0xd3, 0xcb, 0xda, 0xd9, 0x54, 0x57, 0xd6, -0x4a, 0x62, 0x6e, 0x64, 0x60, 0x15, 0x15, 0x63, -0x67, 0x62, 0x60, 0x7f, 0x46, 0x46, 0x40, 0xd5, -0xcf, 0xf6, 0xc9, 0xcb, 0xf0, 0xfd, 0xf8, 0xe6, -0xec, 0xe9, 0x94, 0x91, 0x96, 0xf7, 0xd0, 0xe7, -0xf3, 0x7d, 0x6b, 0x7d, 0x5d, 0x65, 0x68, 0x61, -0x5d, 0x5c, 0x72, 0x43, 0xcd, 0xf6, 0xdf, 0xd2, -0xd2, 0x51, 0xdf, 0x49, 0x62, 0x14, 0x68, 0x6e, -0x10, 0x11, 0x69, 0x64, 0x61, 0x6d, 0x64, 0x75, -0x44, 0x74, 0x5e, 0xcf, 0xff, 0xf1, 0xc1, 0xf7, -0xf6, 0xe5, 0xe4, 0xe6, 0xe9, 0x91, 0x93, 0x90, -0x95, 0xce, 0xe5, 0xe0, 0xc7, 0x66, 0x62, 0x45, -0x75, 0x63, 0x6e, 0x79, 0x55, 0x49, 0x71, 0x53, -0xca, 0xcb, 0xd0, 0xdb, 0xd3, 0xd5, 0x5b, 0x67, -0x6b, 0x15, 0x61, 0x69, 0x17, 0x14, 0x6c, 0x66, -0x6f, 0x62, 0x7f, 0x48, 0x74, 0x75, 0x59, 0xd0, -0xdb, 0x54, 0xd7, 0xc3 }; + 0x80, 0x08, 0x00, 0x04, 0x00, 0x00, 0x02, 0x80, + 0xd2, 0xbd, 0x4e, 0x3e, 0xff, 0xf3, 0xff, 0xe1, + 0xe7, 0xe4, 0xe5, 0xe2, 0xec, 0xef, 0xeb, 0xe9, + 0x95, 0x97, 0xf8, 0xcc, 0xe4, 0xf9, 0x58, 0x6d, + 0x72, 0x46, 0x7c, 0x62, 0x60, 0x42, 0x40, 0x70, + 0x4e, 0xd3, 0xcb, 0xda, 0xd9, 0x54, 0x57, 0xd6, + 0x4a, 0x62, 0x6e, 0x64, 0x60, 0x15, 0x15, 0x63, + 0x67, 0x62, 0x60, 0x7f, 0x46, 0x46, 0x40, 0xd5, + 0xcf, 0xf6, 0xc9, 0xcb, 0xf0, 0xfd, 0xf8, 0xe6, + 0xec, 0xe9, 0x94, 0x91, 0x96, 0xf7, 0xd0, 0xe7, + 0xf3, 0x7d, 0x6b, 0x7d, 0x5d, 0x65, 0x68, 0x61, + 0x5d, 0x5c, 0x72, 0x43, 0xcd, 0xf6, 0xdf, 0xd2, + 0xd2, 0x51, 0xdf, 0x49, 0x62, 0x14, 0x68, 0x6e, + 0x10, 0x11, 0x69, 0x64, 0x61, 0x6d, 0x64, 0x75, + 0x44, 0x74, 0x5e, 0xcf, 0xff, 0xf1, 0xc1, 0xf7, + 0xf6, 0xe5, 0xe4, 0xe6, 0xe9, 0x91, 0x93, 0x90, + 0x95, 0xce, 0xe5, 0xe0, 0xc7, 0x66, 0x62, 0x45, + 0x75, 0x63, 0x6e, 0x79, 0x55, 0x49, 0x71, 0x53, + 0xca, 0xcb, 0xd0, 0xdb, 0xd3, 0xd5, 0x5b, 0x67, + 0x6b, 0x15, 0x61, 0x69, 0x17, 0x14, 0x6c, 0x66, + 0x6f, 0x62, 0x7f, 0x48, 0x74, 0x75, 0x59, 0xd0, + 0xdb, 0x54, 0xd7, 0xc3 +}; char packet_5[] = { -0x80, 0x08, 0x2c, 0x44, 0x11, 0x47, 0x32, 0x42, -0x58, 0xf3, 0x3d, 0xea, 0x54, 0xd5, 0xde, 0xc4, -0xc0, 0xce, 0xd8, 0xd5, 0xdc, 0xde, 0xd4, 0xd9, -0x54, 0x4d, 0x74, 0x47, 0x44, 0x58, 0xc7, 0xc3, -0xc4, 0xd4, 0x55, 0x50, 0x43, 0x45, 0xd4, 0xc7, -0xcf, 0xc0, 0x55, 0x42, 0x48, 0x76, 0x4f, 0xd7, -0xc7, 0xcf, 0xc6, 0xc6, 0xf5, 0xc6, 0x53, 0x5a, -0x42, 0x5e, 0x51, 0xd6, 0xc4, 0xde, 0x56, 0x42, -0x42, 0x5e, 0xd7, 0xd4, 0xdb, 0xcb, 0xda, 0xd6, -0xd7, 0x53, 0x47, 0x4d, 0xd4, 0xdf, 0xdc, 0xd5, -0x5a, 0x59, 0x5a, 0x5a, 0xd5, 0xc4, 0xd7, 0x55, -0xc3, 0xce, 0xde, 0xd2, 0xd6, 0x46, 0x71, 0x7c, -0x4c, 0xd8, 0xf5, 0xf7, 0xcf, 0x54, 0x56, 0xd5, -0xdc, 0xda, 0xd7, 0xd7, 0x57, 0x5a, 0x5c, 0x52, -0x47, 0x5c, 0xd4, 0xd3, 0xd4, 0x47, 0x42, 0x4d, -0x54, 0xcf, 0xf3, 0xf0, 0xc0, 0xdb, 0xd1, 0x50, -0x47, 0x5e, 0x58, 0x49, 0x43, 0x5a, 0x54, 0xdc, -0x56, 0x56, 0xd9, 0xc8, 0xc2, 0xd2, 0x5d, 0x5a, -0x5a, 0x49, 0x40, 0x57, 0xda, 0xdb, 0xd6, 0x55, -0xdd, 0xcf, 0xdb, 0x5c, 0x51, 0xd0, 0xd5, 0x5f, -0x53, 0xd8, 0xc3, 0xc3, 0xd0, 0x5c, 0x5b, 0x44, -0x4e, 0x74, 0x4f, 0x56 }; + 0x80, 0x08, 0x2c, 0x44, 0x11, 0x47, 0x32, 0x42, + 0x58, 0xf3, 0x3d, 0xea, 0x54, 0xd5, 0xde, 0xc4, + 0xc0, 0xce, 0xd8, 0xd5, 0xdc, 0xde, 0xd4, 0xd9, + 0x54, 0x4d, 0x74, 0x47, 0x44, 0x58, 0xc7, 0xc3, + 0xc4, 0xd4, 0x55, 0x50, 0x43, 0x45, 0xd4, 0xc7, + 0xcf, 0xc0, 0x55, 0x42, 0x48, 0x76, 0x4f, 0xd7, + 0xc7, 0xcf, 0xc6, 0xc6, 0xf5, 0xc6, 0x53, 0x5a, + 0x42, 0x5e, 0x51, 0xd6, 0xc4, 0xde, 0x56, 0x42, + 0x42, 0x5e, 0xd7, 0xd4, 0xdb, 0xcb, 0xda, 0xd6, + 0xd7, 0x53, 0x47, 0x4d, 0xd4, 0xdf, 0xdc, 0xd5, + 0x5a, 0x59, 0x5a, 0x5a, 0xd5, 0xc4, 0xd7, 0x55, + 0xc3, 0xce, 0xde, 0xd2, 0xd6, 0x46, 0x71, 0x7c, + 0x4c, 0xd8, 0xf5, 0xf7, 0xcf, 0x54, 0x56, 0xd5, + 0xdc, 0xda, 0xd7, 0xd7, 0x57, 0x5a, 0x5c, 0x52, + 0x47, 0x5c, 0xd4, 0xd3, 0xd4, 0x47, 0x42, 0x4d, + 0x54, 0xcf, 0xf3, 0xf0, 0xc0, 0xdb, 0xd1, 0x50, + 0x47, 0x5e, 0x58, 0x49, 0x43, 0x5a, 0x54, 0xdc, + 0x56, 0x56, 0xd9, 0xc8, 0xc2, 0xd2, 0x5d, 0x5a, + 0x5a, 0x49, 0x40, 0x57, 0xda, 0xdb, 0xd6, 0x55, + 0xdd, 0xcf, 0xdb, 0x5c, 0x51, 0xd0, 0xd5, 0x5f, + 0x53, 0xd8, 0xc3, 0xc3, 0xd0, 0x5c, 0x5b, 0x44, + 0x4e, 0x74, 0x4f, 0x56 +}; char packet_6[] = { -0x80, 0x08, 0x00, 0x05, 0x00, 0x00, 0x03, 0x20, -0xd2, 0xbd, 0x4e, 0x3e, 0xca, 0xf0, 0xfd, 0xe2, -0xea, 0x96, 0x91, 0x91, 0xe7, 0xd9, 0xf9, 0xf9, -0x48, 0x6b, 0x61, 0x74, 0x66, 0x15, 0x69, 0x74, -0x42, 0x7d, 0x75, 0xd2, 0xf7, 0xc8, 0xc3, 0xd1, -0x5f, 0x5f, 0x7d, 0x6f, 0x15, 0x6d, 0x6e, 0x16, -0x16, 0x68, 0x61, 0x62, 0x6c, 0x66, 0x79, 0x7d, -0x7f, 0x77, 0x5c, 0xd9, 0xdb, 0x5e, 0x55, 0xcf, -0xf1, 0xf0, 0xe5, 0xef, 0x95, 0x96, 0x93, 0x97, -0xcd, 0xc3, 0xe4, 0xf7, 0x64, 0x15, 0x7a, 0x73, -0x60, 0x68, 0x64, 0xd1, 0x53, 0x4e, 0x5d, 0xf7, -0xf9, 0xf3, 0xf5, 0xd5, 0xd4, 0x58, 0x67, 0x6e, -0x6c, 0x61, 0x68, 0x14, 0x68, 0x61, 0x64, 0x63, -0x61, 0x79, 0x75, 0x4b, 0x4f, 0x44, 0xd7, 0xcb, -0xc0, 0xd8, 0xf6, 0xe4, 0xe1, 0xe7, 0xed, 0x97, -0x91, 0x93, 0x9d, 0x96, 0xff, 0xfd, 0xe5, 0xc7, -0x66, 0x67, 0x4d, 0x4e, 0x64, 0x62, 0x71, 0x54, -0xd5, 0x5f, 0xd0, 0xce, 0xce, 0xdf, 0x5d, 0x73, -0x72, 0x73, 0x6c, 0x15, 0x6d, 0x6d, 0x15, 0x14, -0x69, 0x63, 0x62, 0x62, 0x66, 0x78, 0x72, 0x76, -0x43, 0x5b, 0xd5, 0xc0, 0xd9, 0xdd, 0xca, 0xf8, -0xe4, 0xe7, 0xef, 0x96 }; + 0x80, 0x08, 0x00, 0x05, 0x00, 0x00, 0x03, 0x20, + 0xd2, 0xbd, 0x4e, 0x3e, 0xca, 0xf0, 0xfd, 0xe2, + 0xea, 0x96, 0x91, 0x91, 0xe7, 0xd9, 0xf9, 0xf9, + 0x48, 0x6b, 0x61, 0x74, 0x66, 0x15, 0x69, 0x74, + 0x42, 0x7d, 0x75, 0xd2, 0xf7, 0xc8, 0xc3, 0xd1, + 0x5f, 0x5f, 0x7d, 0x6f, 0x15, 0x6d, 0x6e, 0x16, + 0x16, 0x68, 0x61, 0x62, 0x6c, 0x66, 0x79, 0x7d, + 0x7f, 0x77, 0x5c, 0xd9, 0xdb, 0x5e, 0x55, 0xcf, + 0xf1, 0xf0, 0xe5, 0xef, 0x95, 0x96, 0x93, 0x97, + 0xcd, 0xc3, 0xe4, 0xf7, 0x64, 0x15, 0x7a, 0x73, + 0x60, 0x68, 0x64, 0xd1, 0x53, 0x4e, 0x5d, 0xf7, + 0xf9, 0xf3, 0xf5, 0xd5, 0xd4, 0x58, 0x67, 0x6e, + 0x6c, 0x61, 0x68, 0x14, 0x68, 0x61, 0x64, 0x63, + 0x61, 0x79, 0x75, 0x4b, 0x4f, 0x44, 0xd7, 0xcb, + 0xc0, 0xd8, 0xf6, 0xe4, 0xe1, 0xe7, 0xed, 0x97, + 0x91, 0x93, 0x9d, 0x96, 0xff, 0xfd, 0xe5, 0xc7, + 0x66, 0x67, 0x4d, 0x4e, 0x64, 0x62, 0x71, 0x54, + 0xd5, 0x5f, 0xd0, 0xce, 0xce, 0xdf, 0x5d, 0x73, + 0x72, 0x73, 0x6c, 0x15, 0x6d, 0x6d, 0x15, 0x14, + 0x69, 0x63, 0x62, 0x62, 0x66, 0x78, 0x72, 0x76, + 0x43, 0x5b, 0xd5, 0xc0, 0xd9, 0xdd, 0xca, 0xf8, + 0xe4, 0xe7, 0xef, 0x96 +}; char packet_7[] = { -0x80, 0x08, 0x2c, 0x45, 0x11, 0x47, 0x32, 0xe2, -0x58, 0xf3, 0x3d, 0xea, 0xdd, 0xd9, 0xd2, 0xd6, -0xd0, 0xd6, 0xdf, 0xd7, 0xd7, 0x54, 0xd5, 0x57, -0x57, 0xd0, 0xd4, 0x55, 0xd5, 0xd8, 0xdb, 0xc0, -0xc2, 0x53, 0x58, 0x5d, 0x57, 0x5e, 0x47, 0x41, -0x4a, 0x5f, 0xde, 0xd9, 0x55, 0xd0, 0xc5, 0xdd, -0xd3, 0xdd, 0xc6, 0xc1, 0xd1, 0x52, 0x5b, 0xd1, -0xcc, 0xd9, 0x43, 0x7a, 0x78, 0x4e, 0x55, 0xd2, -0xc5, 0xc3, 0xda, 0xc5, 0xd4, 0xd3, 0xc7, 0xd2, -0xd9, 0xdb, 0x55, 0x45, 0x59, 0x51, 0x59, 0xd4, -0xc2, 0xc6, 0xd0, 0xd1, 0x59, 0x48, 0x40, 0x47, -0x5a, 0x55, 0xd2, 0xdc, 0xd9, 0xc9, 0xf6, 0xd9, -0x42, 0x72, 0x40, 0xd1, 0x50, 0xd7, 0xc4, 0xc9, -0xc5, 0xc1, 0xc3, 0x54, 0x5b, 0x48, 0x43, 0x57, -0xd3, 0xd1, 0x5c, 0x47, 0x47, 0x49, 0x47, 0x59, -0xd1, 0xf5, 0xd8, 0xd6, 0xdd, 0xd8, 0x5c, 0x53, -0xc7, 0xc9, 0xc9, 0xc0, 0xd4, 0x4d, 0x4f, 0x47, -0x50, 0xdf, 0xce, 0xd8, 0x5d, 0x43, 0x40, 0x5f, -0xd1, 0x56, 0x58, 0xd0, 0xd0, 0xd0, 0xdb, 0x55, -0x5b, 0x5b, 0xd4, 0xda, 0xc0, 0xc6, 0xd4, 0x58, -0x5a, 0xd8, 0xc7, 0xdf, 0x54, 0x4a, 0x71, 0x43, -0xd0, 0xc3, 0xc9, 0xde }; + 0x80, 0x08, 0x2c, 0x45, 0x11, 0x47, 0x32, 0xe2, + 0x58, 0xf3, 0x3d, 0xea, 0xdd, 0xd9, 0xd2, 0xd6, + 0xd0, 0xd6, 0xdf, 0xd7, 0xd7, 0x54, 0xd5, 0x57, + 0x57, 0xd0, 0xd4, 0x55, 0xd5, 0xd8, 0xdb, 0xc0, + 0xc2, 0x53, 0x58, 0x5d, 0x57, 0x5e, 0x47, 0x41, + 0x4a, 0x5f, 0xde, 0xd9, 0x55, 0xd0, 0xc5, 0xdd, + 0xd3, 0xdd, 0xc6, 0xc1, 0xd1, 0x52, 0x5b, 0xd1, + 0xcc, 0xd9, 0x43, 0x7a, 0x78, 0x4e, 0x55, 0xd2, + 0xc5, 0xc3, 0xda, 0xc5, 0xd4, 0xd3, 0xc7, 0xd2, + 0xd9, 0xdb, 0x55, 0x45, 0x59, 0x51, 0x59, 0xd4, + 0xc2, 0xc6, 0xd0, 0xd1, 0x59, 0x48, 0x40, 0x47, + 0x5a, 0x55, 0xd2, 0xdc, 0xd9, 0xc9, 0xf6, 0xd9, + 0x42, 0x72, 0x40, 0xd1, 0x50, 0xd7, 0xc4, 0xc9, + 0xc5, 0xc1, 0xc3, 0x54, 0x5b, 0x48, 0x43, 0x57, + 0xd3, 0xd1, 0x5c, 0x47, 0x47, 0x49, 0x47, 0x59, + 0xd1, 0xf5, 0xd8, 0xd6, 0xdd, 0xd8, 0x5c, 0x53, + 0xc7, 0xc9, 0xc9, 0xc0, 0xd4, 0x4d, 0x4f, 0x47, + 0x50, 0xdf, 0xce, 0xd8, 0x5d, 0x43, 0x40, 0x5f, + 0xd1, 0x56, 0x58, 0xd0, 0xd0, 0xd0, 0xdb, 0x55, + 0x5b, 0x5b, 0xd4, 0xda, 0xc0, 0xc6, 0xd4, 0x58, + 0x5a, 0xd8, 0xc7, 0xdf, 0x54, 0x4a, 0x71, 0x43, + 0xd0, 0xc3, 0xc9, 0xde +}; char packet_8[] = { -0x80, 0x08, 0x00, 0x06, 0x00, 0x00, 0x03, 0xc0, -0xd2, 0xbd, 0x4e, 0x3e, 0x90, 0x93, 0x92, 0x92, -0xe0, 0xf1, 0xff, 0xf6, 0x73, 0x60, 0x73, 0x75, -0x7f, 0x66, 0x7e, 0x5b, 0xd7, 0x56, 0xd5, 0xd2, -0xdf, 0xd2, 0xd0, 0x48, 0x78, 0x65, 0x66, 0x6f, -0x6b, 0x6c, 0x6f, 0x68, 0x6b, 0x6e, 0x6c, 0x62, -0x65, 0x78, 0x7d, 0x48, 0x4b, 0x4a, 0x42, 0xda, -0xf4, 0xc0, 0xcf, 0xfd, 0xe6, 0xe0, 0xe3, 0xe9, -0x91, 0x92, 0x9c, 0x9f, 0x90, 0xe2, 0xe7, 0xfa, -0xc3, 0x46, 0x75, 0x5f, 0x47, 0x42, 0x48, 0x44, -0xd3, 0xd0, 0xc5, 0xdf, 0xd2, 0xd8, 0xd8, 0x58, -0x7c, 0x72, 0x73, 0x7e, 0x60, 0x61, 0x65, 0x67, -0x60, 0x6d, 0x66, 0x7c, 0x71, 0x7d, 0x7d, 0x4a, -0xd4, 0xd8, 0xd2, 0xc1, 0xf5, 0xce, 0xdb, 0xf0, -0xe6, 0xe6, 0xe6, 0xed, 0xea, 0x97, 0x91, 0x92, -0x9c, 0x97, 0xe4, 0xfb, 0xe4, 0xc1, 0x74, 0x40, -0x54, 0x50, 0x4e, 0x75, 0x45, 0x54, 0x50, 0x44, -0x5f, 0x5d, 0x5b, 0x46, 0x73, 0x64, 0x7a, 0x7e, -0x67, 0x63, 0x66, 0x60, 0x6c, 0x69, 0x6c, 0x60, -0x64, 0x7a, 0x7b, 0x7c, 0x48, 0x45, 0x5b, 0x59, -0xd8, 0xca, 0xcc, 0xc3, 0xf0, 0xfa, 0xe5, 0xe1, -0xed, 0xea, 0x96, 0x91 }; + 0x80, 0x08, 0x00, 0x06, 0x00, 0x00, 0x03, 0xc0, + 0xd2, 0xbd, 0x4e, 0x3e, 0x90, 0x93, 0x92, 0x92, + 0xe0, 0xf1, 0xff, 0xf6, 0x73, 0x60, 0x73, 0x75, + 0x7f, 0x66, 0x7e, 0x5b, 0xd7, 0x56, 0xd5, 0xd2, + 0xdf, 0xd2, 0xd0, 0x48, 0x78, 0x65, 0x66, 0x6f, + 0x6b, 0x6c, 0x6f, 0x68, 0x6b, 0x6e, 0x6c, 0x62, + 0x65, 0x78, 0x7d, 0x48, 0x4b, 0x4a, 0x42, 0xda, + 0xf4, 0xc0, 0xcf, 0xfd, 0xe6, 0xe0, 0xe3, 0xe9, + 0x91, 0x92, 0x9c, 0x9f, 0x90, 0xe2, 0xe7, 0xfa, + 0xc3, 0x46, 0x75, 0x5f, 0x47, 0x42, 0x48, 0x44, + 0xd3, 0xd0, 0xc5, 0xdf, 0xd2, 0xd8, 0xd8, 0x58, + 0x7c, 0x72, 0x73, 0x7e, 0x60, 0x61, 0x65, 0x67, + 0x60, 0x6d, 0x66, 0x7c, 0x71, 0x7d, 0x7d, 0x4a, + 0xd4, 0xd8, 0xd2, 0xc1, 0xf5, 0xce, 0xdb, 0xf0, + 0xe6, 0xe6, 0xe6, 0xed, 0xea, 0x97, 0x91, 0x92, + 0x9c, 0x97, 0xe4, 0xfb, 0xe4, 0xc1, 0x74, 0x40, + 0x54, 0x50, 0x4e, 0x75, 0x45, 0x54, 0x50, 0x44, + 0x5f, 0x5d, 0x5b, 0x46, 0x73, 0x64, 0x7a, 0x7e, + 0x67, 0x63, 0x66, 0x60, 0x6c, 0x69, 0x6c, 0x60, + 0x64, 0x7a, 0x7b, 0x7c, 0x48, 0x45, 0x5b, 0x59, + 0xd8, 0xca, 0xcc, 0xc3, 0xf0, 0xfa, 0xe5, 0xe1, + 0xed, 0xea, 0x96, 0x91 +}; char packet_9[] = { -0x80, 0x08, 0x2c, 0x46, 0x11, 0x47, 0x33, 0x82, -0x58, 0xf3, 0x3d, 0xea, 0x5b, 0x47, 0x55, 0xdf, -0xd1, 0xd5, 0x54, 0xd3, 0xc4, 0x55, 0x5e, 0x56, -0xd1, 0xd2, 0xde, 0xdd, 0x54, 0x5c, 0x45, 0x5d, -0x55, 0x5d, 0x59, 0xd6, 0x55, 0x5a, 0xd3, 0xd9, -0xd0, 0xdc, 0xd8, 0xd8, 0xc6, 0xca, 0xc6, 0xd1, -0x5a, 0x7f, 0x7e, 0x4f, 0xdd, 0xd9, 0x57, 0x45, -0x59, 0xd7, 0xdd, 0xc3, 0xc6, 0x54, 0x5c, 0xd4, -0xdd, 0xdd, 0x5d, 0x43, 0x55, 0xdf, 0xda, 0xcc, -0xc9, 0x54, 0x4f, 0x5c, 0x55, 0xd2, 0xd0, 0xd1, -0x52, 0x5f, 0xdd, 0x53, 0x58, 0x53, 0xd6, 0xdd, -0xd9, 0xdc, 0xc1, 0xd7, 0x4a, 0x4e, 0x47, 0x51, -0xdf, 0xf5, 0xc6, 0x57, 0x5b, 0x75, 0x74, 0x55, -0xf6, 0xdb, 0x5e, 0x50, 0xd4, 0xd3, 0x56, 0x58, -0x5f, 0xd7, 0xdd, 0xde, 0xd2, 0xd5, 0x4d, 0x71, -0x5f, 0xf4, 0xf2, 0xc0, 0x50, 0x41, 0x5c, 0xd0, -0xd7, 0xdc, 0xd1, 0x45, 0x4e, 0x5c, 0x54, 0x5e, -0x77, 0x72, 0x5a, 0xcf, 0xf2, 0xf4, 0xda, 0xd2, -0xd6, 0x58, 0x5e, 0xdf, 0xc1, 0xc2, 0x57, 0x40, -0x56, 0xd7, 0xd7, 0xd5, 0x56, 0x45, 0x43, 0x50, -0xd9, 0xd2, 0x52, 0x5e, 0x5d, 0xd2, 0xd8, 0xd2, -0x54, 0x58, 0x41, 0x43 }; + 0x80, 0x08, 0x2c, 0x46, 0x11, 0x47, 0x33, 0x82, + 0x58, 0xf3, 0x3d, 0xea, 0x5b, 0x47, 0x55, 0xdf, + 0xd1, 0xd5, 0x54, 0xd3, 0xc4, 0x55, 0x5e, 0x56, + 0xd1, 0xd2, 0xde, 0xdd, 0x54, 0x5c, 0x45, 0x5d, + 0x55, 0x5d, 0x59, 0xd6, 0x55, 0x5a, 0xd3, 0xd9, + 0xd0, 0xdc, 0xd8, 0xd8, 0xc6, 0xca, 0xc6, 0xd1, + 0x5a, 0x7f, 0x7e, 0x4f, 0xdd, 0xd9, 0x57, 0x45, + 0x59, 0xd7, 0xdd, 0xc3, 0xc6, 0x54, 0x5c, 0xd4, + 0xdd, 0xdd, 0x5d, 0x43, 0x55, 0xdf, 0xda, 0xcc, + 0xc9, 0x54, 0x4f, 0x5c, 0x55, 0xd2, 0xd0, 0xd1, + 0x52, 0x5f, 0xdd, 0x53, 0x58, 0x53, 0xd6, 0xdd, + 0xd9, 0xdc, 0xc1, 0xd7, 0x4a, 0x4e, 0x47, 0x51, + 0xdf, 0xf5, 0xc6, 0x57, 0x5b, 0x75, 0x74, 0x55, + 0xf6, 0xdb, 0x5e, 0x50, 0xd4, 0xd3, 0x56, 0x58, + 0x5f, 0xd7, 0xdd, 0xde, 0xd2, 0xd5, 0x4d, 0x71, + 0x5f, 0xf4, 0xf2, 0xc0, 0x50, 0x41, 0x5c, 0xd0, + 0xd7, 0xdc, 0xd1, 0x45, 0x4e, 0x5c, 0x54, 0x5e, + 0x77, 0x72, 0x5a, 0xcf, 0xf2, 0xf4, 0xda, 0xd2, + 0xd6, 0x58, 0x5e, 0xdf, 0xc1, 0xc2, 0x57, 0x40, + 0x56, 0xd7, 0xd7, 0xd5, 0x56, 0x45, 0x43, 0x50, + 0xd9, 0xd2, 0x52, 0x5e, 0x5d, 0xd2, 0xd8, 0xd2, + 0x54, 0x58, 0x41, 0x43 +}; char packet_10[] = { -0x80, 0x08, 0x2c, 0x47, 0x11, 0x47, 0x34, 0x22, -0x58, 0xf3, 0x3d, 0xea, 0x56, 0xd4, 0xd6, 0x58, -0x42, 0x53, 0xc4, 0xf7, 0xcb, 0xf5, 0xf4, 0xc1, -0xd0, 0x4d, 0x45, 0xd6, 0x57, 0xd0, 0xd9, 0xdb, -0x50, 0x44, 0x59, 0x4b, 0x4f, 0xd6, 0xd8, 0x57, -0x5e, 0xd6, 0x57, 0xd0, 0xc5, 0xdf, 0xc6, 0xcd, -0xc5, 0x51, 0x50, 0xd0, 0xd6, 0xd2, 0xdb, 0x5d, -0x75, 0x75, 0x73, 0x75, 0xc0, 0xf7, 0xf0, 0xf6, -0xc9, 0xd8, 0xd5, 0x57, 0x56, 0x48, 0x70, 0x75, -0x42, 0x42, 0x5f, 0xd0, 0x5d, 0x5b, 0x5c, 0x55, -0xd6, 0xc1, 0xcf, 0xd8, 0xd3, 0xd0, 0x45, 0x4f, -0x54, 0xc6, 0xd0, 0x59, 0x55, 0xc4, 0xd1, 0x5a, -0x73, 0x7f, 0x47, 0x54, 0xd1, 0xdf, 0xdc, 0xd7, -0xc7, 0xc8, 0xdb, 0xc7, 0xca, 0xc9, 0xc0, 0xc7, -0xc1, 0x51, 0x40, 0x5f, 0x52, 0xd7, 0xda, 0xdf, -0x41, 0x4c, 0x56, 0x54, 0x5f, 0x4a, 0x4a, 0x4e, -0x5d, 0xc4, 0xc6, 0xcd, 0xc7, 0xd6, 0x52, 0xd4, -0xc4, 0xc4, 0xc6, 0xd5, 0x5b, 0x41, 0x4e, 0x56, -0xc4, 0xd8, 0x54, 0x5e, 0x4d, 0x48, 0x76, 0x73, -0x4d, 0x5b, 0x59, 0xd8, 0xf0, 0xf7, 0xde, 0x52, -0xd0, 0xc3, 0xfd, 0xfa, 0xfd, 0xc1, 0x40, 0x4a, -0x5a, 0x45, 0x5d, 0xd0 }; + 0x80, 0x08, 0x2c, 0x47, 0x11, 0x47, 0x34, 0x22, + 0x58, 0xf3, 0x3d, 0xea, 0x56, 0xd4, 0xd6, 0x58, + 0x42, 0x53, 0xc4, 0xf7, 0xcb, 0xf5, 0xf4, 0xc1, + 0xd0, 0x4d, 0x45, 0xd6, 0x57, 0xd0, 0xd9, 0xdb, + 0x50, 0x44, 0x59, 0x4b, 0x4f, 0xd6, 0xd8, 0x57, + 0x5e, 0xd6, 0x57, 0xd0, 0xc5, 0xdf, 0xc6, 0xcd, + 0xc5, 0x51, 0x50, 0xd0, 0xd6, 0xd2, 0xdb, 0x5d, + 0x75, 0x75, 0x73, 0x75, 0xc0, 0xf7, 0xf0, 0xf6, + 0xc9, 0xd8, 0xd5, 0x57, 0x56, 0x48, 0x70, 0x75, + 0x42, 0x42, 0x5f, 0xd0, 0x5d, 0x5b, 0x5c, 0x55, + 0xd6, 0xc1, 0xcf, 0xd8, 0xd3, 0xd0, 0x45, 0x4f, + 0x54, 0xc6, 0xd0, 0x59, 0x55, 0xc4, 0xd1, 0x5a, + 0x73, 0x7f, 0x47, 0x54, 0xd1, 0xdf, 0xdc, 0xd7, + 0xc7, 0xc8, 0xdb, 0xc7, 0xca, 0xc9, 0xc0, 0xc7, + 0xc1, 0x51, 0x40, 0x5f, 0x52, 0xd7, 0xda, 0xdf, + 0x41, 0x4c, 0x56, 0x54, 0x5f, 0x4a, 0x4a, 0x4e, + 0x5d, 0xc4, 0xc6, 0xcd, 0xc7, 0xd6, 0x52, 0xd4, + 0xc4, 0xc4, 0xc6, 0xd5, 0x5b, 0x41, 0x4e, 0x56, + 0xc4, 0xd8, 0x54, 0x5e, 0x4d, 0x48, 0x76, 0x73, + 0x4d, 0x5b, 0x59, 0xd8, 0xf0, 0xf7, 0xde, 0x52, + 0xd0, 0xc3, 0xfd, 0xfa, 0xfd, 0xc1, 0x40, 0x4a, + 0x5a, 0x45, 0x5d, 0xd0 +}; #define MAKE_TEST(n) \ /* deserialize the packet*/ \ @@ -310,21 +321,21 @@ char packet_10[] = { void test_parser() { - trtp_rtp_packet_t* packet; - tsk_buffer_t* buffer; - tsk_size_t i; + trtp_rtp_packet_t* packet; + tsk_buffer_t* buffer; + tsk_size_t i; - MAKE_TEST(0); - MAKE_TEST(1); - MAKE_TEST(2); - MAKE_TEST(3); - MAKE_TEST(4); - MAKE_TEST(5); - MAKE_TEST(6); - MAKE_TEST(7); - MAKE_TEST(8); - MAKE_TEST(9); - MAKE_TEST(10); + MAKE_TEST(0); + MAKE_TEST(1); + MAKE_TEST(2); + MAKE_TEST(3); + MAKE_TEST(4); + MAKE_TEST(5); + MAKE_TEST(6); + MAKE_TEST(7); + MAKE_TEST(8); + MAKE_TEST(9); + MAKE_TEST(10); } -- cgit v1.1