OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "media/cast/test/transport/transport.h" | |
6 | |
7 #include <string> | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/logging.h" | |
11 #include "base/memory/ref_counted.h" | |
12 #include "base/memory/scoped_ptr.h" | |
13 #include "base/rand_util.h" | |
14 #include "net/base/completion_callback.h" | |
15 #include "net/base/io_buffer.h" | |
16 #include "net/base/rand_callback.h" | |
17 #include "net/base/test_completion_callback.h" | |
18 | |
19 namespace media { | |
20 namespace cast { | |
21 namespace test { | |
22 | |
23 const int kMaxPacketSize = 1500; | |
24 | |
25 class LocalUdpTransportData; | |
26 | |
27 void CreateUDPAddress(std::string ip_str, int port, net::IPEndPoint* address) { | |
28 net::IPAddressNumber ip_number; | |
29 bool rv = net::ParseIPLiteralToNumber(ip_str, &ip_number); | |
30 if (!rv) | |
31 return; | |
32 *address = net::IPEndPoint(ip_number, port); | |
33 } | |
34 | |
35 class LocalUdpTransportData { | |
36 public: | |
37 LocalUdpTransportData(net::DatagramServerSocket* udp_socket) | |
38 : udp_socket_(udp_socket), | |
39 buffer_(new net::IOBufferWithSize(kMaxPacketSize)), | |
40 weak_factory_(this) { | |
41 } | |
42 void DeletePacket(const uint8* packet) { | |
Alpha Left Google
2013/11/04 19:51:09
Remove this method as it is not needed.
mikhal
2013/11/04 21:20:07
True.Done.
On 2013/11/04 19:51:09, Alpha wrote:
| |
43 RecvFromSocketLoop(); | |
44 } | |
45 | |
46 void ListenTo(net::IPEndPoint bind_address) { | |
47 bind_address_ = bind_address; | |
48 RecvFromSocketLoop(); | |
49 } | |
50 | |
51 void PacketReceived(int result) { | |
52 // Got a packet with length result. | |
53 uint8* data = reinterpret_cast<uint8*>(buffer_->data()); | |
54 packet_receiver_->ReceivedPacket(data, result, | |
55 base::Bind(&LocalUdpTransportData::DeletePacket, | |
Alpha Left Google
2013/11/04 19:51:09
That's not right. You don't need to delete the pac
mikhal
2013/11/04 21:20:07
Done.
| |
56 weak_factory_.GetWeakPtr(), data)); | |
57 } | |
58 | |
59 void RecvFromSocketLoop() { | |
60 // Callback should always trigger with a packet. | |
61 int res = udp_socket_->RecvFrom(buffer_.get(), kMaxPacketSize, | |
62 &bind_address_, base::Bind(&LocalUdpTransportData::PacketReceived, | |
63 weak_factory_.GetWeakPtr())); | |
64 if (res > 0) { | |
Alpha Left Google
2013/11/04 19:51:09
What happens if there's an error? The read loop wi
mikhal
2013/11/04 21:20:07
Done.
| |
65 PacketReceived(res); | |
66 } | |
67 } | |
68 | |
69 void set_packet_receiver(PacketReceiver* packet_receiver) { | |
70 packet_receiver_ = packet_receiver; | |
71 } | |
72 | |
73 void Close() { | |
74 udp_socket_->Close(); | |
75 } | |
76 | |
77 private: | |
78 net::DatagramServerSocket* udp_socket_; | |
79 net::IPEndPoint bind_address_; | |
80 PacketReceiver* packet_receiver_; | |
81 scoped_refptr<net::IOBufferWithSize> buffer_; | |
82 base::WeakPtrFactory<LocalUdpTransportData> weak_factory_; | |
83 DISALLOW_COPY_AND_ASSIGN(LocalUdpTransportData); | |
84 }; | |
85 | |
86 class LocalPacketSender : public PacketSender { | |
87 public: | |
88 explicit LocalPacketSender(net::DatagramServerSocket* udp_socket) | |
89 : udp_socket_(udp_socket), | |
90 send_address_(), | |
91 loss_limit_(0) {} | |
92 | |
93 virtual bool SendPacket(const Packet& packet) { | |
94 const uint8* data = packet.data(); | |
95 if (loss_limit_ > 0) { | |
96 int r = base::RandInt(0, 100); | |
97 if (r < loss_limit_) { | |
98 VLOG(1) << "Drop packet f:" << static_cast<int>(data[12 + 1]) | |
99 << " p:" << static_cast<int>(data[12 + 3]) | |
100 << " m:" << static_cast<int>(data[12 + 5]); | |
101 return true; | |
102 } | |
103 } | |
104 net::TestCompletionCallback callback; | |
105 scoped_refptr<net::WrappedIOBuffer> buffer( | |
106 new net::WrappedIOBuffer(reinterpret_cast<const char*>(data))); | |
107 int rv = udp_socket_->SendTo( | |
108 buffer.get(), packet.size(), send_address_, callback.callback()); | |
109 return (rv == packet.size()); | |
110 } | |
111 | |
112 virtual bool SendPackets(const PacketList& packets) { | |
113 bool out_val = true; | |
114 for (size_t i = 0; i < packets.size(); ++i) { | |
115 const Packet& packet = packets[i]; | |
116 out_val |= SendPacket(packet); | |
117 } | |
118 return out_val; | |
119 } | |
120 | |
121 void SetPacketLoss(int percentage) { | |
122 DCHECK(percentage >= 0); | |
123 DCHECK(percentage < 100); | |
124 loss_limit_ = percentage; | |
125 } | |
126 | |
127 void SetSendAddress(net::IPEndPoint& send_address) { | |
128 send_address_ = send_address; | |
129 } | |
130 | |
131 private: | |
132 net::DatagramServerSocket* udp_socket_; // Not owned by this class. | |
133 net::IPEndPoint send_address_; | |
134 int loss_limit_; | |
135 }; | |
136 | |
137 Transport::Transport(scoped_refptr<CastEnvironment> cast_environment) | |
138 : udp_socket_(new net::UDPServerSocket(NULL, net::NetLog::Source())), | |
139 local_udp_transport_data_(new LocalUdpTransportData(udp_socket_.get())), | |
140 packet_sender_(new LocalPacketSender(udp_socket_.get())) {} | |
141 | |
142 Transport::~Transport() {} | |
143 | |
144 PacketSender* Transport::packet_sender() { | |
145 return static_cast<PacketSender*>(packet_sender_.get()); | |
146 } | |
147 | |
148 void Transport::SetSendSidePacketLoss(int percentage) { | |
149 packet_sender_->SetPacketLoss(percentage); | |
150 } | |
151 | |
152 void Transport::StopReceiving() { | |
153 local_udp_transport_data_->Close(); | |
154 } | |
155 | |
156 void Transport::SetLocalReceiver(PacketReceiver* packet_receiver, | |
157 std::string ip_address, | |
158 int port) { | |
159 net::IPEndPoint bind_address; | |
160 CreateUDPAddress(ip_address, port, &bind_address); | |
161 local_udp_transport_data_->set_packet_receiver(packet_receiver); | |
162 udp_socket_->AllowAddressReuse(); | |
163 udp_socket_->SetMulticastLoopbackMode(true); | |
164 udp_socket_->Listen(bind_address); | |
165 | |
166 // Start listening once receiver has been set. | |
167 local_udp_transport_data_->ListenTo(bind_address); | |
168 } | |
169 | |
170 void Transport::SetSendDestination(std::string ip_address, int port) { | |
171 net::IPEndPoint send_address; | |
172 CreateUDPAddress(ip_address, port, &send_address); | |
173 packet_sender_->SetSendAddress(send_address); | |
174 } | |
175 | |
176 } // namespace test | |
177 } // namespace cast | |
178 } // namespace media | |
OLD | NEW |