Home | History | Annotate | Download | only in socket
      1 // Copyright (c) 2012 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 "chrome/browser/extensions/api/socket/socket.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/lazy_instance.h"
      9 #include "chrome/browser/extensions/api/api_resource_manager.h"
     10 #include "net/base/address_list.h"
     11 #include "net/base/io_buffer.h"
     12 #include "net/base/ip_endpoint.h"
     13 #include "net/base/net_errors.h"
     14 #include "net/socket/socket.h"
     15 
     16 namespace extensions {
     17 
     18 const char kSocketTypeNotSupported[] = "Socket type does not support this API";
     19 
     20 static base::LazyInstance<ProfileKeyedAPIFactory<ApiResourceManager<Socket> > >
     21     g_factory = LAZY_INSTANCE_INITIALIZER;
     22 
     23 // static
     24 template <>
     25 ProfileKeyedAPIFactory<ApiResourceManager<Socket> >*
     26 ApiResourceManager<Socket>::GetFactoryInstance() {
     27   return &g_factory.Get();
     28 }
     29 
     30 Socket::Socket(const std::string& owner_extension_id)
     31     : ApiResource(owner_extension_id), is_connected_(false) {
     32 }
     33 
     34 Socket::~Socket() {
     35   // Derived destructors should make sure the socket has been closed.
     36   DCHECK(!is_connected_);
     37 }
     38 
     39 void Socket::Write(scoped_refptr<net::IOBuffer> io_buffer,
     40                    int byte_count,
     41                    const CompletionCallback& callback) {
     42   DCHECK(!callback.is_null());
     43   write_queue_.push(WriteRequest(io_buffer, byte_count, callback));
     44   WriteData();
     45 }
     46 
     47 void Socket::WriteData() {
     48   // IO is pending.
     49   if (io_buffer_write_.get())
     50     return;
     51 
     52   WriteRequest& request = write_queue_.front();
     53 
     54   DCHECK(request.byte_count >= request.bytes_written);
     55   io_buffer_write_ = new net::WrappedIOBuffer(
     56       request.io_buffer->data() + request.bytes_written);
     57   int result = WriteImpl(
     58       io_buffer_write_.get(),
     59       request.byte_count - request.bytes_written,
     60       base::Bind(&Socket::OnWriteComplete, base::Unretained(this)));
     61 
     62   if (result != net::ERR_IO_PENDING)
     63     OnWriteComplete(result);
     64 }
     65 
     66 void Socket::OnWriteComplete(int result) {
     67   io_buffer_write_ = NULL;
     68 
     69   WriteRequest& request = write_queue_.front();
     70 
     71   if (result >= 0) {
     72     request.bytes_written += result;
     73     if (request.bytes_written < request.byte_count) {
     74       WriteData();
     75       return;
     76     }
     77     DCHECK(request.bytes_written == request.byte_count);
     78     result = request.bytes_written;
     79   }
     80 
     81   request.callback.Run(result);
     82   write_queue_.pop();
     83 
     84   if (!write_queue_.empty())
     85     WriteData();
     86 }
     87 
     88 bool Socket::SetKeepAlive(bool enable, int delay) {
     89   return false;
     90 }
     91 
     92 bool Socket::SetNoDelay(bool no_delay) {
     93   return false;
     94 }
     95 
     96 int Socket::Listen(const std::string& address, int port, int backlog,
     97                    std::string* error_msg) {
     98   *error_msg = kSocketTypeNotSupported;
     99   return net::ERR_FAILED;
    100 }
    101 
    102 void Socket::Accept(const AcceptCompletionCallback& callback) {
    103   callback.Run(net::ERR_FAILED, NULL);
    104 }
    105 
    106 // static
    107 bool Socket::StringAndPortToIPEndPoint(const std::string& ip_address_str,
    108                                        int port,
    109                                        net::IPEndPoint* ip_end_point) {
    110   DCHECK(ip_end_point);
    111   net::IPAddressNumber ip_number;
    112   if (!net::ParseIPLiteralToNumber(ip_address_str, &ip_number))
    113     return false;
    114 
    115   *ip_end_point = net::IPEndPoint(ip_number, port);
    116   return true;
    117 }
    118 
    119 bool Socket::StringAndPortToAddressList(const std::string& ip_address_str,
    120                                         int port,
    121                                         net::AddressList* address_list) {
    122   DCHECK(address_list);
    123   net::IPAddressNumber ip_number;
    124   if (!net::ParseIPLiteralToNumber(ip_address_str, &ip_number))
    125     return false;
    126 
    127   *address_list = net::AddressList::CreateFromIPAddress(ip_number, port);
    128   return true;
    129 }
    130 
    131 void Socket::IPEndPointToStringAndPort(const net::IPEndPoint& address,
    132                                        std::string* ip_address_str,
    133                                        int* port) {
    134   DCHECK(ip_address_str);
    135   DCHECK(port);
    136   *ip_address_str = address.ToStringWithoutPort();
    137   if (ip_address_str->empty()) {
    138     *port = 0;
    139   } else {
    140     *port = address.port();
    141   }
    142 }
    143 
    144 Socket::WriteRequest::WriteRequest(scoped_refptr<net::IOBuffer> io_buffer,
    145                                    int byte_count,
    146                                    const CompletionCallback& callback)
    147     : io_buffer(io_buffer),
    148       byte_count(byte_count),
    149       callback(callback),
    150       bytes_written(0) {
    151 }
    152 
    153 Socket::WriteRequest::~WriteRequest() { }
    154 
    155 }  // namespace extensions
    156