Index: media/cast/test/transport/transport.cc |
diff --git a/media/cast/test/transport/transport.cc b/media/cast/test/transport/transport.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e06184f4cfbd9df9a3d51239195f3230e7215bc9 |
--- /dev/null |
+++ b/media/cast/test/transport/transport.cc |
@@ -0,0 +1,190 @@ |
+// Copyright 2013 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "media/cast/test/transport/transport.h" |
+ |
+#include <stdio.h> |
Alpha Left Google
2013/11/01 23:23:19
What is this for? I don't see anything related to
mikhal
2013/11/04 17:50:42
Done.
|
+#include <stdlib.h> |
Alpha Left Google
2013/11/01 23:23:19
#include <string> instead, it will give you memcpy
mikhal
2013/11/04 17:50:42
Done.
|
+ |
+#include <cassert> |
Alpha Left Google
2013/11/01 23:23:19
Don't use <cassert>, use base/logging.h instead wh
mikhal
2013/11/04 17:50:42
Done.
|
+ |
+#include "base/bind.h" |
+#include "base/logging.h" |
+#include "base/memory/ref_counted.h" |
+#include "base/memory/scoped_ptr.h" |
+#include "base/message_loop/message_loop.h" |
Alpha Left Google
2013/11/01 23:23:19
I don't see this being used.
mikhal
2013/11/04 17:50:42
Done.
|
+#include "base/rand_util.h" |
+#include "net/base/completion_callback.h" |
+#include "net/base/io_buffer.h" |
+#include "net/base/rand_callback.h" |
+#include "net/base/test_completion_callback.h" |
+ |
+namespace media { |
+namespace cast { |
+namespace test { |
+ |
+const int kMaxPacketSize = 1500; |
+ |
+typedef std::vector<unsigned char> IPAddressNumber; |
Alpha Left Google
2013/11/01 23:23:19
This is already defined as net::IPAddressNumber.
mikhal
2013/11/04 17:50:42
Done.
|
+class LocalUdpTransportData; |
+ |
+void CreateUDPAddress(std::string ip_str, int port, net::IPEndPoint* address) { |
+ IPAddressNumber ip_number; |
Alpha Left Google
2013/11/01 23:23:19
Use net::IPAddressNumber instead.
mikhal
2013/11/04 17:50:42
Done.
|
+ bool rv = net::ParseIPLiteralToNumber(ip_str, &ip_number); |
+ if (!rv) |
+ return; |
+ *address = net::IPEndPoint(ip_number, port); |
+} |
+ |
+class LocalUdpTransportData { |
+ public: |
+ LocalUdpTransportData(net::DatagramServerSocket* udp_socket) |
+ : udp_socket_(udp_socket), |
+ buffer_(new net::IOBufferWithSize(kMaxPacketSize)), |
+ weak_factory_(this) { |
+} |
+ void DeletePacket(const uint8* packet) { |
+ delete [] packet; |
Alpha Left Google
2013/11/01 23:23:19
If you pass in buffer_data->data() to packet_recei
|
+ RecvFromSocketLoop(); |
+ } |
+ |
+ void ListenTo(net::IPEndPoint bind_address) { |
+ bind_address_ = bind_address; |
+ RecvFromSocketLoop(); |
+ } |
+ |
+ void PacketReceived(int result) { |
+ // Got a packet with length result. |
+ uint8* data = new uint8[result]; |
+ memcpy(data, reinterpret_cast<uint8*>(buffer_->data()), result); |
Alpha Left Google
2013/11/01 23:23:19
Don't do this memcpy just pass buffer_->data() to
mikhal
2013/11/04 17:50:42
Done.
|
+ packet_receiver_->ReceivedPacket(data, result, |
+ base::Bind(&LocalUdpTransportData::DeletePacket, |
+ weak_factory_.GetWeakPtr(), data)); |
+ } |
+ |
+ void RecvFromSocketLoop() { |
Alpha Left Google
2013/11/01 23:23:19
This is good! Now you know how this async read loo
mikhal
2013/11/04 17:50:42
thanks!
On 2013/11/01 23:23:19, Alpha wrote:
|
+ // Callback should always trigger with a packet. |
+ int res = udp_socket_->RecvFrom(buffer_.get(), kMaxPacketSize, |
+ &bind_address_, base::Bind(&LocalUdpTransportData::PacketReceived, |
+ weak_factory_.GetWeakPtr())); |
+ if (res > 0 ) { |
Alpha Left Google
2013/11/01 23:23:19
nit: (res > 0)
mikhal
2013/11/04 17:50:42
Done.
|
+ PacketReceived(res); |
+ } |
+ } |
+ |
+ void set_packet_receiver(PacketReceiver* packet_receiver) { |
+ packet_receiver_ = packet_receiver; |
+ } |
+ |
+ void Close() { |
+ udp_socket_->Close(); |
+ } |
+ |
+ private: |
+ net::DatagramServerSocket* udp_socket_; |
+ net::IPEndPoint bind_address_; |
+ PacketReceiver* packet_receiver_; |
+ scoped_refptr<net::IOBufferWithSize> buffer_; |
+ base::WeakPtrFactory<LocalUdpTransportData> weak_factory_; |
+ DISALLOW_COPY_AND_ASSIGN(LocalUdpTransportData); |
+}; |
+ |
+ |
Alpha Left Google
2013/11/01 23:23:19
nit: remove this empty line.
mikhal
2013/11/04 17:50:42
Done.
|
+class LocalPacketSender : public PacketSender { |
+ public: |
+ explicit LocalPacketSender(net::DatagramServerSocket* udp_socket) |
+ : udp_socket_(udp_socket), |
+ send_address_(), |
+ loss_limit_(0) {} |
+ |
+ bool UniformLoss(double loss_pct) { |
Alpha Left Google
2013/11/01 23:23:19
This is not being used.
mikhal
2013/11/04 17:50:42
removed
On 2013/11/01 23:23:19, Alpha wrote:
|
+ double randVal = base::RandInt(1, 100); |
+ return randVal < loss_pct; |
+ } |
+ |
+ |
Alpha Left Google
2013/11/01 23:23:19
nit: remove this extra space.
mikhal
2013/11/04 17:50:42
Done.
|
+ virtual bool SendPacket(const Packet& packet) { |
+ const uint8* data = packet.data(); |
+ if (loss_limit_ > 0) { |
+ int r = base::RandInt(0, 100); |
Alpha Left Google
2013/11/01 23:23:19
Maybe use UniformLoss() instead?
mikhal
2013/11/04 17:50:42
Removed uniform loss as we only have one type of l
|
+ if (r < loss_limit_) { |
+ VLOG(1) << "Drop packet f:" << static_cast<int>(data[12 + 1]) |
+ << " p:" << static_cast<int>(data[12 + 3]) |
+ << " m:" << static_cast<int>(data[12 + 5]); |
+ return true; |
+ } |
+ } |
+ net::TestCompletionCallback callback; |
+ scoped_refptr<net::WrappedIOBuffer> buffer( |
+ new net::WrappedIOBuffer(reinterpret_cast<const char*>(data))); |
+ int rv = udp_socket_->SendTo( |
Alpha Left Google
2013/11/01 23:23:19
It will be more clear if you do this:
#include "b
|
+ buffer.get(), packet.size(), send_address_, callback.callback()); |
+ return (rv == packet.size()); |
+ } |
+ |
+ virtual bool SendPackets(const PacketList& packets) { |
+ bool out_val = true; |
Alpha Left Google
2013/11/01 23:23:19
nit: There's two space after _val.
mikhal
2013/11/04 17:50:42
Done.
|
+ for (size_t i = 0; i < packets.size(); ++i) { |
+ const Packet& packet = packets[i]; |
+ out_val |= SendPacket(packet); |
+ } |
+ return out_val; |
+ } |
+ |
+ void SetPacketLoss(int percentage) { |
+ assert(percentage >= 0); |
Alpha Left Google
2013/11/01 23:23:19
Use CHECK() instead of assert().
mikhal
2013/11/04 17:50:42
Done.
|
+ assert(percentage < 100); |
+ loss_limit_ = percentage; |
+ } |
+ |
+ void SetSendAddress(net::IPEndPoint& send_address) { |
+ send_address_ = send_address; |
+ } |
+ |
+ private: |
+ net::DatagramServerSocket* udp_socket_; // Not owned by this class. |
+ net::IPEndPoint send_address_; |
+ int loss_limit_; |
+}; |
+ |
+Transport::Transport(scoped_refptr<CastEnvironment> cast_environment) |
+ : udp_socket_(new net::UDPServerSocket(NULL, net::NetLog::Source())), |
+ local_udp_transport_data_(new LocalUdpTransportData(udp_socket_.get())), |
+ packet_sender_(new LocalPacketSender(udp_socket_.get())) {} |
+ |
+Transport::~Transport() {} |
+ |
+void Transport::SetSendSidePacketLoss(int percentage) { |
+ PacketSender* sender = packet_sender_.get(); |
+ static_cast<LocalPacketSender*>(sender)->SetPacketLoss(percentage); |
Alpha Left Google
2013/11/01 23:23:19
Since packet_sender_ is always LocalPacketSender I
mikhal
2013/11/04 17:50:42
Done.
|
+} |
+ |
+void Transport::StopReceiving() { |
+ local_udp_transport_data_->Close(); |
+} |
+ |
+void Transport::SetLocalReceiver(PacketReceiver* packet_receiver, |
+ std::string ip_address, |
+ int port) { |
+ net::IPEndPoint bind_address; |
+ CreateUDPAddress(ip_address, port, &bind_address); |
+ local_udp_transport_data_->set_packet_receiver(packet_receiver); |
+ udp_socket_->AllowAddressReuse(); |
+ udp_socket_->SetMulticastLoopbackMode(true); |
+ udp_socket_->Listen(bind_address); |
+ |
+ // Start listening once receiver has been set. |
+ local_udp_transport_data_->ListenTo(bind_address); |
+} |
+ |
+void Transport::SetSendDestination(std::string ip_address, int port) { |
+ net::IPEndPoint send_address; |
+ CreateUDPAddress(ip_address, port, &send_address); |
+ PacketSender* sender = packet_sender_.get(); |
+ static_cast<LocalPacketSender*>(sender)->SetSendAddress(send_address); |
+} |
+ |
+} // namespace test |
+} // namespace cast |
+} // namespace media |