Line data Source code
1 : /* 2 : * Copyright (C) 2004-2024 Savoir-faire Linux Inc. 3 : * Copyright (C) 2012 VLC authors and VideoLAN 4 : * 5 : * This program is free software: you can redistribute it and/or modify 6 : * it under the terms of the GNU General Public License as published by 7 : * the Free Software Foundation, either version 3 of the License, or 8 : * (at your option) any later version. 9 : * 10 : * This program is distributed in the hope that it will be useful, 11 : * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 : * GNU General Public License for more details. 14 : * 15 : * You should have received a copy of the GNU General Public License 16 : * along with this program. If not, see <https://www.gnu.org/licenses/>. 17 : */ 18 : #pragma once 19 : 20 : #ifdef HAVE_CONFIG_H 21 : #include <config.h> 22 : #endif 23 : 24 : #include "media_io_handle.h" 25 : 26 : #ifndef _WIN32 27 : #include <sys/socket.h> 28 : #include <netdb.h> 29 : #include <poll.h> 30 : #else 31 : #include <winsock2.h> 32 : #include <ws2tcpip.h> 33 : using socklen_t = int; 34 : #endif 35 : 36 : #include <dhtnet/ip_utils.h> 37 : #include <dhtnet/ice_socket.h> 38 : 39 : #include <cstdint> 40 : #include <mutex> 41 : #include <memory> 42 : #include <atomic> 43 : #include <list> 44 : #include <vector> 45 : #include <condition_variable> 46 : #include <functional> 47 : 48 : namespace jami { 49 : 50 : class SRTPProtoContext; 51 : 52 : typedef struct 53 : { 54 : #ifdef WORDS_BIGENDIAN 55 : uint32_t version : 2; /* protocol version */ 56 : uint32_t p : 1; /* padding flag */ 57 : uint32_t rc : 5; /* reception report count must be 201 for report */ 58 : 59 : #else 60 : uint32_t rc : 5; /* reception report count must be 201 for report */ 61 : uint32_t p : 1; /* padding flag */ 62 : uint32_t version : 2; /* protocol version */ 63 : #endif 64 : uint32_t pt : 8; /* payload type */ 65 : uint32_t len : 16; /* length of RTCP packet */ 66 : uint32_t ssrc; /* synchronization source identifier of packet send */ 67 : uint32_t id; /* synchronization source identifier of first source */ 68 : uint32_t fraction_lost : 8; /* 8 bits of fraction, 24 bits of total packets lost */ 69 : uint32_t cum_lost_packet : 24; /* cumulative number packet lost */ 70 : uint32_t ext_high; /* Extended highest sequence number received */ 71 : uint32_t jitter; /* jitter */ 72 : uint32_t lsr; /* last SR timestamp */ 73 : uint32_t dlsr; /* Delay since last SR timestamp */ 74 : } rtcpRRHeader; 75 : 76 : typedef struct 77 : { 78 : #ifdef WORDS_BIGENDIAN 79 : uint32_t version : 2; /* protocol version */ 80 : uint32_t p : 1; /* padding flag */ 81 : uint32_t rc : 5; /* reception report count must be 201 for report */ 82 : 83 : #else 84 : uint32_t rc : 5; /* reception report count must be 201 for report */ 85 : uint32_t p : 1; /* padding flag */ 86 : uint32_t version : 2; /* protocol version */ 87 : #endif 88 : uint32_t pt : 8; /* payload type */ 89 : uint32_t len : 16; /* length of RTCP packet */ 90 : uint32_t ssrc; /* synchronization source identifier of packet send */ 91 : uint32_t timestampMSB; /* timestamp MSB */ 92 : uint32_t timestampLSB; /* timestamp LSB */ 93 : uint32_t timestampRTP; /* RTP timestamp */ 94 : uint32_t spc; /* Sender's packet count */ 95 : uint32_t soc; /* Sender's octet count */ 96 : } rtcpSRHeader; 97 : 98 : typedef struct 99 : { 100 : #ifdef WORDS_BIGENDIAN 101 : uint32_t version : 2; /* protocol version */ 102 : uint32_t p : 1; /* padding flag always 0 */ 103 : uint32_t fmt : 5; /* Feedback message type always 15 */ 104 : 105 : #else 106 : uint32_t fmt : 5; /* Feedback message type always 15 */ 107 : uint32_t p : 1; /* padding flag always 0 */ 108 : uint32_t version : 2; /* protocol version */ 109 : #endif 110 : uint32_t pt : 8; /* payload type */ 111 : uint32_t len : 16; /* length of RTCP packet */ 112 : uint32_t ssrc; /* synchronization source identifier of packet sender */ 113 : uint32_t ssrc_source; /* synchronization source identifier of first source alway 0*/ 114 : uint32_t uid; /* Unique identifier Always ‘R’ ‘E’ ‘M’ ‘B’ (4 ASCII characters). */ 115 : uint32_t n_ssrc : 8; /* Number of SSRCs in this message. */ 116 : uint32_t br_exp : 6; /* BR Exp */ 117 : uint32_t br_mantis : 18; /* BR Mantissa */ 118 : uint32_t f_ssrc; /* SSRC feedback */ 119 : } rtcpREMBHeader; 120 : 121 : typedef struct 122 : { 123 : uint64_t last_send_ts; 124 : std::chrono::steady_clock::time_point last_receive_ts; 125 : uint64_t send_ts; 126 : std::chrono::steady_clock::time_point receive_ts; 127 : } TS_Frame; 128 : 129 : class SocketPair 130 : { 131 : public: 132 : SocketPair(const char* uri, int localPort); 133 : SocketPair(std::unique_ptr<dhtnet::IceSocket> rtp_sock, std::unique_ptr<dhtnet::IceSocket> rtcp_sock); 134 : ~SocketPair(); 135 : 136 : void interrupt(); 137 : 138 : // Set the read blocking mode. 139 : // By default, the read operation will block until data is available 140 : // on the socket. This method allows to switch to unblocking mode 141 : // if to stop the receiver thread to exit and there is no more data 142 : // to read (if the peer mutes/stops the media/RTP stream). 143 : void setReadBlockingMode(bool blocking); 144 : 145 : MediaIOHandle* createIOContext(const uint16_t mtu); 146 : 147 : void openSockets(const char* uri, int localPort); 148 : void closeSockets(); 149 : 150 : /* 151 : Supported suites are: 152 : 153 : AES_CM_128_HMAC_SHA1_80 154 : SRTP_AES128_CM_HMAC_SHA1_80 155 : AES_CM_128_HMAC_SHA1_32 156 : SRTP_AES128_CM_HMAC_SHA1_3 157 : 158 : Example (unsecure) usage: 159 : createSRTP("AES_CM_128_HMAC_SHA1_80", 160 : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn", 161 : "AES_CM_128_HMAC_SHA1_80", 162 : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn"); 163 : 164 : Will throw an std::runtime_error on failure, should be handled at a higher level 165 : */ 166 : void createSRTP(const char* out_suite, 167 : const char* out_params, 168 : const char* in_suite, 169 : const char* in_params); 170 : 171 : void stopSendOp(bool state = true); 172 : std::list<rtcpRRHeader> getRtcpRR(); 173 : std::list<rtcpREMBHeader> getRtcpREMB(); 174 : 175 : bool waitForRTCP(std::chrono::seconds interval); 176 : double getLastLatency(); 177 : 178 152 : void setPacketLossCallback(std::function<void(void)> cb) 179 : { 180 152 : packetLossCallback_ = std::move(cb); 181 152 : } 182 : void setRtpDelayCallback(std::function<void(int, int)> cb); 183 : 184 : int writeData(uint8_t* buf, int buf_size); 185 : 186 : uint16_t lastSeqValOut(); 187 : 188 : private: 189 : NON_COPYABLE(SocketPair); 190 : using clock = std::chrono::steady_clock; 191 : using time_point = clock::time_point; 192 : 193 : int readCallback(uint8_t* buf, int buf_size); 194 : int writeCallback(uint8_t* buf, int buf_size); 195 : 196 : int waitForData(); 197 : int readRtpData(void* buf, int buf_size); 198 : int readRtcpData(void* buf, int buf_size); 199 : void saveRtcpRRPacket(uint8_t* buf, size_t len); 200 : void saveRtcpREMBPacket(uint8_t* buf, size_t len); 201 : 202 : std::mutex dataBuffMutex_; 203 : std::condition_variable cv_; 204 : std::list<std::vector<uint8_t>> rtpDataBuff_; 205 : std::list<std::vector<uint8_t>> rtcpDataBuff_; 206 : 207 : std::unique_ptr<dhtnet::IceSocket> rtp_sock_; 208 : std::unique_ptr<dhtnet::IceSocket> rtcp_sock_; 209 : 210 : int rtpHandle_ {-1}; 211 : int rtcpHandle_ {-1}; 212 : dhtnet::IpAddr rtpDestAddr_; 213 : dhtnet::IpAddr rtcpDestAddr_; 214 : std::atomic_bool interrupted_ {false}; 215 : // Read operations are blocking. This will allow unblocking the 216 : // receiver thread if the peer stops/mutes the media (RTP) 217 : std::atomic_bool readBlockingMode_ {false}; 218 : std::atomic_bool noWrite_ {false}; 219 : std::unique_ptr<SRTPProtoContext> srtpContext_; 220 : std::function<void(void)> packetLossCallback_; 221 : std::function<void(int, int)> rtpDelayCallback_; 222 : bool getOneWayDelayGradient(float sendTS, bool marker, int32_t* gradient, int32_t* deltaR); 223 : bool parse_RTP_ext(uint8_t* buf, float* abs); 224 : 225 : std::list<rtcpRRHeader> listRtcpRRHeader_; 226 : std::list<rtcpREMBHeader> listRtcpREMBHeader_; 227 : std::mutex rtcpInfo_mutex_; 228 : std::condition_variable cvRtcpPacketReadyToRead_; 229 : static constexpr unsigned MAX_LIST_SIZE {10}; 230 : 231 : mutable std::atomic_bool rtcpPacketLoss_ {false}; 232 : double lastSRTS_ {}; 233 : uint32_t lastDLSR_ {}; 234 : 235 : std::list<double> histoLatency_; 236 : 237 : time_point lastRR_time; 238 : uint16_t lastSeqNumIn_ {0}; 239 : float lastSendTS_ {0.0f}; 240 : time_point lastReceiveTS_ {}; 241 : time_point arrival_TS {}; 242 : 243 : TS_Frame svgTS = {}; 244 : }; 245 : 246 : } // namespace jami