blob: 2fdd1d4a39abc97f6eced33ddb65a4cf66d1abc8 [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:
133 virtual bool SendPacket(talk_base::Buffer* packet) {
134 talk_base::CritScope cs(&crit_);
135
136 uint32 cur_ssrc = 0;
137 if (!GetRtpSsrc(packet->data(), packet->length(), &cur_ssrc)) {
138 return false;
139 }
140 sent_ssrcs_[cur_ssrc]++;
141
142 // Check if we need to drop this packet.
143 std::map<uint32, std::set<uint32> >::iterator itr =
144 drop_map_.find(cur_ssrc);
145 if (itr != drop_map_.end() &&
146 itr->second.count(sent_ssrcs_[cur_ssrc]) > 0) {
147 // "Drop" the packet.
148 return true;
149 }
150
151 rtp_packets_.push_back(*packet);
152 if (conf_) {
153 talk_base::Buffer buffer_copy(*packet);
154 for (size_t i = 0; i < conf_sent_ssrcs_.size(); ++i) {
155 if (!SetRtpSsrc(buffer_copy.data(), buffer_copy.length(),
156 conf_sent_ssrcs_[i])) {
157 return false;
158 }
159 PostMessage(ST_RTP, buffer_copy);
160 }
161 } else {
162 PostMessage(ST_RTP, *packet);
163 }
164 return true;
165 }
166
167 virtual bool SendRtcp(talk_base::Buffer* packet) {
168 talk_base::CritScope cs(&crit_);
169 rtcp_packets_.push_back(*packet);
170 if (!conf_) {
171 // don't worry about RTCP in conf mode for now
172 PostMessage(ST_RTCP, *packet);
173 }
174 return true;
175 }
176
177 virtual int SetOption(SocketType type, talk_base::Socket::Option opt,
178 int option) {
179 if (opt == talk_base::Socket::OPT_SNDBUF) {
180 sendbuf_size_ = option;
181 } else if (opt == talk_base::Socket::OPT_RCVBUF) {
182 recvbuf_size_ = option;
183 }
184 return 0;
185 }
186
187 void PostMessage(int id, const talk_base::Buffer& packet) {
188 thread_->Post(this, id, talk_base::WrapMessageData(packet));
189 }
190
191 virtual void OnMessage(talk_base::Message* msg) {
192 talk_base::TypedMessageData<talk_base::Buffer>* msg_data =
193 static_cast<talk_base::TypedMessageData<talk_base::Buffer>*>(
194 msg->pdata);
195 if (dest_) {
196 if (msg->message_id == ST_RTP) {
197 dest_->OnPacketReceived(&msg_data->data());
198 } else {
199 dest_->OnRtcpReceived(&msg_data->data());
200 }
201 }
202 delete msg_data;
203 }
204
205 private:
206 void GetNumRtpBytesAndPackets(uint32 ssrc, int* bytes, int* packets) {
207 if (bytes) {
208 *bytes = 0;
209 }
210 if (packets) {
211 *packets = 0;
212 }
213 uint32 cur_ssrc = 0;
214 for (size_t i = 0; i < rtp_packets_.size(); ++i) {
215 if (!GetRtpSsrc(rtp_packets_[i].data(),
216 rtp_packets_[i].length(), &cur_ssrc)) {
217 return;
218 }
219 if (ssrc == cur_ssrc) {
220 if (bytes) {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000221 *bytes += static_cast<int>(rtp_packets_[i].length());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000222 }
223 if (packets) {
224 ++(*packets);
225 }
226 }
227 }
228 }
229
230 talk_base::Thread* thread_;
231 MediaChannel* dest_;
232 bool conf_;
233 // The ssrcs used in sending out packets in conference mode.
234 std::vector<uint32> conf_sent_ssrcs_;
235 // Map to track counts of packets that have been sent per ssrc.
236 // This includes packets that are dropped.
237 std::map<uint32, uint32> sent_ssrcs_;
238 // Map to track packet-number that needs to be dropped per ssrc.
239 std::map<uint32, std::set<uint32> > drop_map_;
240 talk_base::CriticalSection crit_;
241 std::vector<talk_base::Buffer> rtp_packets_;
242 std::vector<talk_base::Buffer> rtcp_packets_;
243 int sendbuf_size_;
244 int recvbuf_size_;
245};
246
247} // namespace cricket
248
249#endif // TALK_MEDIA_BASE_FAKENETWORKINTERFACE_H_