| OLD | NEW | 
|    1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |    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 |    2 // Use of this source code is governed by a BSD-style license that can be | 
|    3 // found in the LICENSE file. |    3 // found in the LICENSE file. | 
|    4  |    4  | 
|    5 #include "chrome/browser/extensions/api/socket/udp_socket.h" |    5 #include "chrome/browser/extensions/api/socket/udp_socket.h" | 
|    6  |    6  | 
|    7 #include "chrome/browser/extensions/api/api_resource.h" |    7 #include "chrome/browser/extensions/api/api_resource.h" | 
|    8 #include "chrome/browser/extensions/api/api_resource_event_notifier.h" |    8 #include "chrome/browser/extensions/api/api_resource_event_notifier.h" | 
|    9 #include "net/base/ip_endpoint.h" |    9 #include "net/base/ip_endpoint.h" | 
|   10 #include "net/base/net_errors.h" |   10 #include "net/base/net_errors.h" | 
|   11 #include "net/udp/datagram_socket.h" |   11 #include "net/udp/datagram_socket.h" | 
|   12 #include "net/udp/udp_client_socket.h" |   12 #include "net/udp/udp_client_socket.h" | 
|   13  |   13  | 
|   14 namespace extensions { |   14 namespace extensions { | 
|   15  |   15  | 
|   16 UDPSocket::UDPSocket(APIResourceEventNotifier* event_notifier) |   16 UDPSocket::UDPSocket(APIResourceEventNotifier* event_notifier) | 
|   17     : Socket(event_notifier), |   17     : Socket(event_notifier), | 
|   18       socket_(net::DatagramSocket::DEFAULT_BIND, |   18       socket_(net::DatagramSocket::DEFAULT_BIND, | 
|   19               net::RandIntCallback(), |   19               net::RandIntCallback(), | 
|   20               NULL, |   20               NULL, | 
|   21               net::NetLog::Source()) { |   21               net::NetLog::Source()) { | 
|   22 } |   22 } | 
|   23  |   23  | 
|   24 UDPSocket::~UDPSocket() { |   24 UDPSocket::~UDPSocket() { | 
|   25   if (is_connected_) { |   25   if (is_connected_) { | 
|   26     Disconnect(); |   26     Disconnect(); | 
|   27   } |   27   } | 
|   28 } |   28 } | 
|   29  |   29  | 
|   30 int UDPSocket::Connect(const std::string& address, int port) { |   30 void UDPSocket::Connect(const std::string& address, | 
|   31   if (is_connected_) |   31                         int port, | 
|   32     return net::ERR_CONNECTION_FAILED; |   32                         const CompletionCallback& callback) { | 
 |   33   int result = net::ERR_CONNECTION_FAILED; | 
 |   34   do { | 
 |   35     if (is_connected_) | 
 |   36       break; | 
|   33  |   37  | 
|   34   net::IPEndPoint ip_end_point; |   38     net::IPEndPoint ip_end_point; | 
|   35   if (!StringAndPortToIPEndPoint(address, port, &ip_end_point)) |   39     if (!StringAndPortToIPEndPoint(address, port, &ip_end_point)) { | 
|   36     return net::ERR_INVALID_ARGUMENT; |   40       result = net::ERR_ADDRESS_INVALID; | 
 |   41       break; | 
 |   42     } | 
|   37  |   43  | 
|   38   int result = socket_.Connect(ip_end_point); |   44     result = socket_.Connect(ip_end_point); | 
|   39   is_connected_ = (result == net::OK); |   45     is_connected_ = (result == net::OK); | 
|   40   return result; |   46   } while (false); | 
 |   47  | 
 |   48   callback.Run(result); | 
|   41 } |   49 } | 
|   42  |   50  | 
|   43 int UDPSocket::Bind(const std::string& address, int port) { |   51 int UDPSocket::Bind(const std::string& address, int port) { | 
|   44   net::IPEndPoint ip_end_point; |   52   net::IPEndPoint ip_end_point; | 
|   45   if (!StringAndPortToIPEndPoint(address, port, &ip_end_point)) |   53   if (!StringAndPortToIPEndPoint(address, port, &ip_end_point)) | 
|   46     return net::ERR_INVALID_ARGUMENT; |   54     return net::ERR_INVALID_ARGUMENT; | 
|   47  |   55  | 
|   48   return socket_.Bind(ip_end_point); |   56   return socket_.Bind(ip_end_point); | 
|   49 } |   57 } | 
|   50  |   58  | 
|   51 void UDPSocket::Disconnect() { |   59 void UDPSocket::Disconnect() { | 
|   52   is_connected_ = false; |   60   is_connected_ = false; | 
|   53   socket_.Close(); |   61   socket_.Close(); | 
|   54 } |   62 } | 
|   55  |   63  | 
|   56 int UDPSocket::Read(scoped_refptr<net::IOBuffer> io_buffer, int io_buffer_len) { |   64 void UDPSocket::Read(int count, | 
|   57   if (!socket_.is_connected()) |   65                      const ReadCompletionCallback& callback) { | 
|   58     return net::ERR_SOCKET_NOT_CONNECTED; |   66   DCHECK(!callback.is_null()); | 
|   59  |   67  | 
|   60   return socket_.Read( |   68   if (!read_callback_.is_null()) { | 
|   61       io_buffer.get(), |   69     callback.Run(net::ERR_IO_PENDING, NULL); | 
|   62       io_buffer_len, |   70     return; | 
|   63       base::Bind(&Socket::OnDataRead, base::Unretained(this), io_buffer, |   71   } else { | 
|   64           static_cast<net::IPEndPoint*>(NULL))); |   72     read_callback_ = callback; | 
 |   73   } | 
 |   74  | 
 |   75   int result = net::ERR_FAILED; | 
 |   76   scoped_refptr<net::IOBuffer> io_buffer; | 
 |   77   do { | 
 |   78     if (count < 0) { | 
 |   79       result = net::ERR_INVALID_ARGUMENT; | 
 |   80       break; | 
 |   81     } | 
 |   82  | 
 |   83     if (!socket_.is_connected()) { | 
 |   84       result = net::ERR_SOCKET_NOT_CONNECTED; | 
 |   85       break; | 
 |   86     } | 
 |   87  | 
 |   88     io_buffer = new net::IOBuffer(count); | 
 |   89     result = socket_.Read(io_buffer.get(), count, | 
 |   90         base::Bind(&UDPSocket::OnReadComplete, base::Unretained(this), | 
 |   91             io_buffer)); | 
 |   92   } while (false); | 
 |   93  | 
 |   94   if (result != net::ERR_IO_PENDING) | 
 |   95     OnReadComplete(io_buffer, result); | 
|   65 } |   96 } | 
|   66  |   97  | 
|   67 int UDPSocket::Write(scoped_refptr<net::IOBuffer> io_buffer, int byte_count) { |   98 void UDPSocket::Write(scoped_refptr<net::IOBuffer> io_buffer, | 
|   68   if (!socket_.is_connected()) |   99                       int byte_count, | 
|   69     return net::ERR_SOCKET_NOT_CONNECTED; |  100                       const CompletionCallback& callback) { | 
 |  101   DCHECK(!callback.is_null()); | 
|   70  |  102  | 
|   71   return socket_.Write( |  103   if (!write_callback_.is_null()) { | 
|   72       io_buffer.get(), byte_count, |  104     // TODO(penghuang): Put requests in a pending queue to support multiple | 
|   73       base::Bind(&Socket::OnWriteComplete, base::Unretained(this))); |  105     // write calls. | 
 |  106     callback.Run(net::ERR_IO_PENDING); | 
 |  107     return; | 
 |  108   } else { | 
 |  109     write_callback_ = callback; | 
 |  110   } | 
 |  111  | 
 |  112   int result = net::ERR_FAILED; | 
 |  113   do { | 
 |  114     if (!socket_.is_connected()) { | 
 |  115       result = net::ERR_SOCKET_NOT_CONNECTED; | 
 |  116       break; | 
 |  117     } | 
 |  118  | 
 |  119     result = socket_.Write( | 
 |  120         io_buffer.get(), byte_count, | 
 |  121         base::Bind(&UDPSocket::OnWriteComplete, base::Unretained(this))); | 
 |  122   } while (false); | 
 |  123  | 
 |  124   if (result != net::ERR_IO_PENDING) | 
 |  125     OnWriteComplete(result); | 
|   74 } |  126 } | 
|   75  |  127  | 
|   76 int UDPSocket::RecvFrom(scoped_refptr<net::IOBuffer> io_buffer, |  128 void UDPSocket::RecvFrom(int count, | 
|   77                         int io_buffer_len, |  129                          const RecvFromCompletionCallback& callback) { | 
|   78                         net::IPEndPoint* address) { |  130   DCHECK(!callback.is_null()); | 
|   79   if (!socket_.is_connected()) |  | 
|   80     return net::ERR_SOCKET_NOT_CONNECTED; |  | 
|   81  |  131  | 
|   82   return socket_.RecvFrom( |  132   if (!recv_from_callback_.is_null()) { | 
|   83       io_buffer.get(), |  133     callback.Run(net::ERR_IO_PENDING, NULL, NULL, 0); | 
|   84       io_buffer_len, |  134     return; | 
|   85       address, |  135   } else { | 
|   86       base::Bind(&Socket::OnDataRead, base::Unretained(this), io_buffer, |  136     recv_from_callback_ = callback; | 
|   87           address)); |  137   } | 
 |  138  | 
 |  139   int result = net::ERR_FAILED; | 
 |  140   scoped_refptr<net::IOBuffer> io_buffer; | 
 |  141   scoped_refptr<IPEndPoint> address; | 
 |  142   do { | 
 |  143     if (count < 0) { | 
 |  144       result = net::ERR_INVALID_ARGUMENT; | 
 |  145       break; | 
 |  146     } | 
 |  147  | 
 |  148     if (!socket_.is_connected()) { | 
 |  149       result = net::ERR_SOCKET_NOT_CONNECTED; | 
 |  150       break; | 
 |  151     } | 
 |  152  | 
 |  153     io_buffer = new net::IOBuffer(count); | 
 |  154     address = new IPEndPoint(); | 
 |  155     result = socket_.RecvFrom( | 
 |  156         io_buffer.get(), | 
 |  157         count, | 
 |  158         &address->data, | 
 |  159         base::Bind(&UDPSocket::OnRecvFromComplete, | 
 |  160                    base::Unretained(this), | 
 |  161                    io_buffer, | 
 |  162                    address)); | 
 |  163   } while (false); | 
 |  164  | 
 |  165   if (result != net::ERR_IO_PENDING) | 
 |  166     OnRecvFromComplete(io_buffer, address, result); | 
|   88 } |  167 } | 
|   89  |  168  | 
|   90 int UDPSocket::SendTo(scoped_refptr<net::IOBuffer> io_buffer, |  169 void UDPSocket::SendTo(scoped_refptr<net::IOBuffer> io_buffer, | 
|   91                       int byte_count, |  170                        int byte_count, | 
|   92                       const std::string& address, |  171                        const std::string& address, | 
|   93                       int port) { |  172                        int port, | 
|   94   net::IPEndPoint ip_end_point; |  173                        const CompletionCallback& callback) { | 
|   95   if (!StringAndPortToIPEndPoint(address, port, &ip_end_point)) |  174   DCHECK(!callback.is_null()); | 
|   96     return net::ERR_INVALID_ARGUMENT; |  | 
|   97  |  175  | 
|   98   if (!socket_.is_connected()) |  176   if (!send_to_callback_.is_null()) { | 
|   99     return net::ERR_SOCKET_NOT_CONNECTED; |  177     // TODO(penghuang): Put requests in a pending queue to support multiple | 
 |  178     // sendTo calls. | 
 |  179     callback.Run(net::ERR_IO_PENDING); | 
 |  180     return; | 
 |  181   } else { | 
 |  182     send_to_callback_ = callback; | 
 |  183   } | 
|  100  |  184  | 
|  101   return socket_.SendTo( |  185   int result = net::ERR_FAILED; | 
|  102       io_buffer.get(), |  186   do { | 
|  103       byte_count, |  187     net::IPEndPoint ip_end_point; | 
|  104       ip_end_point, |  188     if (!StringAndPortToIPEndPoint(address, port, &ip_end_point)) { | 
|  105       base::Bind(&Socket::OnWriteComplete, base::Unretained(this))); |  189       result =  net::ERR_ADDRESS_INVALID; | 
 |  190       break; | 
 |  191     } | 
 |  192  | 
 |  193     if (!socket_.is_connected()) { | 
 |  194       result = net::ERR_SOCKET_NOT_CONNECTED; | 
 |  195       break; | 
 |  196     } | 
 |  197  | 
 |  198     result = socket_.SendTo( | 
 |  199         io_buffer.get(), | 
 |  200         byte_count, | 
 |  201         ip_end_point, | 
 |  202         base::Bind(&UDPSocket::OnSendToComplete, base::Unretained(this))); | 
 |  203   } while (false); | 
 |  204  | 
 |  205   if (result != net::ERR_IO_PENDING) | 
 |  206     OnSendToComplete(result); | 
 |  207 } | 
 |  208  | 
 |  209 void UDPSocket::OnReadComplete(scoped_refptr<net::IOBuffer> io_buffer, | 
 |  210                                int result) { | 
 |  211   DCHECK(!read_callback_.is_null()); | 
 |  212   read_callback_.Run(result, io_buffer); | 
 |  213   read_callback_.Reset(); | 
 |  214 } | 
 |  215  | 
 |  216 void UDPSocket::OnWriteComplete(int result) { | 
 |  217   DCHECK(!write_callback_.is_null()); | 
 |  218   write_callback_.Run(result); | 
 |  219   write_callback_.Reset(); | 
 |  220 } | 
 |  221  | 
 |  222 void UDPSocket::OnRecvFromComplete(scoped_refptr<net::IOBuffer> io_buffer, | 
 |  223                                    scoped_refptr<IPEndPoint> address, | 
 |  224                                    int result) { | 
 |  225   DCHECK(!recv_from_callback_.is_null()); | 
 |  226   std::string ip; | 
 |  227   int port = 0; | 
 |  228   if (result > 0 && address.get()) { | 
 |  229     IPEndPointToStringAndPort(address->data, &ip, &port); | 
 |  230   } | 
 |  231   recv_from_callback_.Run(result, io_buffer, ip, port); | 
 |  232   recv_from_callback_.Reset(); | 
 |  233 } | 
 |  234  | 
 |  235 void UDPSocket::OnSendToComplete(int result) { | 
 |  236   DCHECK(!send_to_callback_.is_null()); | 
 |  237   send_to_callback_.Run(result); | 
 |  238   send_to_callback_.Reset(); | 
|  106 } |  239 } | 
|  107  |  240  | 
|  108 }  // namespace extensions |  241 }  // namespace extensions | 
| OLD | NEW |