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