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