1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/browser/api/socket/udp_socket.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <algorithm>
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/lazy_instance.h"
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/browser/api/api_resource.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/ip_endpoint.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/udp/datagram_socket.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/udp/udp_client_socket.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static base::LazyInstance<
19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    BrowserContextKeyedAPIFactory<ApiResourceManager<ResumableUDPSocket> > >
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    g_factory = LAZY_INSTANCE_INITIALIZER;
213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// static
233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)template <>
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BrowserContextKeyedAPIFactory<ApiResourceManager<ResumableUDPSocket> >*
253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)ApiResourceManager<ResumableUDPSocket>::GetFactoryInstance() {
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return g_factory.Pointer();
273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UDPSocket::UDPSocket(const std::string& owner_extension_id)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : Socket(owner_extension_id),
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      socket_(net::DatagramSocket::DEFAULT_BIND,
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              net::RandIntCallback(),
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              NULL,
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)              net::NetLog::Source()) {}
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)UDPSocket::~UDPSocket() { Disconnect(); }
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocket::Connect(const std::string& address,
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        int port,
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const CompletionCallback& callback) {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result = net::ERR_CONNECTION_FAILED;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (is_connected_)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::IPEndPoint ip_end_point;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!StringAndPortToIPEndPoint(address, port, &ip_end_point)) {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = net::ERR_ADDRESS_INVALID;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = socket_.Connect(ip_end_point);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    is_connected_ = (result == net::OK);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (false);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback.Run(result);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocket::Bind(const std::string& address, int port) {
60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (IsBound())
61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return net::ERR_CONNECTION_FAILED;
62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::IPEndPoint ip_end_point;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!StringAndPortToIPEndPoint(address, port, &ip_end_point))
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::ERR_INVALID_ARGUMENT;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return socket_.Bind(ip_end_point);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocket::Disconnect() {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_connected_ = false;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_.Close();
738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  read_callback_.Reset();
748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  recv_from_callback_.Reset();
758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  send_to_callback_.Reset();
768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  multicast_groups_.clear();
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void UDPSocket::Read(int count, const ReadCompletionCallback& callback) {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!read_callback_.is_null()) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback.Run(net::ERR_IO_PENDING, NULL);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    read_callback_ = callback;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result = net::ERR_FAILED;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<net::IOBuffer> io_buffer;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (count < 0) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = net::ERR_INVALID_ARGUMENT;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!socket_.is_connected()) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = net::ERR_SOCKET_NOT_CONNECTED;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    io_buffer = new net::IOBuffer(count);
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    result = socket_.Read(
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        io_buffer.get(),
105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        count,
106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        base::Bind(
107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            &UDPSocket::OnReadComplete, base::Unretained(this), io_buffer));
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (false);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != net::ERR_IO_PENDING)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnReadComplete(io_buffer, result);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocket::WriteImpl(net::IOBuffer* io_buffer,
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         int io_buffer_size,
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const net::CompletionCallback& callback) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!socket_.is_connected())
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::ERR_SOCKET_NOT_CONNECTED;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return socket_.Write(io_buffer, io_buffer_size, callback);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocket::RecvFrom(int count,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const RecvFromCompletionCallback& callback) {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!recv_from_callback_.is_null()) {
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback.Run(net::ERR_IO_PENDING, NULL, std::string(), 0);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    recv_from_callback_ = callback;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result = net::ERR_FAILED;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<net::IOBuffer> io_buffer;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<IPEndPoint> address;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (count < 0) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = net::ERR_INVALID_ARGUMENT;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!socket_.is_connected()) {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = net::ERR_SOCKET_NOT_CONNECTED;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    io_buffer = new net::IOBuffer(count);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    address = new IPEndPoint();
150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    result = socket_.RecvFrom(io_buffer.get(),
151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                              count,
152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                              &address->data,
153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                              base::Bind(&UDPSocket::OnRecvFromComplete,
154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                         base::Unretained(this),
155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                         io_buffer,
156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                         address));
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (false);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != net::ERR_IO_PENDING)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnRecvFromComplete(io_buffer, address, result);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocket::SendTo(scoped_refptr<net::IOBuffer> io_buffer,
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       int byte_count,
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const std::string& address,
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       int port,
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const CompletionCallback& callback) {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!send_to_callback_.is_null()) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(penghuang): Put requests in a pending queue to support multiple
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // sendTo calls.
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback.Run(net::ERR_IO_PENDING);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    send_to_callback_ = callback;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result = net::ERR_FAILED;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::IPEndPoint ip_end_point;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!StringAndPortToIPEndPoint(address, port, &ip_end_point)) {
183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      result = net::ERR_ADDRESS_INVALID;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!socket_.is_connected()) {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = net::ERR_SOCKET_NOT_CONNECTED;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = socket_.SendTo(
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        io_buffer.get(),
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        byte_count,
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ip_end_point,
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&UDPSocket::OnSendToComplete, base::Unretained(this)));
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (false);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != net::ERR_IO_PENDING)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnSendToComplete(result);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool UDPSocket::IsConnected() { return is_connected_; }
2047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool UDPSocket::GetPeerAddress(net::IPEndPoint* address) {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !socket_.GetPeerAddress(address);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool UDPSocket::GetLocalAddress(net::IPEndPoint* address) {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !socket_.GetLocalAddress(address);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)Socket::SocketType UDPSocket::GetSocketType() const { return Socket::TYPE_UDP; }
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocket::OnReadComplete(scoped_refptr<net::IOBuffer> io_buffer,
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               int result) {
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!read_callback_.is_null());
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_callback_.Run(result, io_buffer);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_callback_.Reset();
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocket::OnRecvFromComplete(scoped_refptr<net::IOBuffer> io_buffer,
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   scoped_refptr<IPEndPoint> address,
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   int result) {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!recv_from_callback_.is_null());
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string ip;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int port = 0;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result > 0 && address.get()) {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPEndPointToStringAndPort(address->data, &ip, &port);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  recv_from_callback_.Run(result, io_buffer, ip, port);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  recv_from_callback_.Reset();
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocket::OnSendToComplete(int result) {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!send_to_callback_.is_null());
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  send_to_callback_.Run(result);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  send_to_callback_.Reset();
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool UDPSocket::IsBound() { return socket_.is_connected(); }
242a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int UDPSocket::JoinGroup(const std::string& address) {
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  net::IPAddressNumber ip;
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!net::ParseIPLiteralToNumber(address, &ip))
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return net::ERR_ADDRESS_INVALID;
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string normalized_address = net::IPAddressToString(ip);
249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::vector<std::string>::iterator find_result = std::find(
250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      multicast_groups_.begin(), multicast_groups_.end(), normalized_address);
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (find_result != multicast_groups_.end())
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return net::ERR_ADDRESS_INVALID;
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int rv = socket_.JoinGroup(ip);
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (rv == 0)
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    multicast_groups_.push_back(normalized_address);
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return rv;
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int UDPSocket::LeaveGroup(const std::string& address) {
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  net::IPAddressNumber ip;
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!net::ParseIPLiteralToNumber(address, &ip))
263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return net::ERR_ADDRESS_INVALID;
264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string normalized_address = net::IPAddressToString(ip);
266a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::vector<std::string>::iterator find_result = std::find(
267a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      multicast_groups_.begin(), multicast_groups_.end(), normalized_address);
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (find_result == multicast_groups_.end())
269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return net::ERR_ADDRESS_INVALID;
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int rv = socket_.LeaveGroup(ip);
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (rv == 0)
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    multicast_groups_.erase(find_result);
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return rv;
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int UDPSocket::SetMulticastTimeToLive(int ttl) {
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return socket_.SetMulticastTimeToLive(ttl);
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int UDPSocket::SetMulticastLoopbackMode(bool loopback) {
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return socket_.SetMulticastLoopbackMode(loopback);
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const std::vector<std::string>& UDPSocket::GetJoinedGroups() const {
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return multicast_groups_;
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)ResumableUDPSocket::ResumableUDPSocket(const std::string& owner_extension_id)
2903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    : UDPSocket(owner_extension_id),
2913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      persistent_(false),
292a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      buffer_size_(0),
293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      paused_(false) {}
2943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool ResumableUDPSocket::IsPersistent() const { return persistent(); }
2963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extensions
298