blob: d0f277e8f42d0b3d01b3eb9612af532080ec2dd4 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
2 * libjingle
3 * Copyright 2004 Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#ifndef TALK_MEDIA_BASE_FAKENETWORKINTERFACE_H_
29#define TALK_MEDIA_BASE_FAKENETWORKINTERFACE_H_
30
31#include <vector>
32#include <map>
33
34#include "talk/base/buffer.h"
35#include "talk/base/byteorder.h"
36#include "talk/base/criticalsection.h"
37#include "talk/base/messagehandler.h"
38#include "talk/base/messagequeue.h"
39#include "talk/base/thread.h"
40#include "talk/media/base/mediachannel.h"
41#include "talk/media/base/rtputils.h"
42
43namespace cricket {
44
45// Fake NetworkInterface that sends/receives RTP/RTCP packets.
46class FakeNetworkInterface : public MediaChannel::NetworkInterface,
47 public talk_base::MessageHandler {
48 public:
49 FakeNetworkInterface()
50 : thread_(talk_base::Thread::Current()),
51 dest_(NULL),
52 conf_(false),
53 sendbuf_size_(-1),
54 recvbuf_size_(-1) {
55 }
56
57 void SetDestination(MediaChannel* dest) { dest_ = dest; }
58
59 // Conference mode is a mode where instead of simply forwarding the packets,
60 // the transport will send multiple copies of the packet with the specified
61 // SSRCs. This allows us to simulate receiving media from multiple sources.
62 void SetConferenceMode(bool conf, const std::vector<uint32>& ssrcs) {
63 talk_base::CritScope cs(&crit_);
64 conf_ = conf;
65 conf_sent_ssrcs_ = ssrcs;
66 }
67
68 int NumRtpBytes() {
69 talk_base::CritScope cs(&crit_);
70 int bytes = 0;
71 for (size_t i = 0; i < rtp_packets_.size(); ++i) {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +000072 bytes += static_cast<int>(rtp_packets_[i].length());
henrike@webrtc.org28e20752013-07-10 00:45:36 +000073 }
74 return bytes;
75 }
76
77 int NumRtpBytes(uint32 ssrc) {
78 talk_base::CritScope cs(&crit_);
79 int bytes = 0;
80 GetNumRtpBytesAndPackets(ssrc, &bytes, NULL);
81 return bytes;
82 }
83
84 int NumRtpPackets() {
85 talk_base::CritScope cs(&crit_);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +000086 return static_cast<int>(rtp_packets_.size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +000087 }
88
89 int NumRtpPackets(uint32 ssrc) {
90 talk_base::CritScope cs(&crit_);
91 int packets = 0;
92 GetNumRtpBytesAndPackets(ssrc, NULL, &packets);
93 return packets;
94 }
95
96 int NumSentSsrcs() {
97 talk_base::CritScope cs(&crit_);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +000098 return static_cast<int>(sent_ssrcs_.size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +000099 }
100
101 // Note: callers are responsible for deleting the returned buffer.
102 const talk_base::Buffer* GetRtpPacket(int index) {
103 talk_base::CritScope cs(&crit_);
104 if (index >= NumRtpPackets()) {
105 return NULL;
106 }
107 return new talk_base::Buffer(rtp_packets_[index]);
108 }
109
110 int NumRtcpPackets() {
111 talk_base::CritScope cs(&crit_);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000112 return static_cast<int>(rtcp_packets_.size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000113 }
114
115 // Note: callers are responsible for deleting the returned buffer.
116 const talk_base::Buffer* GetRtcpPacket(int index) {
117 talk_base::CritScope cs(&crit_);
118 if (index >= NumRtcpPackets()) {
119 return NULL;
120 }
121 return new talk_base::Buffer(rtcp_packets_[index]);
122 }
123
124 // Indicate that |n|'th packet for |ssrc| should be dropped.
125 void AddPacketDrop(uint32 ssrc, uint32 n) {
126 drop_map_[ssrc].insert(n);
127 }
128
129 int sendbuf_size() const { return sendbuf_size_; }
130 int recvbuf_size() const { return recvbuf_size_; }
131
132 protected:
mallinath@webrtc.org1112c302013-09-23 20:34:45 +0000133 virtual bool SendPacket(talk_base::Buffer* packet,
134 talk_base::DiffServCodePoint dscp) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000135 talk_base::CritScope cs(&crit_);
136
137 uint32 cur_ssrc = 0;
138 if (!GetRtpSsrc(packet->data(), packet->length(), &cur_ssrc)) {
139 return false;
140 }
141 sent_ssrcs_[cur_ssrc]++;
142
143 // Check if we need to drop this packet.
144 std::map<uint32, std::set<uint32> >::iterator itr =
145 drop_map_.find(cur_ssrc);
146 if (itr != drop_map_.end() &&
147 itr->second.count(sent_ssrcs_[cur_ssrc]) > 0) {
148 // "Drop" the packet.
149 return true;
150 }
151
152 rtp_packets_.push_back(*packet);
153 if (conf_) {
154 talk_base::Buffer buffer_copy(*packet);
155 for (size_t i = 0; i < conf_sent_ssrcs_.size(); ++i) {
156 if (!SetRtpSsrc(buffer_copy.data(), buffer_copy.length(),
157 conf_sent_ssrcs_[i])) {
158 return false;
159 }
160 PostMessage(ST_RTP, buffer_copy);
161 }
162 } else {
163 PostMessage(ST_RTP, *packet);
164 }
165 return true;
166 }
167
mallinath@webrtc.org1112c302013-09-23 20:34:45 +0000168 virtual bool SendRtcp(talk_base::Buffer* packet,
169 talk_base::DiffServCodePoint dscp) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000170 talk_base::CritScope cs(&crit_);
171 rtcp_packets_.push_back(*packet);
172 if (!conf_) {
173 // don't worry about RTCP in conf mode for now
174 PostMessage(ST_RTCP, *packet);
175 }
176 return true;
177 }
178
179 virtual int SetOption(SocketType type, talk_base::Socket::Option opt,
180 int option) {
181 if (opt == talk_base::Socket::OPT_SNDBUF) {
182 sendbuf_size_ = option;
183 } else if (opt == talk_base::Socket::OPT_RCVBUF) {
184 recvbuf_size_ = option;
185 }
186 return 0;
187 }
188
189 void PostMessage(int id, const talk_base::Buffer& packet) {
190 thread_->Post(this, id, talk_base::WrapMessageData(packet));
191 }
192
193 virtual void OnMessage(talk_base::Message* msg) {
194 talk_base::TypedMessageData<talk_base::Buffer>* msg_data =
195 static_cast<talk_base::TypedMessageData<talk_base::Buffer>*>(
196 msg->pdata);
197 if (dest_) {
198 if (msg->message_id == ST_RTP) {
199 dest_->OnPacketReceived(&msg_data->data());
200 } else {
201 dest_->OnRtcpReceived(&msg_data->data());
202 }
203 }
204 delete msg_data;
205 }
206
207 private:
208 void GetNumRtpBytesAndPackets(uint32 ssrc, int* bytes, int* packets) {
209 if (bytes) {
210 *bytes = 0;
211 }
212 if (packets) {
213 *packets = 0;
214 }
215 uint32 cur_ssrc = 0;
216 for (size_t i = 0; i < rtp_packets_.size(); ++i) {
217 if (!GetRtpSsrc(rtp_packets_[i].data(),
218 rtp_packets_[i].length(), &cur_ssrc)) {
219 return;
220 }
221 if (ssrc == cur_ssrc) {
222 if (bytes) {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000223 *bytes += static_cast<int>(rtp_packets_[i].length());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000224 }
225 if (packets) {
226 ++(*packets);
227 }
228 }
229 }
230 }
231
232 talk_base::Thread* thread_;
233 MediaChannel* dest_;
234 bool conf_;
235 // The ssrcs used in sending out packets in conference mode.
236 std::vector<uint32> conf_sent_ssrcs_;
237 // Map to track counts of packets that have been sent per ssrc.
238 // This includes packets that are dropped.
239 std::map<uint32, uint32> sent_ssrcs_;
240 // Map to track packet-number that needs to be dropped per ssrc.
241 std::map<uint32, std::set<uint32> > drop_map_;
242 talk_base::CriticalSection crit_;
243 std::vector<talk_base::Buffer> rtp_packets_;
244 std::vector<talk_base::Buffer> rtcp_packets_;
245 int sendbuf_size_;
246 int recvbuf_size_;
247};
248
249} // namespace cricket
250
251#endif // TALK_MEDIA_BASE_FAKENETWORKINTERFACE_H_