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"
24 const int kMaxReadSize
= 128 * 1024;
25 const size_t kMaxWriteSize
= 128 * 1024;
26 const size_t kMaxPendingSendRequestsUpperbound
= 128;
27 const size_t kDefaultMaxPendingSendRequests
= 32;
31 UDPSocketImpl::PendingSendRequest::PendingSendRequest() {}
33 UDPSocketImpl::PendingSendRequest::~PendingSendRequest() {}
35 UDPSocketImpl::UDPSocketImpl()
36 : socket_(nullptr, net::NetLog::Source()),
38 remaining_recv_slots_(0),
39 max_pending_send_requests_(kDefaultMaxPendingSendRequests
) {
42 UDPSocketImpl::~UDPSocketImpl() {
43 STLDeleteElements(&pending_send_requests_
);
46 void UDPSocketImpl::AllowAddressReuse(
47 const Callback
<void(NetworkErrorPtr
)>& callback
) {
49 callback
.Run(MakeNetworkError(net::ERR_FAILED
));
53 socket_
.AllowAddressReuse();
54 callback
.Run(MakeNetworkError(net::OK
));
57 void UDPSocketImpl::Bind(
59 const Callback
<void(NetworkErrorPtr
, NetAddressPtr
)>& callback
) {
61 callback
.Run(MakeNetworkError(net::ERR_FAILED
), NetAddressPtr());
65 net::IPEndPoint ip_end_point
= addr
.To
<net::IPEndPoint
>();
66 if (ip_end_point
.GetFamily() == net::ADDRESS_FAMILY_UNSPECIFIED
) {
67 callback
.Run(MakeNetworkError(net::ERR_ADDRESS_INVALID
), NetAddressPtr());
71 int net_result
= socket_
.Listen(ip_end_point
);
72 if (net_result
!= net::OK
) {
73 callback
.Run(MakeNetworkError(net_result
), NetAddressPtr());
77 net::IPEndPoint bound_ip_end_point
;
78 NetAddressPtr bound_addr
;
79 net_result
= socket_
.GetLocalAddress(&bound_ip_end_point
);
80 if (net_result
== net::OK
)
81 bound_addr
= NetAddress::From(bound_ip_end_point
);
84 callback
.Run(MakeNetworkError(net::OK
), bound_addr
.Pass());
86 if (remaining_recv_slots_
> 0) {
87 DCHECK(!recvfrom_buffer_
.get());
92 void UDPSocketImpl::SetSendBufferSize(
94 const Callback
<void(NetworkErrorPtr
)>& callback
) {
96 callback
.Run(MakeNetworkError(net::ERR_FAILED
));
100 if (size
> static_cast<uint32_t>(std::numeric_limits
<int32_t>::max()))
101 size
= std::numeric_limits
<int32_t>::max();
103 int net_result
= socket_
.SetSendBufferSize(static_cast<int32_t>(size
));
104 callback
.Run(MakeNetworkError(net_result
));
107 void UDPSocketImpl::SetReceiveBufferSize(
109 const Callback
<void(NetworkErrorPtr
)>& callback
) {
111 callback
.Run(MakeNetworkError(net::ERR_FAILED
));
115 if (size
> static_cast<uint32_t>(std::numeric_limits
<int32_t>::max()))
116 size
= std::numeric_limits
<int32_t>::max();
118 int net_result
= socket_
.SetReceiveBufferSize(static_cast<int32_t>(size
));
119 callback
.Run(MakeNetworkError(net_result
));
122 void UDPSocketImpl::NegotiateMaxPendingSendRequests(
123 uint32_t requested_size
,
124 const Callback
<void(uint32_t)>& callback
) {
125 if (requested_size
!= 0) {
126 max_pending_send_requests_
=
127 std::min(kMaxPendingSendRequestsUpperbound
,
128 static_cast<size_t>(requested_size
));
130 callback
.Run(static_cast<uint32_t>(max_pending_send_requests_
));
132 if (pending_send_requests_
.size() > max_pending_send_requests_
) {
133 std::deque
<PendingSendRequest
*> discarded_requests(
134 pending_send_requests_
.begin() + max_pending_send_requests_
,
135 pending_send_requests_
.end());
136 pending_send_requests_
.resize(max_pending_send_requests_
);
137 for (auto& discarded_request
: discarded_requests
) {
138 discarded_request
->callback
.Run(
139 MakeNetworkError(net::ERR_INSUFFICIENT_RESOURCES
));
140 delete discarded_request
;
145 void UDPSocketImpl::ReceiveMore(uint32_t datagram_number
) {
146 if (datagram_number
== 0)
148 if (std::numeric_limits
<size_t>::max() - remaining_recv_slots_
<
153 remaining_recv_slots_
+= datagram_number
;
155 if (bound_
&& !recvfrom_buffer_
.get()) {
156 DCHECK_EQ(datagram_number
, remaining_recv_slots_
);
161 void UDPSocketImpl::SendTo(NetAddressPtr dest_addr
,
163 const Callback
<void(NetworkErrorPtr
)>& callback
) {
165 callback
.Run(MakeNetworkError(net::ERR_FAILED
));
169 if (sendto_buffer_
.get()) {
170 if (pending_send_requests_
.size() >= max_pending_send_requests_
) {
171 callback
.Run(MakeNetworkError(net::ERR_INSUFFICIENT_RESOURCES
));
175 PendingSendRequest
* request
= new PendingSendRequest
;
176 request
->addr
= dest_addr
.Pass();
177 request
->data
= data
.Pass();
178 request
->callback
= callback
;
179 pending_send_requests_
.push_back(request
);
183 DCHECK_EQ(0u, pending_send_requests_
.size());
185 DoSendTo(dest_addr
.Pass(), data
.Pass(), callback
);
188 void UDPSocketImpl::DoRecvFrom() {
190 DCHECK(!recvfrom_buffer_
.get());
191 DCHECK_GT(remaining_recv_slots_
, 0u);
193 recvfrom_buffer_
= new net::IOBuffer(kMaxReadSize
);
195 // It is safe to use base::Unretained(this) because |socket_| is owned by this
196 // object. If this object gets destroyed (and so does |socket_|), the callback
198 int net_result
= socket_
.RecvFrom(
199 recvfrom_buffer_
.get(),
202 base::Bind(&UDPSocketImpl::OnRecvFromCompleted
, base::Unretained(this)));
203 if (net_result
!= net::ERR_IO_PENDING
)
204 OnRecvFromCompleted(net_result
);
207 void UDPSocketImpl::DoSendTo(NetAddressPtr addr
,
209 const Callback
<void(NetworkErrorPtr
)>& callback
) {
211 DCHECK(!sendto_buffer_
.get());
213 net::IPEndPoint ip_end_point
= addr
.To
<net::IPEndPoint
>();
214 if (ip_end_point
.GetFamily() == net::ADDRESS_FAMILY_UNSPECIFIED
) {
215 callback
.Run(MakeNetworkError(net::ERR_ADDRESS_INVALID
));
219 if (data
.size() > kMaxWriteSize
) {
220 callback
.Run(MakeNetworkError(net::ERR_INVALID_ARGUMENT
));
223 sendto_buffer_
= new net::IOBufferWithSize(static_cast<int>(data
.size()));
225 memcpy(sendto_buffer_
->data(), &data
.storage()[0], data
.size());
227 // It is safe to use base::Unretained(this) because |socket_| is owned by this
228 // object. If this object gets destroyed (and so does |socket_|), the callback
230 int net_result
= socket_
.SendTo(sendto_buffer_
.get(), sendto_buffer_
->size(),
232 base::Bind(&UDPSocketImpl::OnSendToCompleted
,
233 base::Unretained(this), callback
));
234 if (net_result
!= net::ERR_IO_PENDING
)
235 OnSendToCompleted(callback
, net_result
);
238 void UDPSocketImpl::OnRecvFromCompleted(int net_result
) {
239 DCHECK(recvfrom_buffer_
.get());
241 NetAddressPtr net_address
;
242 Array
<uint8_t> array
;
243 if (net_result
>= 0) {
244 net_address
= NetAddress::From(recvfrom_address_
);
245 std::vector
<uint8_t> data(net_result
);
247 memcpy(&data
[0], recvfrom_buffer_
->data(), net_result
);
251 recvfrom_buffer_
= nullptr;
253 client()->OnReceived(MakeNetworkError(net_result
), net_address
.Pass(),
256 DCHECK_GT(remaining_recv_slots_
, 0u);
257 remaining_recv_slots_
--;
258 if (remaining_recv_slots_
> 0)
262 void UDPSocketImpl::OnSendToCompleted(
263 const Callback
<void(NetworkErrorPtr
)>& callback
,
265 DCHECK(sendto_buffer_
.get());
267 sendto_buffer_
= nullptr;
269 callback
.Run(MakeNetworkError(net_result
));
271 if (pending_send_requests_
.empty())
274 scoped_ptr
<PendingSendRequest
> request(pending_send_requests_
.front());
275 pending_send_requests_
.pop_front();
277 DoSendTo(request
->addr
.Pass(), request
->data
.Pass(), request
->callback
);