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 "mojo/services/network/udp_socket_impl.h"
12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/stl_util.h"
15 #include "mojo/services/network/net_adapters.h"
16 #include "mojo/services/network/net_address_type_converters.h"
17 #include "net/base/io_buffer.h"
18 #include "net/base/net_errors.h"
19 #include "net/base/rand_callback.h"
20 #include "net/udp/datagram_socket.h"
26 const int kMaxReadSize
= 128 * 1024;
27 const size_t kMaxWriteSize
= 128 * 1024;
28 const size_t kMaxPendingSendRequestsUpperbound
= 128;
29 const size_t kDefaultMaxPendingSendRequests
= 32;
33 UDPSocketImpl::PendingSendRequest::PendingSendRequest() {}
35 UDPSocketImpl::PendingSendRequest::~PendingSendRequest() {}
37 UDPSocketImpl::UDPSocketImpl(InterfaceRequest
<UDPSocket
> request
,
38 scoped_ptr
<mojo::AppRefCount
> app_refcount
)
39 : binding_(this, request
.Pass()),
40 socket_(net::DatagramSocket::DEFAULT_BIND
,
41 net::RandIntCallback(),
43 net::NetLog::Source()),
44 state_(NOT_BOUND_OR_CONNECTED
),
45 allow_address_reuse_(false),
46 remaining_recv_slots_(0),
47 max_pending_send_requests_(kDefaultMaxPendingSendRequests
),
48 app_refcount_(app_refcount
.Pass()) {
51 UDPSocketImpl::~UDPSocketImpl() {
52 STLDeleteElements(&pending_send_requests_
);
55 void UDPSocketImpl::AllowAddressReuse(
56 const Callback
<void(NetworkErrorPtr
)>& callback
) {
57 if (IsBoundOrConnected()) {
58 callback
.Run(MakeNetworkError(net::ERR_FAILED
));
62 allow_address_reuse_
= true;
63 callback
.Run(MakeNetworkError(net::OK
));
66 void UDPSocketImpl::Bind(
68 const Callback
<void(NetworkErrorPtr
,
70 InterfaceRequest
<UDPSocketReceiver
>)>& callback
) {
71 int net_result
= net::OK
;
75 if (IsBoundOrConnected()) {
76 net_result
= net::ERR_FAILED
;
80 net::IPEndPoint ip_end_point
= addr
.To
<net::IPEndPoint
>();
81 if (ip_end_point
.GetFamily() == net::ADDRESS_FAMILY_UNSPECIFIED
) {
82 net_result
= net::ERR_ADDRESS_INVALID
;
86 net_result
= socket_
.Open(ip_end_point
.GetFamily());
87 if (net_result
!= net::OK
)
91 if (allow_address_reuse_
) {
92 net_result
= socket_
.AllowAddressReuse();
93 if (net_result
!= net::OK
)
97 net_result
= socket_
.Bind(ip_end_point
);
98 if (net_result
!= net::OK
)
101 net::IPEndPoint bound_ip_end_point
;
102 net_result
= socket_
.GetLocalAddress(&bound_ip_end_point
);
103 if (net_result
!= net::OK
)
107 callback
.Run(MakeNetworkError(net_result
),
108 NetAddress::From(bound_ip_end_point
), GetProxy(&receiver_
));
110 if (remaining_recv_slots_
> 0) {
111 DCHECK(!recvfrom_buffer_
.get());
117 DCHECK(net_result
!= net::OK
);
120 callback
.Run(MakeNetworkError(net_result
), nullptr, nullptr);
123 void UDPSocketImpl::Connect(
124 NetAddressPtr remote_addr
,
125 const Callback
<void(NetworkErrorPtr
,
127 InterfaceRequest
<UDPSocketReceiver
>)>& callback
) {
128 int net_result
= net::OK
;
132 if (IsBoundOrConnected()) {
133 net_result
= net::ERR_FAILED
;
137 net::IPEndPoint ip_end_point
= remote_addr
.To
<net::IPEndPoint
>();
138 if (ip_end_point
.GetFamily() == net::ADDRESS_FAMILY_UNSPECIFIED
) {
139 net_result
= net::ERR_ADDRESS_INVALID
;
143 net_result
= socket_
.Open(ip_end_point
.GetFamily());
144 if (net_result
!= net::OK
)
148 net_result
= socket_
.Connect(ip_end_point
);
149 if (net_result
!= net::OK
)
152 net::IPEndPoint local_ip_end_point
;
153 net_result
= socket_
.GetLocalAddress(&local_ip_end_point
);
154 if (net_result
!= net::OK
)
158 callback
.Run(MakeNetworkError(net_result
),
159 NetAddress::From(local_ip_end_point
), GetProxy(&receiver_
));
161 if (remaining_recv_slots_
> 0) {
162 DCHECK(!recvfrom_buffer_
.get());
168 DCHECK(net_result
!= net::OK
);
171 callback
.Run(MakeNetworkError(net_result
), nullptr, nullptr);
174 void UDPSocketImpl::SetSendBufferSize(
176 const Callback
<void(NetworkErrorPtr
)>& callback
) {
177 if (!IsBoundOrConnected()) {
178 callback
.Run(MakeNetworkError(net::ERR_FAILED
));
182 if (size
> static_cast<uint32_t>(std::numeric_limits
<int32_t>::max()))
183 size
= std::numeric_limits
<int32_t>::max();
185 int net_result
= socket_
.SetSendBufferSize(static_cast<int32_t>(size
));
186 callback
.Run(MakeNetworkError(net_result
));
189 void UDPSocketImpl::SetReceiveBufferSize(
191 const Callback
<void(NetworkErrorPtr
)>& callback
) {
192 if (!IsBoundOrConnected()) {
193 callback
.Run(MakeNetworkError(net::ERR_FAILED
));
197 if (size
> static_cast<uint32_t>(std::numeric_limits
<int32_t>::max()))
198 size
= std::numeric_limits
<int32_t>::max();
200 int net_result
= socket_
.SetReceiveBufferSize(static_cast<int32_t>(size
));
201 callback
.Run(MakeNetworkError(net_result
));
204 void UDPSocketImpl::NegotiateMaxPendingSendRequests(
205 uint32_t requested_size
,
206 const Callback
<void(uint32_t)>& callback
) {
207 if (requested_size
!= 0) {
208 max_pending_send_requests_
=
209 std::min(kMaxPendingSendRequestsUpperbound
,
210 static_cast<size_t>(requested_size
));
212 callback
.Run(static_cast<uint32_t>(max_pending_send_requests_
));
214 if (pending_send_requests_
.size() > max_pending_send_requests_
) {
215 std::deque
<PendingSendRequest
*> discarded_requests(
216 pending_send_requests_
.begin() + max_pending_send_requests_
,
217 pending_send_requests_
.end());
218 pending_send_requests_
.resize(max_pending_send_requests_
);
219 for (auto& discarded_request
: discarded_requests
) {
220 discarded_request
->callback
.Run(
221 MakeNetworkError(net::ERR_INSUFFICIENT_RESOURCES
));
222 delete discarded_request
;
227 void UDPSocketImpl::ReceiveMore(uint32_t datagram_number
) {
230 if (datagram_number
== 0)
232 if (std::numeric_limits
<size_t>::max() - remaining_recv_slots_
<
237 remaining_recv_slots_
+= datagram_number
;
239 if (IsBoundOrConnected() && !recvfrom_buffer_
.get()) {
240 DCHECK_EQ(datagram_number
, remaining_recv_slots_
);
245 void UDPSocketImpl::SendTo(NetAddressPtr dest_addr
,
247 const Callback
<void(NetworkErrorPtr
)>& callback
) {
248 if (!IsBoundOrConnected()) {
249 callback
.Run(MakeNetworkError(net::ERR_FAILED
));
252 if (state_
== BOUND
&& !dest_addr
) {
253 callback
.Run(MakeNetworkError(net::ERR_INVALID_ARGUMENT
));
257 if (sendto_buffer_
.get()) {
258 if (pending_send_requests_
.size() >= max_pending_send_requests_
) {
259 callback
.Run(MakeNetworkError(net::ERR_INSUFFICIENT_RESOURCES
));
263 PendingSendRequest
* request
= new PendingSendRequest
;
264 request
->addr
= dest_addr
.Pass();
265 request
->data
= data
.Pass();
266 request
->callback
= callback
;
267 pending_send_requests_
.push_back(request
);
271 DCHECK_EQ(0u, pending_send_requests_
.size());
273 DoSendTo(dest_addr
.Pass(), data
.Pass(), callback
);
276 void UDPSocketImpl::DoRecvFrom() {
277 DCHECK(IsBoundOrConnected());
279 DCHECK(!recvfrom_buffer_
.get());
280 DCHECK_GT(remaining_recv_slots_
, 0u);
282 recvfrom_buffer_
= new net::IOBuffer(kMaxReadSize
);
284 // It is safe to use base::Unretained(this) because |socket_| is owned by this
285 // object. If this object gets destroyed (and so does |socket_|), the callback
287 int net_result
= socket_
.RecvFrom(
288 recvfrom_buffer_
.get(),
290 state_
== BOUND
? &recvfrom_address_
: nullptr,
291 base::Bind(&UDPSocketImpl::OnRecvFromCompleted
, base::Unretained(this)));
292 if (net_result
!= net::ERR_IO_PENDING
)
293 OnRecvFromCompleted(net_result
);
296 void UDPSocketImpl::DoSendTo(NetAddressPtr addr
,
298 const Callback
<void(NetworkErrorPtr
)>& callback
) {
299 DCHECK(IsBoundOrConnected());
300 DCHECK(!sendto_buffer_
.get());
302 if (data
.size() > kMaxWriteSize
) {
303 callback
.Run(MakeNetworkError(net::ERR_INVALID_ARGUMENT
));
306 sendto_buffer_
= new net::IOBufferWithSize(static_cast<int>(data
.size()));
308 memcpy(sendto_buffer_
->data(), &data
.storage()[0], data
.size());
310 int net_result
= net::OK
;
312 net::IPEndPoint ip_end_point
= addr
.To
<net::IPEndPoint
>();
313 if (ip_end_point
.GetFamily() == net::ADDRESS_FAMILY_UNSPECIFIED
) {
314 callback
.Run(MakeNetworkError(net::ERR_ADDRESS_INVALID
));
318 // It is safe to use base::Unretained(this) because |socket_| is owned by
319 // this object. If this object gets destroyed (and so does |socket_|), the
320 // callback won't be called.
321 net_result
= socket_
.SendTo(sendto_buffer_
.get(), sendto_buffer_
->size(),
323 base::Bind(&UDPSocketImpl::OnSendToCompleted
,
324 base::Unretained(this), callback
));
326 DCHECK(state_
== CONNECTED
);
327 net_result
= socket_
.Write(sendto_buffer_
.get(), sendto_buffer_
->size(),
328 base::Bind(&UDPSocketImpl::OnSendToCompleted
,
329 base::Unretained(this), callback
));
331 if (net_result
!= net::ERR_IO_PENDING
)
332 OnSendToCompleted(callback
, net_result
);
335 void UDPSocketImpl::OnRecvFromCompleted(int net_result
) {
336 DCHECK(recvfrom_buffer_
.get());
338 NetAddressPtr net_address
;
339 Array
<uint8_t> array
;
340 if (net_result
>= 0) {
342 net_address
= NetAddress::From(recvfrom_address_
);
344 std::vector
<uint8_t> data(net_result
);
346 memcpy(&data
[0], recvfrom_buffer_
->data(), net_result
);
350 recvfrom_buffer_
= nullptr;
352 receiver_
->OnReceived(MakeNetworkError(net_result
), net_address
.Pass(),
354 DCHECK_GT(remaining_recv_slots_
, 0u);
355 remaining_recv_slots_
--;
356 if (remaining_recv_slots_
> 0)
360 void UDPSocketImpl::OnSendToCompleted(
361 const Callback
<void(NetworkErrorPtr
)>& callback
,
363 DCHECK(sendto_buffer_
.get());
365 sendto_buffer_
= nullptr;
367 callback
.Run(MakeNetworkError(net_result
));
369 if (pending_send_requests_
.empty())
372 scoped_ptr
<PendingSendRequest
> request(pending_send_requests_
.front());
373 pending_send_requests_
.pop_front();
375 DoSendTo(request
->addr
.Pass(), request
->data
.Pass(), request
->callback
);