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 <vector> 17 18 #include "media/base/media_channel.h" 19 #include "media/base/rtp_utils.h" 20 #include "rtc_base/byte_order.h" 21 #include "rtc_base/copy_on_write_buffer.h" 22 #include "rtc_base/dscp.h" 23 #include "rtc_base/message_handler.h" 24 #include "rtc_base/synchronization/mutex.h" 25 #include "rtc_base/thread.h" 26 27 namespace cricket { 28 29 // Fake NetworkInterface that sends/receives RTP/RTCP packets. 30 class FakeNetworkInterface : public MediaChannel::NetworkInterface, 31 public rtc::MessageHandler { 32 public: FakeNetworkInterface()33 FakeNetworkInterface() 34 : thread_(rtc::Thread::Current()), 35 dest_(NULL), 36 conf_(false), 37 sendbuf_size_(-1), 38 recvbuf_size_(-1), 39 dscp_(rtc::DSCP_NO_CHANGE) {} 40 SetDestination(MediaChannel * dest)41 void SetDestination(MediaChannel* dest) { dest_ = dest; } 42 43 // Conference mode is a mode where instead of simply forwarding the packets, 44 // the transport will send multiple copies of the packet with the specified 45 // SSRCs. This allows us to simulate receiving media from multiple sources. SetConferenceMode(bool conf,const std::vector<uint32_t> & ssrcs)46 void SetConferenceMode(bool conf, const std::vector<uint32_t>& ssrcs) 47 RTC_LOCKS_EXCLUDED(mutex_) { 48 webrtc::MutexLock lock(&mutex_); 49 conf_ = conf; 50 conf_sent_ssrcs_ = ssrcs; 51 } 52 NumRtpBytes()53 int NumRtpBytes() RTC_LOCKS_EXCLUDED(mutex_) { 54 webrtc::MutexLock lock(&mutex_); 55 int bytes = 0; 56 for (size_t i = 0; i < rtp_packets_.size(); ++i) { 57 bytes += static_cast<int>(rtp_packets_[i].size()); 58 } 59 return bytes; 60 } 61 NumRtpBytes(uint32_t ssrc)62 int NumRtpBytes(uint32_t ssrc) RTC_LOCKS_EXCLUDED(mutex_) { 63 webrtc::MutexLock lock(&mutex_); 64 int bytes = 0; 65 GetNumRtpBytesAndPackets(ssrc, &bytes, NULL); 66 return bytes; 67 } 68 NumRtpPackets()69 int NumRtpPackets() RTC_LOCKS_EXCLUDED(mutex_) { 70 webrtc::MutexLock lock(&mutex_); 71 return static_cast<int>(rtp_packets_.size()); 72 } 73 NumRtpPackets(uint32_t ssrc)74 int NumRtpPackets(uint32_t ssrc) RTC_LOCKS_EXCLUDED(mutex_) { 75 webrtc::MutexLock lock(&mutex_); 76 int packets = 0; 77 GetNumRtpBytesAndPackets(ssrc, NULL, &packets); 78 return packets; 79 } 80 NumSentSsrcs()81 int NumSentSsrcs() RTC_LOCKS_EXCLUDED(mutex_) { 82 webrtc::MutexLock lock(&mutex_); 83 return static_cast<int>(sent_ssrcs_.size()); 84 } 85 86 // Note: callers are responsible for deleting the returned buffer. GetRtpPacket(int index)87 const rtc::CopyOnWriteBuffer* GetRtpPacket(int index) 88 RTC_LOCKS_EXCLUDED(mutex_) { 89 webrtc::MutexLock lock(&mutex_); 90 if (index >= static_cast<int>(rtp_packets_.size())) { 91 return NULL; 92 } 93 return new rtc::CopyOnWriteBuffer(rtp_packets_[index]); 94 } 95 NumRtcpPackets()96 int NumRtcpPackets() RTC_LOCKS_EXCLUDED(mutex_) { 97 webrtc::MutexLock lock(&mutex_); 98 return static_cast<int>(rtcp_packets_.size()); 99 } 100 101 // Note: callers are responsible for deleting the returned buffer. GetRtcpPacket(int index)102 const rtc::CopyOnWriteBuffer* GetRtcpPacket(int index) 103 RTC_LOCKS_EXCLUDED(mutex_) { 104 webrtc::MutexLock lock(&mutex_); 105 if (index >= static_cast<int>(rtcp_packets_.size())) { 106 return NULL; 107 } 108 return new rtc::CopyOnWriteBuffer(rtcp_packets_[index]); 109 } 110 sendbuf_size()111 int sendbuf_size() const { return sendbuf_size_; } recvbuf_size()112 int recvbuf_size() const { return recvbuf_size_; } dscp()113 rtc::DiffServCodePoint dscp() const { return dscp_; } options()114 rtc::PacketOptions options() const { return options_; } 115 116 protected: SendPacket(rtc::CopyOnWriteBuffer * packet,const rtc::PacketOptions & options)117 virtual bool SendPacket(rtc::CopyOnWriteBuffer* packet, 118 const rtc::PacketOptions& options) 119 RTC_LOCKS_EXCLUDED(mutex_) { 120 webrtc::MutexLock lock(&mutex_); 121 122 uint32_t cur_ssrc = 0; 123 if (!GetRtpSsrc(packet->data(), packet->size(), &cur_ssrc)) { 124 return false; 125 } 126 sent_ssrcs_[cur_ssrc]++; 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 if (!SetRtpSsrc(packet->data(), packet->size(), conf_sent_ssrcs_[i])) { 133 return false; 134 } 135 PostMessage(ST_RTP, *packet); 136 } 137 } else { 138 PostMessage(ST_RTP, *packet); 139 } 140 return true; 141 } 142 SendRtcp(rtc::CopyOnWriteBuffer * packet,const rtc::PacketOptions & options)143 virtual bool SendRtcp(rtc::CopyOnWriteBuffer* packet, 144 const rtc::PacketOptions& options) 145 RTC_LOCKS_EXCLUDED(mutex_) { 146 webrtc::MutexLock lock(&mutex_); 147 rtcp_packets_.push_back(*packet); 148 options_ = options; 149 if (!conf_) { 150 // don't worry about RTCP in conf mode for now 151 PostMessage(ST_RTCP, *packet); 152 } 153 return true; 154 } 155 SetOption(SocketType type,rtc::Socket::Option opt,int option)156 virtual int SetOption(SocketType type, rtc::Socket::Option opt, int option) { 157 if (opt == rtc::Socket::OPT_SNDBUF) { 158 sendbuf_size_ = option; 159 } else if (opt == rtc::Socket::OPT_RCVBUF) { 160 recvbuf_size_ = option; 161 } else if (opt == rtc::Socket::OPT_DSCP) { 162 dscp_ = static_cast<rtc::DiffServCodePoint>(option); 163 } 164 return 0; 165 } 166 PostMessage(int id,const rtc::CopyOnWriteBuffer & packet)167 void PostMessage(int id, const rtc::CopyOnWriteBuffer& packet) { 168 thread_->Post(RTC_FROM_HERE, this, id, rtc::WrapMessageData(packet)); 169 } 170 OnMessage(rtc::Message * msg)171 virtual void OnMessage(rtc::Message* msg) { 172 rtc::TypedMessageData<rtc::CopyOnWriteBuffer>* msg_data = 173 static_cast<rtc::TypedMessageData<rtc::CopyOnWriteBuffer>*>(msg->pdata); 174 if (dest_) { 175 if (msg->message_id == ST_RTP) { 176 dest_->OnPacketReceived(msg_data->data(), rtc::TimeMicros()); 177 } else { 178 RTC_LOG(LS_VERBOSE) << "Dropping RTCP packet, they not handled by " 179 "MediaChannel anymore."; 180 } 181 } 182 delete msg_data; 183 } 184 185 private: GetNumRtpBytesAndPackets(uint32_t ssrc,int * bytes,int * packets)186 void GetNumRtpBytesAndPackets(uint32_t ssrc, int* bytes, int* packets) { 187 if (bytes) { 188 *bytes = 0; 189 } 190 if (packets) { 191 *packets = 0; 192 } 193 uint32_t cur_ssrc = 0; 194 for (size_t i = 0; i < rtp_packets_.size(); ++i) { 195 if (!GetRtpSsrc(rtp_packets_[i].data(), rtp_packets_[i].size(), 196 &cur_ssrc)) { 197 return; 198 } 199 if (ssrc == cur_ssrc) { 200 if (bytes) { 201 *bytes += static_cast<int>(rtp_packets_[i].size()); 202 } 203 if (packets) { 204 ++(*packets); 205 } 206 } 207 } 208 } 209 210 rtc::Thread* thread_; 211 MediaChannel* dest_; 212 bool conf_; 213 // The ssrcs used in sending out packets in conference mode. 214 std::vector<uint32_t> conf_sent_ssrcs_; 215 // Map to track counts of packets that have been sent per ssrc. 216 // This includes packets that are dropped. 217 std::map<uint32_t, uint32_t> sent_ssrcs_; 218 // Map to track packet-number that needs to be dropped per ssrc. 219 std::map<uint32_t, std::set<uint32_t> > drop_map_; 220 webrtc::Mutex mutex_; 221 std::vector<rtc::CopyOnWriteBuffer> rtp_packets_; 222 std::vector<rtc::CopyOnWriteBuffer> rtcp_packets_; 223 int sendbuf_size_; 224 int recvbuf_size_; 225 rtc::DiffServCodePoint dscp_; 226 // Options of the most recently sent packet. 227 rtc::PacketOptions options_; 228 }; 229 230 } // namespace cricket 231 232 #endif // MEDIA_BASE_FAKE_NETWORK_INTERFACE_H_ 233