Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / media / cast / transport / transport / udp_transport.cc
index 9b3ad3c..d16a117 100644 (file)
@@ -26,49 +26,60 @@ const int kMaxPacketSize = 1500;
 
 bool IsEmpty(const net::IPEndPoint& addr) {
   net::IPAddressNumber empty_addr(addr.address().size());
-  return std::equal(empty_addr.begin(),
-                    empty_addr.end(),
-                    addr.address().begin());
+  return std::equal(
+             empty_addr.begin(), empty_addr.end(), addr.address().begin()) &&
+         !addr.port();
 }
 
 bool IsEqual(const net::IPEndPoint& addr1, const net::IPEndPoint& addr2) {
-  return addr1.port() == addr2.port() &&
-      std::equal(addr1.address().begin(),
-                 addr1.address().end(),
-                 addr2.address().begin());
+  return addr1.port() == addr2.port() && std::equal(addr1.address().begin(),
+                                                    addr1.address().end(),
+                                                    addr2.address().begin());
 }
-
 }  // namespace
 
 UdpTransport::UdpTransport(
-    const scoped_refptr<base::TaskRunner>& io_thread_proxy,
+    const scoped_refptr<base::SingleThreadTaskRunner>& io_thread_proxy,
     const net::IPEndPoint& local_end_point,
     const net::IPEndPoint& remote_end_point,
     const CastTransportStatusCallback& status_callback)
     : io_thread_proxy_(io_thread_proxy),
       local_addr_(local_end_point),
       remote_addr_(remote_end_point),
-      udp_socket_(new net::UDPServerSocket(NULL, net::NetLog::Source())),
+      udp_socket_(new net::UDPSocket(net::DatagramSocket::DEFAULT_BIND,
+                                     net::RandIntCallback(),
+                                     NULL,
+                                     net::NetLog::Source())),
+      send_pending_(false),
       recv_buf_(new net::IOBuffer(kMaxPacketSize)),
-      packet_receiver_(NULL),
       status_callback_(status_callback),
       weak_factory_(this) {
+  DCHECK(!IsEmpty(local_end_point) || !IsEmpty(remote_end_point));
 }
 
-UdpTransport::~UdpTransport() {
-}
+UdpTransport::~UdpTransport() {}
 
-void UdpTransport::StartReceiving(PacketReceiver* packet_receiver) {
+void UdpTransport::StartReceiving(
+    const PacketReceiverCallback& packet_receiver) {
   DCHECK(io_thread_proxy_->RunsTasksOnCurrentThread());
-  DCHECK(!packet_receiver_);
 
   packet_receiver_ = packet_receiver;
   udp_socket_->AllowAddressReuse();
   udp_socket_->SetMulticastLoopbackMode(true);
-  if (udp_socket_->Listen(local_addr_) < 0) {
-    status_callback_.Run(TRANSPORT_SOCKET_ERROR);
-    LOG(ERROR) << "Failed to bind local address";
-    return;
+  if (!IsEmpty(local_addr_)) {
+    if (udp_socket_->Bind(local_addr_) < 0) {
+      status_callback_.Run(TRANSPORT_SOCKET_ERROR);
+      LOG(ERROR) << "Failed to bind local address.";
+      return;
+    }
+  } else if (!IsEmpty(remote_addr_)) {
+    if (udp_socket_->Connect(remote_addr_) < 0) {
+      status_callback_.Run(TRANSPORT_SOCKET_ERROR);
+      LOG(ERROR) << "Failed to connect to remote address.";
+      return;
+    }
+  } else {
+    NOTREACHED() << "Either local or remote address has to be defined.";
   }
   ReceiveOnePacket();
 }
@@ -101,43 +112,47 @@ void UdpTransport::OnReceived(int result) {
 
   if (IsEmpty(remote_addr_)) {
     remote_addr_ = recv_addr_;
-    VLOG(1) << "First packet received from: "
-            << remote_addr_.ToString() << ".";
+    VLOG(1) << "First packet received from: " << remote_addr_.ToString() << ".";
   } else if (!IsEqual(remote_addr_, recv_addr_)) {
     LOG(ERROR) << "Received from an unrecognized address: "
-            << recv_addr_.ToString() << ".";
+               << recv_addr_.ToString() << ".";
     return;
   }
   // TODO(hclam): The interfaces should use net::IOBuffer to eliminate memcpy.
-  uint8* data = new uint8[result];
-  memcpy(data, recv_buf_->data(), result);
-  packet_receiver_->ReceivedPacket(
-      data,
-      result,
-      base::Bind(&PacketReceiver::DeletePacket, data));
+  scoped_ptr<Packet> packet(
+      new Packet(recv_buf_->data(), recv_buf_->data() + result));
+  packet_receiver_.Run(packet.Pass());
   ReceiveOnePacket();
 }
 
 bool UdpTransport::SendPacket(const Packet& packet) {
   DCHECK(io_thread_proxy_->RunsTasksOnCurrentThread());
 
+  if (send_pending_) {
+    VLOG(1) << "Cannot send because of pending IO.";
+    return false;
+  }
+
   // TODO(hclam): This interface should take a net::IOBuffer to minimize
   // memcpy.
-  scoped_refptr<net::IOBuffer> buf = new net::IOBuffer(
-      static_cast<int>(packet.size()));
+  scoped_refptr<net::IOBuffer> buf =
+      new net::IOBuffer(static_cast<int>(packet.size()));
   memcpy(buf->data(), &packet[0], packet.size());
   int ret = udp_socket_->SendTo(
       buf,
       static_cast<int>(packet.size()),
       remote_addr_,
       base::Bind(&UdpTransport::OnSent, weak_factory_.GetWeakPtr(), buf));
-  return ret == net::OK;
+  if (ret == net::ERR_IO_PENDING)
+    send_pending_ = true;
+  // When ok, will return a positive value equal the number of bytes sent.
+  return ret >= net::OK;
 }
 
-void UdpTransport::OnSent(const scoped_refptr<net::IOBuffer>& buf,
-                          int result) {
+void UdpTransport::OnSent(const scoped_refptr<net::IOBuffer>& buf, int result) {
   DCHECK(io_thread_proxy_->RunsTasksOnCurrentThread());
 
+  send_pending_ = false;
   if (result < 0) {
     LOG(ERROR) << "Failed to send packet: " << result << ".";
     status_callback_.Run(TRANSPORT_SOCKET_ERROR);