Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / extensions / browser / api / socket / udp_socket.cc
blob28220462a4be52c0bf9c10d15600b95282ab4f1d
1 // Copyright 2014 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.
5 #include "extensions/browser/api/socket/udp_socket.h"
7 #include <algorithm>
9 #include "base/lazy_instance.h"
10 #include "extensions/browser/api/api_resource.h"
11 #include "net/base/ip_endpoint.h"
12 #include "net/base/net_errors.h"
13 #include "net/udp/datagram_socket.h"
14 #include "net/udp/udp_client_socket.h"
16 namespace extensions {
18 static base::LazyInstance<
19 BrowserContextKeyedAPIFactory<ApiResourceManager<ResumableUDPSocket> > >
20 g_factory = LAZY_INSTANCE_INITIALIZER;
22 // static
23 template <>
24 BrowserContextKeyedAPIFactory<ApiResourceManager<ResumableUDPSocket> >*
25 ApiResourceManager<ResumableUDPSocket>::GetFactoryInstance() {
26 return g_factory.Pointer();
29 UDPSocket::UDPSocket(const std::string& owner_extension_id)
30 : Socket(owner_extension_id),
31 socket_(net::DatagramSocket::DEFAULT_BIND,
32 net::RandIntCallback(),
33 NULL,
34 net::NetLog::Source()) {}
36 UDPSocket::~UDPSocket() { Disconnect(); }
38 void UDPSocket::Connect(const std::string& address,
39 uint16 port,
40 const CompletionCallback& callback) {
41 int result = net::ERR_CONNECTION_FAILED;
42 do {
43 if (is_connected_)
44 break;
46 net::IPEndPoint ip_end_point;
47 if (!StringAndPortToIPEndPoint(address, port, &ip_end_point)) {
48 result = net::ERR_ADDRESS_INVALID;
49 break;
52 result = socket_.Open(ip_end_point.GetFamily());
53 if (result != net::OK)
54 break;
56 result = socket_.Connect(ip_end_point);
57 if (result != net::OK) {
58 socket_.Close();
59 break;
61 is_connected_ = true;
62 } while (false);
64 callback.Run(result);
67 int UDPSocket::Bind(const std::string& address, uint16 port) {
68 if (IsBound())
69 return net::ERR_CONNECTION_FAILED;
71 net::IPEndPoint ip_end_point;
72 if (!StringAndPortToIPEndPoint(address, port, &ip_end_point))
73 return net::ERR_INVALID_ARGUMENT;
75 int result = socket_.Open(ip_end_point.GetFamily());
76 if (result != net::OK)
77 return result;
79 result = socket_.Bind(ip_end_point);
80 if (result != net::OK)
81 socket_.Close();
82 return result;
85 void UDPSocket::Disconnect() {
86 is_connected_ = false;
87 socket_.Close();
88 read_callback_.Reset();
89 recv_from_callback_.Reset();
90 send_to_callback_.Reset();
91 multicast_groups_.clear();
94 void UDPSocket::Read(int count, const ReadCompletionCallback& callback) {
95 DCHECK(!callback.is_null());
97 if (!read_callback_.is_null()) {
98 callback.Run(net::ERR_IO_PENDING, NULL);
99 return;
100 } else {
101 read_callback_ = callback;
104 int result = net::ERR_FAILED;
105 scoped_refptr<net::IOBuffer> io_buffer;
106 do {
107 if (count < 0) {
108 result = net::ERR_INVALID_ARGUMENT;
109 break;
112 if (!socket_.is_connected()) {
113 result = net::ERR_SOCKET_NOT_CONNECTED;
114 break;
117 io_buffer = new net::IOBuffer(count);
118 result = socket_.Read(
119 io_buffer.get(),
120 count,
121 base::Bind(
122 &UDPSocket::OnReadComplete, base::Unretained(this), io_buffer));
123 } while (false);
125 if (result != net::ERR_IO_PENDING)
126 OnReadComplete(io_buffer, result);
129 int UDPSocket::WriteImpl(net::IOBuffer* io_buffer,
130 int io_buffer_size,
131 const net::CompletionCallback& callback) {
132 if (!socket_.is_connected())
133 return net::ERR_SOCKET_NOT_CONNECTED;
134 else
135 return socket_.Write(io_buffer, io_buffer_size, callback);
138 void UDPSocket::RecvFrom(int count,
139 const RecvFromCompletionCallback& callback) {
140 DCHECK(!callback.is_null());
142 if (!recv_from_callback_.is_null()) {
143 callback.Run(net::ERR_IO_PENDING, NULL, std::string(), 0);
144 return;
145 } else {
146 recv_from_callback_ = callback;
149 int result = net::ERR_FAILED;
150 scoped_refptr<net::IOBuffer> io_buffer;
151 scoped_refptr<IPEndPoint> address;
152 do {
153 if (count < 0) {
154 result = net::ERR_INVALID_ARGUMENT;
155 break;
158 if (!socket_.is_connected()) {
159 result = net::ERR_SOCKET_NOT_CONNECTED;
160 break;
163 io_buffer = new net::IOBuffer(count);
164 address = new IPEndPoint();
165 result = socket_.RecvFrom(io_buffer.get(),
166 count,
167 &address->data,
168 base::Bind(&UDPSocket::OnRecvFromComplete,
169 base::Unretained(this),
170 io_buffer,
171 address));
172 } while (false);
174 if (result != net::ERR_IO_PENDING)
175 OnRecvFromComplete(io_buffer, address, result);
178 void UDPSocket::SendTo(scoped_refptr<net::IOBuffer> io_buffer,
179 int byte_count,
180 const std::string& address,
181 uint16 port,
182 const CompletionCallback& callback) {
183 DCHECK(!callback.is_null());
185 if (!send_to_callback_.is_null()) {
186 // TODO(penghuang): Put requests in a pending queue to support multiple
187 // sendTo calls.
188 callback.Run(net::ERR_IO_PENDING);
189 return;
190 } else {
191 send_to_callback_ = callback;
194 int result = net::ERR_FAILED;
195 do {
196 net::IPEndPoint ip_end_point;
197 if (!StringAndPortToIPEndPoint(address, port, &ip_end_point)) {
198 result = net::ERR_ADDRESS_INVALID;
199 break;
202 if (!socket_.is_connected()) {
203 result = net::ERR_SOCKET_NOT_CONNECTED;
204 break;
207 result = socket_.SendTo(
208 io_buffer.get(),
209 byte_count,
210 ip_end_point,
211 base::Bind(&UDPSocket::OnSendToComplete, base::Unretained(this)));
212 } while (false);
214 if (result != net::ERR_IO_PENDING)
215 OnSendToComplete(result);
218 bool UDPSocket::IsConnected() { return is_connected_; }
220 bool UDPSocket::GetPeerAddress(net::IPEndPoint* address) {
221 return !socket_.GetPeerAddress(address);
224 bool UDPSocket::GetLocalAddress(net::IPEndPoint* address) {
225 return !socket_.GetLocalAddress(address);
228 Socket::SocketType UDPSocket::GetSocketType() const { return Socket::TYPE_UDP; }
230 void UDPSocket::OnReadComplete(scoped_refptr<net::IOBuffer> io_buffer,
231 int result) {
232 DCHECK(!read_callback_.is_null());
233 read_callback_.Run(result, io_buffer);
234 read_callback_.Reset();
237 void UDPSocket::OnRecvFromComplete(scoped_refptr<net::IOBuffer> io_buffer,
238 scoped_refptr<IPEndPoint> address,
239 int result) {
240 DCHECK(!recv_from_callback_.is_null());
241 std::string ip;
242 uint16 port = 0;
243 if (result > 0 && address.get()) {
244 IPEndPointToStringAndPort(address->data, &ip, &port);
246 recv_from_callback_.Run(result, io_buffer, ip, port);
247 recv_from_callback_.Reset();
250 void UDPSocket::OnSendToComplete(int result) {
251 DCHECK(!send_to_callback_.is_null());
252 send_to_callback_.Run(result);
253 send_to_callback_.Reset();
256 bool UDPSocket::IsBound() { return socket_.is_connected(); }
258 int UDPSocket::JoinGroup(const std::string& address) {
259 net::IPAddressNumber ip;
260 if (!net::ParseIPLiteralToNumber(address, &ip))
261 return net::ERR_ADDRESS_INVALID;
263 std::string normalized_address = net::IPAddressToString(ip);
264 std::vector<std::string>::iterator find_result = std::find(
265 multicast_groups_.begin(), multicast_groups_.end(), normalized_address);
266 if (find_result != multicast_groups_.end())
267 return net::ERR_ADDRESS_INVALID;
269 int rv = socket_.JoinGroup(ip);
270 if (rv == 0)
271 multicast_groups_.push_back(normalized_address);
272 return rv;
275 int UDPSocket::LeaveGroup(const std::string& address) {
276 net::IPAddressNumber ip;
277 if (!net::ParseIPLiteralToNumber(address, &ip))
278 return net::ERR_ADDRESS_INVALID;
280 std::string normalized_address = net::IPAddressToString(ip);
281 std::vector<std::string>::iterator find_result = std::find(
282 multicast_groups_.begin(), multicast_groups_.end(), normalized_address);
283 if (find_result == multicast_groups_.end())
284 return net::ERR_ADDRESS_INVALID;
286 int rv = socket_.LeaveGroup(ip);
287 if (rv == 0)
288 multicast_groups_.erase(find_result);
289 return rv;
292 int UDPSocket::SetMulticastTimeToLive(int ttl) {
293 return socket_.SetMulticastTimeToLive(ttl);
296 int UDPSocket::SetMulticastLoopbackMode(bool loopback) {
297 return socket_.SetMulticastLoopbackMode(loopback);
300 int UDPSocket::SetBroadcast(bool enabled) {
301 if (!socket_.is_connected()) {
302 return net::ERR_SOCKET_NOT_CONNECTED;
304 return socket_.SetBroadcast(enabled);
307 const std::vector<std::string>& UDPSocket::GetJoinedGroups() const {
308 return multicast_groups_;
311 ResumableUDPSocket::ResumableUDPSocket(const std::string& owner_extension_id)
312 : UDPSocket(owner_extension_id),
313 persistent_(false),
314 buffer_size_(0),
315 paused_(false) {}
317 bool ResumableUDPSocket::IsPersistent() const { return persistent(); }
319 } // namespace extensions