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 : binding_(this, request
.Pass()),
39 socket_(net::DatagramSocket::DEFAULT_BIND
,
40 net::RandIntCallback(),
42 net::NetLog::Source()),
43 state_(NOT_BOUND_OR_CONNECTED
),
44 allow_address_reuse_(false),
45 remaining_recv_slots_(0),
46 max_pending_send_requests_(kDefaultMaxPendingSendRequests
) {
49 UDPSocketImpl::~UDPSocketImpl() {
50 STLDeleteElements(&pending_send_requests_
);
53 void UDPSocketImpl::AllowAddressReuse(
54 const Callback
<void(NetworkErrorPtr
)>& callback
) {
55 if (IsBoundOrConnected()) {
56 callback
.Run(MakeNetworkError(net::ERR_FAILED
));
60 allow_address_reuse_
= true;
61 callback
.Run(MakeNetworkError(net::OK
));
64 void UDPSocketImpl::Bind(
66 const Callback
<void(NetworkErrorPtr
,
68 InterfaceRequest
<UDPSocketReceiver
>)>& callback
) {
69 int net_result
= net::OK
;
73 if (IsBoundOrConnected()) {
74 net_result
= net::ERR_FAILED
;
78 net::IPEndPoint ip_end_point
= addr
.To
<net::IPEndPoint
>();
79 if (ip_end_point
.GetFamily() == net::ADDRESS_FAMILY_UNSPECIFIED
) {
80 net_result
= net::ERR_ADDRESS_INVALID
;
84 net_result
= socket_
.Open(ip_end_point
.GetFamily());
85 if (net_result
!= net::OK
)
89 if (allow_address_reuse_
) {
90 net_result
= socket_
.AllowAddressReuse();
91 if (net_result
!= net::OK
)
95 net_result
= socket_
.Bind(ip_end_point
);
96 if (net_result
!= net::OK
)
99 net::IPEndPoint bound_ip_end_point
;
100 net_result
= socket_
.GetLocalAddress(&bound_ip_end_point
);
101 if (net_result
!= net::OK
)
105 callback
.Run(MakeNetworkError(net_result
),
106 NetAddress::From(bound_ip_end_point
), GetProxy(&receiver_
));
108 if (remaining_recv_slots_
> 0) {
109 DCHECK(!recvfrom_buffer_
.get());
115 DCHECK(net_result
!= net::OK
);
118 callback
.Run(MakeNetworkError(net_result
), nullptr, nullptr);
121 void UDPSocketImpl::Connect(
122 NetAddressPtr remote_addr
,
123 const Callback
<void(NetworkErrorPtr
,
125 InterfaceRequest
<UDPSocketReceiver
>)>& callback
) {
126 int net_result
= net::OK
;
130 if (IsBoundOrConnected()) {
131 net_result
= net::ERR_FAILED
;
135 net::IPEndPoint ip_end_point
= remote_addr
.To
<net::IPEndPoint
>();
136 if (ip_end_point
.GetFamily() == net::ADDRESS_FAMILY_UNSPECIFIED
) {
137 net_result
= net::ERR_ADDRESS_INVALID
;
141 net_result
= socket_
.Open(ip_end_point
.GetFamily());
142 if (net_result
!= net::OK
)
146 net_result
= socket_
.Connect(ip_end_point
);
147 if (net_result
!= net::OK
)
150 net::IPEndPoint local_ip_end_point
;
151 net_result
= socket_
.GetLocalAddress(&local_ip_end_point
);
152 if (net_result
!= net::OK
)
156 callback
.Run(MakeNetworkError(net_result
),
157 NetAddress::From(local_ip_end_point
), GetProxy(&receiver_
));
159 if (remaining_recv_slots_
> 0) {
160 DCHECK(!recvfrom_buffer_
.get());
166 DCHECK(net_result
!= net::OK
);
169 callback
.Run(MakeNetworkError(net_result
), nullptr, nullptr);
172 void UDPSocketImpl::SetSendBufferSize(
174 const Callback
<void(NetworkErrorPtr
)>& callback
) {
175 if (!IsBoundOrConnected()) {
176 callback
.Run(MakeNetworkError(net::ERR_FAILED
));
180 if (size
> static_cast<uint32_t>(std::numeric_limits
<int32_t>::max()))
181 size
= std::numeric_limits
<int32_t>::max();
183 int net_result
= socket_
.SetSendBufferSize(static_cast<int32_t>(size
));
184 callback
.Run(MakeNetworkError(net_result
));
187 void UDPSocketImpl::SetReceiveBufferSize(
189 const Callback
<void(NetworkErrorPtr
)>& callback
) {
190 if (!IsBoundOrConnected()) {
191 callback
.Run(MakeNetworkError(net::ERR_FAILED
));
195 if (size
> static_cast<uint32_t>(std::numeric_limits
<int32_t>::max()))
196 size
= std::numeric_limits
<int32_t>::max();
198 int net_result
= socket_
.SetReceiveBufferSize(static_cast<int32_t>(size
));
199 callback
.Run(MakeNetworkError(net_result
));
202 void UDPSocketImpl::NegotiateMaxPendingSendRequests(
203 uint32_t requested_size
,
204 const Callback
<void(uint32_t)>& callback
) {
205 if (requested_size
!= 0) {
206 max_pending_send_requests_
=
207 std::min(kMaxPendingSendRequestsUpperbound
,
208 static_cast<size_t>(requested_size
));
210 callback
.Run(static_cast<uint32_t>(max_pending_send_requests_
));
212 if (pending_send_requests_
.size() > max_pending_send_requests_
) {
213 std::deque
<PendingSendRequest
*> discarded_requests(
214 pending_send_requests_
.begin() + max_pending_send_requests_
,
215 pending_send_requests_
.end());
216 pending_send_requests_
.resize(max_pending_send_requests_
);
217 for (auto& discarded_request
: discarded_requests
) {
218 discarded_request
->callback
.Run(
219 MakeNetworkError(net::ERR_INSUFFICIENT_RESOURCES
));
220 delete discarded_request
;
225 void UDPSocketImpl::ReceiveMore(uint32_t datagram_number
) {
228 if (datagram_number
== 0)
230 if (std::numeric_limits
<size_t>::max() - remaining_recv_slots_
<
235 remaining_recv_slots_
+= datagram_number
;
237 if (IsBoundOrConnected() && !recvfrom_buffer_
.get()) {
238 DCHECK_EQ(datagram_number
, remaining_recv_slots_
);
243 void UDPSocketImpl::SendTo(NetAddressPtr dest_addr
,
245 const Callback
<void(NetworkErrorPtr
)>& callback
) {
246 if (!IsBoundOrConnected()) {
247 callback
.Run(MakeNetworkError(net::ERR_FAILED
));
250 if (state_
== BOUND
&& !dest_addr
) {
251 callback
.Run(MakeNetworkError(net::ERR_INVALID_ARGUMENT
));
255 if (sendto_buffer_
.get()) {
256 if (pending_send_requests_
.size() >= max_pending_send_requests_
) {
257 callback
.Run(MakeNetworkError(net::ERR_INSUFFICIENT_RESOURCES
));
261 PendingSendRequest
* request
= new PendingSendRequest
;
262 request
->addr
= dest_addr
.Pass();
263 request
->data
= data
.Pass();
264 request
->callback
= callback
;
265 pending_send_requests_
.push_back(request
);
269 DCHECK_EQ(0u, pending_send_requests_
.size());
271 DoSendTo(dest_addr
.Pass(), data
.Pass(), callback
);
274 void UDPSocketImpl::DoRecvFrom() {
275 DCHECK(IsBoundOrConnected());
277 DCHECK(!recvfrom_buffer_
.get());
278 DCHECK_GT(remaining_recv_slots_
, 0u);
280 recvfrom_buffer_
= new net::IOBuffer(kMaxReadSize
);
282 // It is safe to use base::Unretained(this) because |socket_| is owned by this
283 // object. If this object gets destroyed (and so does |socket_|), the callback
285 int net_result
= socket_
.RecvFrom(
286 recvfrom_buffer_
.get(),
288 state_
== BOUND
? &recvfrom_address_
: nullptr,
289 base::Bind(&UDPSocketImpl::OnRecvFromCompleted
, base::Unretained(this)));
290 if (net_result
!= net::ERR_IO_PENDING
)
291 OnRecvFromCompleted(net_result
);
294 void UDPSocketImpl::DoSendTo(NetAddressPtr addr
,
296 const Callback
<void(NetworkErrorPtr
)>& callback
) {
297 DCHECK(IsBoundOrConnected());
298 DCHECK(!sendto_buffer_
.get());
300 if (data
.size() > kMaxWriteSize
) {
301 callback
.Run(MakeNetworkError(net::ERR_INVALID_ARGUMENT
));
304 sendto_buffer_
= new net::IOBufferWithSize(static_cast<int>(data
.size()));
306 memcpy(sendto_buffer_
->data(), &data
.storage()[0], data
.size());
308 int net_result
= net::OK
;
310 net::IPEndPoint ip_end_point
= addr
.To
<net::IPEndPoint
>();
311 if (ip_end_point
.GetFamily() == net::ADDRESS_FAMILY_UNSPECIFIED
) {
312 callback
.Run(MakeNetworkError(net::ERR_ADDRESS_INVALID
));
316 // It is safe to use base::Unretained(this) because |socket_| is owned by
317 // this object. If this object gets destroyed (and so does |socket_|), the
318 // callback won't be called.
319 net_result
= socket_
.SendTo(sendto_buffer_
.get(), sendto_buffer_
->size(),
321 base::Bind(&UDPSocketImpl::OnSendToCompleted
,
322 base::Unretained(this), callback
));
324 DCHECK(state_
== CONNECTED
);
325 net_result
= socket_
.Write(sendto_buffer_
.get(), sendto_buffer_
->size(),
326 base::Bind(&UDPSocketImpl::OnSendToCompleted
,
327 base::Unretained(this), callback
));
329 if (net_result
!= net::ERR_IO_PENDING
)
330 OnSendToCompleted(callback
, net_result
);
333 void UDPSocketImpl::OnRecvFromCompleted(int net_result
) {
334 DCHECK(recvfrom_buffer_
.get());
336 NetAddressPtr net_address
;
337 Array
<uint8_t> array
;
338 if (net_result
>= 0) {
340 net_address
= NetAddress::From(recvfrom_address_
);
342 std::vector
<uint8_t> data(net_result
);
344 memcpy(&data
[0], recvfrom_buffer_
->data(), net_result
);
348 recvfrom_buffer_
= nullptr;
350 receiver_
->OnReceived(MakeNetworkError(net_result
), net_address
.Pass(),
352 DCHECK_GT(remaining_recv_slots_
, 0u);
353 remaining_recv_slots_
--;
354 if (remaining_recv_slots_
> 0)
358 void UDPSocketImpl::OnSendToCompleted(
359 const Callback
<void(NetworkErrorPtr
)>& callback
,
361 DCHECK(sendto_buffer_
.get());
363 sendto_buffer_
= nullptr;
365 callback
.Run(MakeNetworkError(net_result
));
367 if (pending_send_requests_
.empty())
370 scoped_ptr
<PendingSendRequest
> request(pending_send_requests_
.front());
371 pending_send_requests_
.pop_front();
373 DoSendTo(request
->addr
.Pass(), request
->data
.Pass(), request
->callback
);