1 /* 2 * Copyright (c) 2004 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef MEDIA_BASE_FAKE_NETWORK_INTERFACE_H_ 12 #define MEDIA_BASE_FAKE_NETWORK_INTERFACE_H_ 13 14 #include <map> 15 #include <set> 16 #include <utility> 17 #include <vector> 18 19 #include "api/task_queue/pending_task_safety_flag.h" 20 #include "api/task_queue/task_queue_base.h" 21 #include "media/base/media_channel.h" 22 #include "media/base/rtp_utils.h" 23 #include "modules/rtp_rtcp/source/rtp_util.h" 24 #include "rtc_base/byte_order.h" 25 #include "rtc_base/checks.h" 26 #include "rtc_base/copy_on_write_buffer.h" 27 #include "rtc_base/dscp.h" 28 #include "rtc_base/synchronization/mutex.h" 29 #include "rtc_base/thread.h" 30 31 namespace cricket { 32 33 // Fake NetworkInterface that sends/receives RTP/RTCP packets. 34 class FakeNetworkInterface : public MediaChannel::NetworkInterface { 35 public: FakeNetworkInterface()36 FakeNetworkInterface() 37 : thread_(rtc::Thread::Current()), 38 dest_(NULL), 39 conf_(false), 40 sendbuf_size_(-1), 41 recvbuf_size_(-1), 42 dscp_(rtc::DSCP_NO_CHANGE) {} 43 SetDestination(MediaChannel * dest)44 void SetDestination(MediaChannel* dest) { dest_ = dest; } 45 46 // Conference mode is a mode where instead of simply forwarding the packets, 47 // the transport will send multiple copies of the packet with the specified 48 // SSRCs. This allows us to simulate receiving media from multiple sources. SetConferenceMode(bool conf,const std::vector<uint32_t> & ssrcs)49 void SetConferenceMode(bool conf, const std::vector<uint32_t>& ssrcs) 50 RTC_LOCKS_EXCLUDED(mutex_) { 51 webrtc::MutexLock lock(&mutex_); 52 conf_ = conf; 53 conf_sent_ssrcs_ = ssrcs; 54 } 55 NumRtpBytes()56 int NumRtpBytes() RTC_LOCKS_EXCLUDED(mutex_) { 57 webrtc::MutexLock lock(&mutex_); 58 int bytes = 0; 59 for (size_t i = 0; i < rtp_packets_.size(); ++i) { 60 bytes += static_cast<int>(rtp_packets_[i].size()); 61 } 62 return bytes; 63 } 64 NumRtpBytes(uint32_t ssrc)65 int NumRtpBytes(uint32_t ssrc) RTC_LOCKS_EXCLUDED(mutex_) { 66 webrtc::MutexLock lock(&mutex_); 67 int bytes = 0; 68 GetNumRtpBytesAndPackets(ssrc, &bytes, NULL); 69 return bytes; 70 } 71 NumRtpPackets()72 int NumRtpPackets() RTC_LOCKS_EXCLUDED(mutex_) { 73 webrtc::MutexLock lock(&mutex_); 74 return static_cast<int>(rtp_packets_.size()); 75 } 76 NumRtpPackets(uint32_t ssrc)77 int NumRtpPackets(uint32_t ssrc) RTC_LOCKS_EXCLUDED(mutex_) { 78 webrtc::MutexLock lock(&mutex_); 79 int packets = 0; 80 GetNumRtpBytesAndPackets(ssrc, NULL, &packets); 81 return packets; 82 } 83 NumSentSsrcs()84 int NumSentSsrcs() RTC_LOCKS_EXCLUDED(mutex_) { 85 webrtc::MutexLock lock(&mutex_); 86 return static_cast<int>(sent_ssrcs_.size()); 87 } 88 GetRtpPacket(int index)89 rtc::CopyOnWriteBuffer GetRtpPacket(int index) RTC_LOCKS_EXCLUDED(mutex_) { 90 webrtc::MutexLock lock(&mutex_); 91 if (index >= static_cast<int>(rtp_packets_.size())) { 92 return {}; 93 } 94 return rtp_packets_[index]; 95 } 96 NumRtcpPackets()97 int NumRtcpPackets() RTC_LOCKS_EXCLUDED(mutex_) { 98 webrtc::MutexLock lock(&mutex_); 99 return static_cast<int>(rtcp_packets_.size()); 100 } 101 102 // Note: callers are responsible for deleting the returned buffer. GetRtcpPacket(int index)103 const rtc::CopyOnWriteBuffer* GetRtcpPacket(int index) 104 RTC_LOCKS_EXCLUDED(mutex_) { 105 webrtc::MutexLock lock(&mutex_); 106 if (index >= static_cast<int>(rtcp_packets_.size())) { 107 return NULL; 108 } 109 return new rtc::CopyOnWriteBuffer(rtcp_packets_[index]); 110 } 111 sendbuf_size()112 int sendbuf_size() const { return sendbuf_size_; } recvbuf_size()113 int recvbuf_size() const { return recvbuf_size_; } dscp()114 rtc::DiffServCodePoint dscp() const { return dscp_; } options()115 rtc::PacketOptions options() const { return options_; } 116 117 protected: SendPacket(rtc::CopyOnWriteBuffer * packet,const rtc::PacketOptions & options)118 virtual bool SendPacket(rtc::CopyOnWriteBuffer* packet, 119 const rtc::PacketOptions& options) 120 RTC_LOCKS_EXCLUDED(mutex_) { 121 if (!webrtc::IsRtpPacket(*packet)) { 122 return false; 123 } 124 125 webrtc::MutexLock lock(&mutex_); 126 sent_ssrcs_[webrtc::ParseRtpSsrc(*packet)]++; 127 options_ = options; 128 129 rtp_packets_.push_back(*packet); 130 if (conf_) { 131 for (size_t i = 0; i < conf_sent_ssrcs_.size(); ++i) { 132 SetRtpSsrc(conf_sent_ssrcs_[i], *packet); 133 PostPacket(*packet); 134 } 135 } else { 136 PostPacket(*packet); 137 } 138 return true; 139 } 140 SendRtcp(rtc::CopyOnWriteBuffer * packet,const rtc::PacketOptions & options)141 virtual bool SendRtcp(rtc::CopyOnWriteBuffer* packet, 142 const rtc::PacketOptions& options) 143 RTC_LOCKS_EXCLUDED(mutex_) { 144 webrtc::MutexLock lock(&mutex_); 145 rtcp_packets_.push_back(*packet); 146 options_ = options; 147 if (!conf_) { 148 // don't worry about RTCP in conf mode for now 149 RTC_LOG(LS_VERBOSE) << "Dropping RTCP packet, they are not handled by " 150 "MediaChannel anymore."; 151 } 152 return true; 153 } 154 SetOption(SocketType type,rtc::Socket::Option opt,int option)155 virtual int SetOption(SocketType type, rtc::Socket::Option opt, int option) { 156 if (opt == rtc::Socket::OPT_SNDBUF) { 157 sendbuf_size_ = option; 158 } else if (opt == rtc::Socket::OPT_RCVBUF) { 159 recvbuf_size_ = option; 160 } else if (opt == rtc::Socket::OPT_DSCP) { 161 dscp_ = static_cast<rtc::DiffServCodePoint>(option); 162 } 163 return 0; 164 } 165 PostPacket(rtc::CopyOnWriteBuffer packet)166 void PostPacket(rtc::CopyOnWriteBuffer packet) { 167 thread_->PostTask( 168 SafeTask(safety_.flag(), [this, packet = std::move(packet)]() mutable { 169 if (dest_) { 170 dest_->OnPacketReceived(std::move(packet), rtc::TimeMicros()); 171 } 172 })); 173 } 174 175 private: SetRtpSsrc(uint32_t ssrc,rtc::CopyOnWriteBuffer & buffer)176 void SetRtpSsrc(uint32_t ssrc, rtc::CopyOnWriteBuffer& buffer) { 177 RTC_CHECK_GE(buffer.size(), 12); 178 rtc::SetBE32(buffer.MutableData() + 8, ssrc); 179 } 180 GetNumRtpBytesAndPackets(uint32_t ssrc,int * bytes,int * packets)181 void GetNumRtpBytesAndPackets(uint32_t ssrc, int* bytes, int* packets) { 182 if (bytes) { 183 *bytes = 0; 184 } 185 if (packets) { 186 *packets = 0; 187 } 188 for (size_t i = 0; i < rtp_packets_.size(); ++i) { 189 if (ssrc == webrtc::ParseRtpSsrc(rtp_packets_[i])) { 190 if (bytes) { 191 *bytes += static_cast<int>(rtp_packets_[i].size()); 192 } 193 if (packets) { 194 ++(*packets); 195 } 196 } 197 } 198 } 199 200 webrtc::TaskQueueBase* thread_; 201 MediaChannel* dest_; 202 bool conf_; 203 // The ssrcs used in sending out packets in conference mode. 204 std::vector<uint32_t> conf_sent_ssrcs_; 205 // Map to track counts of packets that have been sent per ssrc. 206 // This includes packets that are dropped. 207 std::map<uint32_t, uint32_t> sent_ssrcs_; 208 // Map to track packet-number that needs to be dropped per ssrc. 209 std::map<uint32_t, std::set<uint32_t> > drop_map_; 210 webrtc::Mutex mutex_; 211 std::vector<rtc::CopyOnWriteBuffer> rtp_packets_; 212 std::vector<rtc::CopyOnWriteBuffer> rtcp_packets_; 213 int sendbuf_size_; 214 int recvbuf_size_; 215 rtc::DiffServCodePoint dscp_; 216 // Options of the most recently sent packet. 217 rtc::PacketOptions options_; 218 webrtc::ScopedTaskSafety safety_; 219 }; 220 221 } // namespace cricket 222 223 #endif // MEDIA_BASE_FAKE_NETWORK_INTERFACE_H_ 224