Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(168)

Side by Side Diff: mojo/services/network/udp_socket_impl.cc

Issue 863253002: Update from https://crrev.com/312600 (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 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 "mojo/services/network/udp_socket_impl.h" 5 #include "mojo/services/network/udp_socket_impl.h"
6 6
7 #include <string.h> 7 #include <string.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <limits> 10 #include <limits>
11 11
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h" 13 #include "base/memory/scoped_ptr.h"
14 #include "base/stl_util.h" 14 #include "base/stl_util.h"
15 #include "mojo/services/network/net_adapters.h" 15 #include "mojo/services/network/net_adapters.h"
16 #include "mojo/services/network/net_address_type_converters.h" 16 #include "mojo/services/network/net_address_type_converters.h"
17 #include "net/base/io_buffer.h" 17 #include "net/base/io_buffer.h"
18 #include "net/base/net_errors.h" 18 #include "net/base/net_errors.h"
19 #include "net/base/rand_callback.h"
20 #include "net/udp/datagram_socket.h"
19 21
20 namespace mojo { 22 namespace mojo {
21 23
22 namespace { 24 namespace {
23 25
24 const int kMaxReadSize = 128 * 1024; 26 const int kMaxReadSize = 128 * 1024;
25 const size_t kMaxWriteSize = 128 * 1024; 27 const size_t kMaxWriteSize = 128 * 1024;
26 const size_t kMaxPendingSendRequestsUpperbound = 128; 28 const size_t kMaxPendingSendRequestsUpperbound = 128;
27 const size_t kDefaultMaxPendingSendRequests = 32; 29 const size_t kDefaultMaxPendingSendRequests = 32;
28 30
29 } // namespace 31 } // namespace
30 32
31 UDPSocketImpl::PendingSendRequest::PendingSendRequest() {} 33 UDPSocketImpl::PendingSendRequest::PendingSendRequest() {}
32 34
33 UDPSocketImpl::PendingSendRequest::~PendingSendRequest() {} 35 UDPSocketImpl::PendingSendRequest::~PendingSendRequest() {}
34 36
35 UDPSocketImpl::UDPSocketImpl() 37 UDPSocketImpl::UDPSocketImpl()
36 : socket_(nullptr, net::NetLog::Source()), 38 : socket_(net::DatagramSocket::DEFAULT_BIND, net::RandIntCallback(),
37 bound_(false), 39 nullptr, net::NetLog::Source()),
40 state_(NOT_BOUND_OR_CONNECTED),
41 allow_address_reuse_(false),
38 remaining_recv_slots_(0), 42 remaining_recv_slots_(0),
39 max_pending_send_requests_(kDefaultMaxPendingSendRequests) { 43 max_pending_send_requests_(kDefaultMaxPendingSendRequests) {
40 } 44 }
41 45
42 UDPSocketImpl::~UDPSocketImpl() { 46 UDPSocketImpl::~UDPSocketImpl() {
43 STLDeleteElements(&pending_send_requests_); 47 STLDeleteElements(&pending_send_requests_);
44 } 48 }
45 49
46 void UDPSocketImpl::AllowAddressReuse( 50 void UDPSocketImpl::AllowAddressReuse(
47 const Callback<void(NetworkErrorPtr)>& callback) { 51 const Callback<void(NetworkErrorPtr)>& callback) {
48 if (bound_) { 52 if (IsBoundOrConnected()) {
49 callback.Run(MakeNetworkError(net::ERR_FAILED)); 53 callback.Run(MakeNetworkError(net::ERR_FAILED));
50 return; 54 return;
51 } 55 }
52 56
53 socket_.AllowAddressReuse(); 57 allow_address_reuse_ = true;
54 callback.Run(MakeNetworkError(net::OK)); 58 callback.Run(MakeNetworkError(net::OK));
55 } 59 }
56 60
57 void UDPSocketImpl::Bind( 61 void UDPSocketImpl::Bind(
58 NetAddressPtr addr, 62 NetAddressPtr addr,
59 const Callback<void(NetworkErrorPtr, NetAddressPtr)>& callback) { 63 const Callback<void(NetworkErrorPtr, NetAddressPtr)>& callback) {
60 if (bound_) { 64 int net_result = net::OK;
61 callback.Run(MakeNetworkError(net::ERR_FAILED), NetAddressPtr()); 65 bool opened = false;
66
67 do {
68 if (IsBoundOrConnected()) {
69 net_result = net::ERR_FAILED;
70 break;
71 }
72
73 net::IPEndPoint ip_end_point = addr.To<net::IPEndPoint>();
74 if (ip_end_point.GetFamily() == net::ADDRESS_FAMILY_UNSPECIFIED) {
75 net_result = net::ERR_ADDRESS_INVALID;
76 break;
77 }
78
79 net_result = socket_.Open(ip_end_point.GetFamily());
80 if (net_result != net::OK)
81 break;
82 opened = true;
83
84 if (allow_address_reuse_) {
85 net_result = socket_.AllowAddressReuse();
86 if (net_result != net::OK)
87 break;
88 }
89
90 net_result = socket_.Bind(ip_end_point);
91 if (net_result != net::OK)
92 break;
93
94 net::IPEndPoint bound_ip_end_point;
95 net_result = socket_.GetLocalAddress(&bound_ip_end_point);
96 if (net_result != net::OK)
97 break;
98
99 state_ = BOUND;
100 callback.Run(MakeNetworkError(net_result),
101 NetAddress::From(bound_ip_end_point));
102
103 if (remaining_recv_slots_ > 0) {
104 DCHECK(!recvfrom_buffer_.get());
105 DoRecvFrom();
106 }
62 return; 107 return;
63 } 108 } while (false);
64 109
65 net::IPEndPoint ip_end_point = addr.To<net::IPEndPoint>(); 110 DCHECK(net_result != net::OK);
66 if (ip_end_point.GetFamily() == net::ADDRESS_FAMILY_UNSPECIFIED) { 111 if (opened)
67 callback.Run(MakeNetworkError(net::ERR_ADDRESS_INVALID), NetAddressPtr()); 112 socket_.Close();
68 return; 113 callback.Run(MakeNetworkError(net_result), nullptr);
69 }
70
71 int net_result = socket_.Listen(ip_end_point);
72 if (net_result != net::OK) {
73 callback.Run(MakeNetworkError(net_result), NetAddressPtr());
74 return;
75 }
76
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);
82
83 bound_ = true;
84 callback.Run(MakeNetworkError(net::OK), bound_addr.Pass());
85
86 if (remaining_recv_slots_ > 0) {
87 DCHECK(!recvfrom_buffer_.get());
88 DoRecvFrom();
89 }
90 } 114 }
91 115
92 void UDPSocketImpl::Connect( 116 void UDPSocketImpl::Connect(
93 NetAddressPtr remote_addr, 117 NetAddressPtr remote_addr,
94 const Callback<void(NetworkErrorPtr, NetAddressPtr)>& callback) { 118 const Callback<void(NetworkErrorPtr, NetAddressPtr)>& callback) {
95 // TODO(yzshen): Implement it. 119 int net_result = net::OK;
120 bool opened = false;
121
122 do {
123 if (IsBoundOrConnected()) {
124 net_result = net::ERR_FAILED;
125 break;
126 }
127
128 net::IPEndPoint ip_end_point = remote_addr.To<net::IPEndPoint>();
129 if (ip_end_point.GetFamily() == net::ADDRESS_FAMILY_UNSPECIFIED) {
130 net_result = net::ERR_ADDRESS_INVALID;
131 break;
132 }
133
134 net_result = socket_.Open(ip_end_point.GetFamily());
135 if (net_result != net::OK)
136 break;
137 opened = true;
138
139 net_result = socket_.Connect(ip_end_point);
140 if (net_result != net::OK)
141 break;
142
143 net::IPEndPoint local_ip_end_point;
144 net_result = socket_.GetLocalAddress(&local_ip_end_point);
145 if (net_result != net::OK)
146 break;
147
148 state_ = CONNECTED;
149 callback.Run(MakeNetworkError(net_result),
150 NetAddress::From(local_ip_end_point));
151
152 if (remaining_recv_slots_ > 0) {
153 DCHECK(!recvfrom_buffer_.get());
154 DoRecvFrom();
155 }
156 return;
157 } while (false);
158
159 DCHECK(net_result != net::OK);
160 if (opened)
161 socket_.Close();
162 callback.Run(MakeNetworkError(net_result), nullptr);
96 } 163 }
97 164
98 void UDPSocketImpl::SetSendBufferSize( 165 void UDPSocketImpl::SetSendBufferSize(
99 uint32_t size, 166 uint32_t size,
100 const Callback<void(NetworkErrorPtr)>& callback) { 167 const Callback<void(NetworkErrorPtr)>& callback) {
101 if (!bound_) { 168 if (!IsBoundOrConnected()) {
102 callback.Run(MakeNetworkError(net::ERR_FAILED)); 169 callback.Run(MakeNetworkError(net::ERR_FAILED));
103 return; 170 return;
104 } 171 }
105 172
106 if (size > static_cast<uint32_t>(std::numeric_limits<int32_t>::max())) 173 if (size > static_cast<uint32_t>(std::numeric_limits<int32_t>::max()))
107 size = std::numeric_limits<int32_t>::max(); 174 size = std::numeric_limits<int32_t>::max();
108 175
109 int net_result = socket_.SetSendBufferSize(static_cast<int32_t>(size)); 176 int net_result = socket_.SetSendBufferSize(static_cast<int32_t>(size));
110 callback.Run(MakeNetworkError(net_result)); 177 callback.Run(MakeNetworkError(net_result));
111 } 178 }
112 179
113 void UDPSocketImpl::SetReceiveBufferSize( 180 void UDPSocketImpl::SetReceiveBufferSize(
114 uint32_t size, 181 uint32_t size,
115 const Callback<void(NetworkErrorPtr)>& callback) { 182 const Callback<void(NetworkErrorPtr)>& callback) {
116 if (!bound_) { 183 if (!IsBoundOrConnected()) {
117 callback.Run(MakeNetworkError(net::ERR_FAILED)); 184 callback.Run(MakeNetworkError(net::ERR_FAILED));
118 return; 185 return;
119 } 186 }
120 187
121 if (size > static_cast<uint32_t>(std::numeric_limits<int32_t>::max())) 188 if (size > static_cast<uint32_t>(std::numeric_limits<int32_t>::max()))
122 size = std::numeric_limits<int32_t>::max(); 189 size = std::numeric_limits<int32_t>::max();
123 190
124 int net_result = socket_.SetReceiveBufferSize(static_cast<int32_t>(size)); 191 int net_result = socket_.SetReceiveBufferSize(static_cast<int32_t>(size));
125 callback.Run(MakeNetworkError(net_result)); 192 callback.Run(MakeNetworkError(net_result));
126 } 193 }
(...skipping 24 matching lines...) Expand all
151 void UDPSocketImpl::ReceiveMore(uint32_t datagram_number) { 218 void UDPSocketImpl::ReceiveMore(uint32_t datagram_number) {
152 if (datagram_number == 0) 219 if (datagram_number == 0)
153 return; 220 return;
154 if (std::numeric_limits<size_t>::max() - remaining_recv_slots_ < 221 if (std::numeric_limits<size_t>::max() - remaining_recv_slots_ <
155 datagram_number) { 222 datagram_number) {
156 return; 223 return;
157 } 224 }
158 225
159 remaining_recv_slots_ += datagram_number; 226 remaining_recv_slots_ += datagram_number;
160 227
161 if (bound_ && !recvfrom_buffer_.get()) { 228 if (IsBoundOrConnected() && !recvfrom_buffer_.get()) {
162 DCHECK_EQ(datagram_number, remaining_recv_slots_); 229 DCHECK_EQ(datagram_number, remaining_recv_slots_);
163 DoRecvFrom(); 230 DoRecvFrom();
164 } 231 }
165 } 232 }
166 233
167 void UDPSocketImpl::SendTo(NetAddressPtr dest_addr, 234 void UDPSocketImpl::SendTo(NetAddressPtr dest_addr,
168 Array<uint8_t> data, 235 Array<uint8_t> data,
169 const Callback<void(NetworkErrorPtr)>& callback) { 236 const Callback<void(NetworkErrorPtr)>& callback) {
170 if (!bound_) { 237 if (!IsBoundOrConnected()) {
171 callback.Run(MakeNetworkError(net::ERR_FAILED)); 238 callback.Run(MakeNetworkError(net::ERR_FAILED));
172 return; 239 return;
173 } 240 }
241 if (state_ == BOUND && !dest_addr) {
242 callback.Run(MakeNetworkError(net::ERR_INVALID_ARGUMENT));
243 return;
244 }
174 245
175 if (sendto_buffer_.get()) { 246 if (sendto_buffer_.get()) {
176 if (pending_send_requests_.size() >= max_pending_send_requests_) { 247 if (pending_send_requests_.size() >= max_pending_send_requests_) {
177 callback.Run(MakeNetworkError(net::ERR_INSUFFICIENT_RESOURCES)); 248 callback.Run(MakeNetworkError(net::ERR_INSUFFICIENT_RESOURCES));
178 return; 249 return;
179 } 250 }
180 251
181 PendingSendRequest* request = new PendingSendRequest; 252 PendingSendRequest* request = new PendingSendRequest;
182 request->addr = dest_addr.Pass(); 253 request->addr = dest_addr.Pass();
183 request->data = data.Pass(); 254 request->data = data.Pass();
184 request->callback = callback; 255 request->callback = callback;
185 pending_send_requests_.push_back(request); 256 pending_send_requests_.push_back(request);
186 return; 257 return;
187 } 258 }
188 259
189 DCHECK_EQ(0u, pending_send_requests_.size()); 260 DCHECK_EQ(0u, pending_send_requests_.size());
190 261
191 DoSendTo(dest_addr.Pass(), data.Pass(), callback); 262 DoSendTo(dest_addr.Pass(), data.Pass(), callback);
192 } 263 }
193 264
194 void UDPSocketImpl::DoRecvFrom() { 265 void UDPSocketImpl::DoRecvFrom() {
195 DCHECK(bound_); 266 DCHECK(IsBoundOrConnected());
196 DCHECK(!recvfrom_buffer_.get()); 267 DCHECK(!recvfrom_buffer_.get());
197 DCHECK_GT(remaining_recv_slots_, 0u); 268 DCHECK_GT(remaining_recv_slots_, 0u);
198 269
199 recvfrom_buffer_ = new net::IOBuffer(kMaxReadSize); 270 recvfrom_buffer_ = new net::IOBuffer(kMaxReadSize);
200 271
201 // It is safe to use base::Unretained(this) because |socket_| is owned by this 272 // It is safe to use base::Unretained(this) because |socket_| is owned by this
202 // object. If this object gets destroyed (and so does |socket_|), the callback 273 // object. If this object gets destroyed (and so does |socket_|), the callback
203 // won't be called. 274 // won't be called.
204 int net_result = socket_.RecvFrom( 275 int net_result = socket_.RecvFrom(
205 recvfrom_buffer_.get(), 276 recvfrom_buffer_.get(),
206 kMaxReadSize, 277 kMaxReadSize,
207 &recvfrom_address_, 278 state_ == BOUND ? &recvfrom_address_ : nullptr,
208 base::Bind(&UDPSocketImpl::OnRecvFromCompleted, base::Unretained(this))); 279 base::Bind(&UDPSocketImpl::OnRecvFromCompleted, base::Unretained(this)));
209 if (net_result != net::ERR_IO_PENDING) 280 if (net_result != net::ERR_IO_PENDING)
210 OnRecvFromCompleted(net_result); 281 OnRecvFromCompleted(net_result);
211 } 282 }
212 283
213 void UDPSocketImpl::DoSendTo(NetAddressPtr addr, 284 void UDPSocketImpl::DoSendTo(NetAddressPtr addr,
214 Array<uint8_t> data, 285 Array<uint8_t> data,
215 const Callback<void(NetworkErrorPtr)>& callback) { 286 const Callback<void(NetworkErrorPtr)>& callback) {
216 DCHECK(bound_); 287 DCHECK(IsBoundOrConnected());
217 DCHECK(!sendto_buffer_.get()); 288 DCHECK(!sendto_buffer_.get());
218 289
219 net::IPEndPoint ip_end_point = addr.To<net::IPEndPoint>();
220 if (ip_end_point.GetFamily() == net::ADDRESS_FAMILY_UNSPECIFIED) {
221 callback.Run(MakeNetworkError(net::ERR_ADDRESS_INVALID));
222 return;
223 }
224
225 if (data.size() > kMaxWriteSize) { 290 if (data.size() > kMaxWriteSize) {
226 callback.Run(MakeNetworkError(net::ERR_INVALID_ARGUMENT)); 291 callback.Run(MakeNetworkError(net::ERR_INVALID_ARGUMENT));
227 return; 292 return;
228 } 293 }
229 sendto_buffer_ = new net::IOBufferWithSize(static_cast<int>(data.size())); 294 sendto_buffer_ = new net::IOBufferWithSize(static_cast<int>(data.size()));
230 if (data.size() > 0) 295 if (data.size() > 0)
231 memcpy(sendto_buffer_->data(), &data.storage()[0], data.size()); 296 memcpy(sendto_buffer_->data(), &data.storage()[0], data.size());
232 297
233 // It is safe to use base::Unretained(this) because |socket_| is owned by this 298 int net_result = net::OK;
234 // object. If this object gets destroyed (and so does |socket_|), the callback 299 if (addr) {
235 // won't be called. 300 net::IPEndPoint ip_end_point = addr.To<net::IPEndPoint>();
236 int net_result = socket_.SendTo(sendto_buffer_.get(), sendto_buffer_->size(), 301 if (ip_end_point.GetFamily() == net::ADDRESS_FAMILY_UNSPECIFIED) {
237 ip_end_point, 302 callback.Run(MakeNetworkError(net::ERR_ADDRESS_INVALID));
238 base::Bind(&UDPSocketImpl::OnSendToCompleted, 303 return;
239 base::Unretained(this), callback)); 304 }
305
306 // It is safe to use base::Unretained(this) because |socket_| is owned by
307 // this object. If this object gets destroyed (and so does |socket_|), the
308 // callback won't be called.
309 net_result = socket_.SendTo(sendto_buffer_.get(), sendto_buffer_->size(),
310 ip_end_point,
311 base::Bind(&UDPSocketImpl::OnSendToCompleted,
312 base::Unretained(this), callback));
313 } else {
314 DCHECK(state_ == CONNECTED);
315 net_result = socket_.Write(sendto_buffer_.get(), sendto_buffer_->size(),
316 base::Bind(&UDPSocketImpl::OnSendToCompleted,
317 base::Unretained(this), callback));
318 }
240 if (net_result != net::ERR_IO_PENDING) 319 if (net_result != net::ERR_IO_PENDING)
241 OnSendToCompleted(callback, net_result); 320 OnSendToCompleted(callback, net_result);
242 } 321 }
243 322
244 void UDPSocketImpl::OnRecvFromCompleted(int net_result) { 323 void UDPSocketImpl::OnRecvFromCompleted(int net_result) {
245 DCHECK(recvfrom_buffer_.get()); 324 DCHECK(recvfrom_buffer_.get());
246 325
247 NetAddressPtr net_address; 326 NetAddressPtr net_address;
248 Array<uint8_t> array; 327 Array<uint8_t> array;
249 if (net_result >= 0) { 328 if (net_result >= 0) {
250 net_address = NetAddress::From(recvfrom_address_); 329 if (state_ == BOUND)
330 net_address = NetAddress::From(recvfrom_address_);
331
251 std::vector<uint8_t> data(net_result); 332 std::vector<uint8_t> data(net_result);
252 if (net_result > 0) 333 if (net_result > 0)
253 memcpy(&data[0], recvfrom_buffer_->data(), net_result); 334 memcpy(&data[0], recvfrom_buffer_->data(), net_result);
254 335
255 array.Swap(&data); 336 array.Swap(&data);
256 } 337 }
257 recvfrom_buffer_ = nullptr; 338 recvfrom_buffer_ = nullptr;
258 339
259 client()->OnReceived(MakeNetworkError(net_result), net_address.Pass(), 340 client()->OnReceived(MakeNetworkError(net_result), net_address.Pass(),
260 array.Pass()); 341 array.Pass());
(...skipping 16 matching lines...) Expand all
277 if (pending_send_requests_.empty()) 358 if (pending_send_requests_.empty())
278 return; 359 return;
279 360
280 scoped_ptr<PendingSendRequest> request(pending_send_requests_.front()); 361 scoped_ptr<PendingSendRequest> request(pending_send_requests_.front());
281 pending_send_requests_.pop_front(); 362 pending_send_requests_.pop_front();
282 363
283 DoSendTo(request->addr.Pass(), request->data.Pass(), request->callback); 364 DoSendTo(request->addr.Pass(), request->data.Pass(), request->callback);
284 } 365 }
285 366
286 } // namespace mojo 367 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698