OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "net/udp/udp_socket_win.h" | 5 #include "net/udp/udp_socket_win.h" |
6 | 6 |
7 #include <mstcpip.h> | 7 #include <mstcpip.h> |
8 | 8 |
9 #include "base/callback.h" | 9 #include "base/callback.h" |
10 #include "base/eintr_wrapper.h" | 10 #include "base/eintr_wrapper.h" |
(...skipping 28 matching lines...) Expand all Loading... |
39 void UDPSocketWin::WriteDelegate::OnObjectSignaled(HANDLE object) { | 39 void UDPSocketWin::WriteDelegate::OnObjectSignaled(HANDLE object) { |
40 DCHECK_EQ(object, socket_->write_overlapped_.hEvent); | 40 DCHECK_EQ(object, socket_->write_overlapped_.hEvent); |
41 socket_->DidCompleteWrite(); | 41 socket_->DidCompleteWrite(); |
42 } | 42 } |
43 | 43 |
44 UDPSocketWin::UDPSocketWin(DatagramSocket::BindType bind_type, | 44 UDPSocketWin::UDPSocketWin(DatagramSocket::BindType bind_type, |
45 const RandIntCallback& rand_int_cb, | 45 const RandIntCallback& rand_int_cb, |
46 net::NetLog* net_log, | 46 net::NetLog* net_log, |
47 const net::NetLog::Source& source) | 47 const net::NetLog::Source& source) |
48 : socket_(INVALID_SOCKET), | 48 : socket_(INVALID_SOCKET), |
| 49 socket_options_(0), |
49 bind_type_(bind_type), | 50 bind_type_(bind_type), |
50 rand_int_cb_(rand_int_cb), | 51 rand_int_cb_(rand_int_cb), |
51 ALLOW_THIS_IN_INITIALIZER_LIST(read_delegate_(this)), | 52 ALLOW_THIS_IN_INITIALIZER_LIST(read_delegate_(this)), |
52 ALLOW_THIS_IN_INITIALIZER_LIST(write_delegate_(this)), | 53 ALLOW_THIS_IN_INITIALIZER_LIST(write_delegate_(this)), |
53 recv_from_address_(NULL), | 54 recv_from_address_(NULL), |
54 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) { | 55 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) { |
55 EnsureWinsockInit(); | 56 EnsureWinsockInit(); |
56 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, | 57 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, |
57 source.ToEventParametersCallback()); | 58 source.ToEventParametersCallback()); |
58 memset(&read_overlapped_, 0, sizeof(read_overlapped_)); | 59 memset(&read_overlapped_, 0, sizeof(read_overlapped_)); |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
222 | 223 |
223 remote_address_.reset(new IPEndPoint(address)); | 224 remote_address_.reset(new IPEndPoint(address)); |
224 return rv; | 225 return rv; |
225 } | 226 } |
226 | 227 |
227 int UDPSocketWin::Bind(const IPEndPoint& address) { | 228 int UDPSocketWin::Bind(const IPEndPoint& address) { |
228 DCHECK(!is_connected()); | 229 DCHECK(!is_connected()); |
229 int rv = CreateSocket(address); | 230 int rv = CreateSocket(address); |
230 if (rv < 0) | 231 if (rv < 0) |
231 return rv; | 232 return rv; |
| 233 rv = SetSocketOptions(); |
| 234 if (rv < 0) |
| 235 return rv; |
232 rv = DoBind(address); | 236 rv = DoBind(address); |
233 if (rv < 0) | 237 if (rv < 0) |
234 return rv; | 238 return rv; |
235 local_address_.reset(); | 239 local_address_.reset(); |
236 return rv; | 240 return rv; |
237 } | 241 } |
238 | 242 |
239 int UDPSocketWin::CreateSocket(const IPEndPoint& address) { | 243 int UDPSocketWin::CreateSocket(const IPEndPoint& address) { |
240 socket_ = WSASocket(address.GetFamily(), SOCK_DGRAM, IPPROTO_UDP, NULL, 0, | 244 socket_ = WSASocket(address.GetFamily(), SOCK_DGRAM, IPPROTO_UDP, NULL, 0, |
241 WSA_FLAG_OVERLAPPED); | 245 WSA_FLAG_OVERLAPPED); |
(...skipping 11 matching lines...) Expand all Loading... |
253 } | 257 } |
254 | 258 |
255 bool UDPSocketWin::SetSendBufferSize(int32 size) { | 259 bool UDPSocketWin::SetSendBufferSize(int32 size) { |
256 DCHECK(CalledOnValidThread()); | 260 DCHECK(CalledOnValidThread()); |
257 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, | 261 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, |
258 reinterpret_cast<const char*>(&size), sizeof(size)); | 262 reinterpret_cast<const char*>(&size), sizeof(size)); |
259 DCHECK(!rv) << "Could not set socket send buffer size: " << errno; | 263 DCHECK(!rv) << "Could not set socket send buffer size: " << errno; |
260 return rv == 0; | 264 return rv == 0; |
261 } | 265 } |
262 | 266 |
| 267 void UDPSocketWin::AllowAddressReuse() { |
| 268 DCHECK(CalledOnValidThread()); |
| 269 DCHECK(!is_connected()); |
| 270 |
| 271 socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS; |
| 272 } |
| 273 |
| 274 void UDPSocketWin::AllowBroadcast() { |
| 275 DCHECK(CalledOnValidThread()); |
| 276 DCHECK(!is_connected()); |
| 277 |
| 278 socket_options_ |= SOCKET_OPTION_BROADCAST; |
| 279 } |
| 280 |
263 void UDPSocketWin::DoReadCallback(int rv) { | 281 void UDPSocketWin::DoReadCallback(int rv) { |
264 DCHECK_NE(rv, ERR_IO_PENDING); | 282 DCHECK_NE(rv, ERR_IO_PENDING); |
265 DCHECK(!read_callback_.is_null()); | 283 DCHECK(!read_callback_.is_null()); |
266 | 284 |
267 // since Run may result in Read being called, clear read_callback_ up front. | 285 // since Run may result in Read being called, clear read_callback_ up front. |
268 CompletionCallback c = read_callback_; | 286 CompletionCallback c = read_callback_; |
269 read_callback_.Reset(); | 287 read_callback_.Reset(); |
270 c.Run(rv); | 288 c.Run(rv); |
271 } | 289 } |
272 | 290 |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
424 int result = MapSystemError(os_error); | 442 int result = MapSystemError(os_error); |
425 LogWrite(result, NULL, NULL); | 443 LogWrite(result, NULL, NULL); |
426 return result; | 444 return result; |
427 } | 445 } |
428 } | 446 } |
429 | 447 |
430 write_watcher_.StartWatching(write_overlapped_.hEvent, &write_delegate_); | 448 write_watcher_.StartWatching(write_overlapped_.hEvent, &write_delegate_); |
431 return ERR_IO_PENDING; | 449 return ERR_IO_PENDING; |
432 } | 450 } |
433 | 451 |
| 452 int UDPSocketWin::SetSocketOptions() { |
| 453 BOOL true_value = 1; |
| 454 if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) { |
| 455 int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, |
| 456 reinterpret_cast<const char*>(&true_value), |
| 457 sizeof(true_value)); |
| 458 if (rv < 0) |
| 459 return MapSystemError(errno); |
| 460 } |
| 461 if (socket_options_ & SOCKET_OPTION_BROADCAST) { |
| 462 int rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, |
| 463 reinterpret_cast<const char*>(&true_value), |
| 464 sizeof(true_value)); |
| 465 if (rv < 0) |
| 466 return MapSystemError(errno); |
| 467 } |
| 468 return OK; |
| 469 } |
| 470 |
434 int UDPSocketWin::DoBind(const IPEndPoint& address) { | 471 int UDPSocketWin::DoBind(const IPEndPoint& address) { |
435 SockaddrStorage storage; | 472 SockaddrStorage storage; |
436 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) | 473 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) |
437 return ERR_UNEXPECTED; | 474 return ERR_UNEXPECTED; |
438 int rv = bind(socket_, storage.addr, storage.addr_len); | 475 int rv = bind(socket_, storage.addr, storage.addr_len); |
439 return rv < 0 ? MapSystemError(WSAGetLastError()) : rv; | 476 return rv < 0 ? MapSystemError(WSAGetLastError()) : rv; |
440 } | 477 } |
441 | 478 |
442 int UDPSocketWin::RandomBind(const IPEndPoint& address) { | 479 int UDPSocketWin::RandomBind(const IPEndPoint& address) { |
443 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null()); | 480 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null()); |
444 | 481 |
445 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s. | 482 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s. |
446 IPAddressNumber ip(address.address().size()); | 483 IPAddressNumber ip(address.address().size()); |
447 | 484 |
448 for (int i = 0; i < kBindRetries; ++i) { | 485 for (int i = 0; i < kBindRetries; ++i) { |
449 int rv = DoBind(IPEndPoint(ip, rand_int_cb_.Run(kPortStart, kPortEnd))); | 486 int rv = DoBind(IPEndPoint(ip, rand_int_cb_.Run(kPortStart, kPortEnd))); |
450 if (rv == OK || rv != ERR_ADDRESS_IN_USE) | 487 if (rv == OK || rv != ERR_ADDRESS_IN_USE) |
451 return rv; | 488 return rv; |
452 } | 489 } |
453 return DoBind(IPEndPoint(ip, 0)); | 490 return DoBind(IPEndPoint(ip, 0)); |
454 } | 491 } |
455 | 492 |
456 bool UDPSocketWin::ReceiveAddressToIPEndpoint(IPEndPoint* address) const { | 493 bool UDPSocketWin::ReceiveAddressToIPEndpoint(IPEndPoint* address) const { |
457 const struct sockaddr* addr = | 494 const struct sockaddr* addr = |
458 reinterpret_cast<const struct sockaddr*>(&recv_addr_storage_); | 495 reinterpret_cast<const struct sockaddr*>(&recv_addr_storage_); |
459 return address->FromSockAddr(addr, recv_addr_len_); | 496 return address->FromSockAddr(addr, recv_addr_len_); |
460 } | 497 } |
461 | 498 |
462 } // namespace net | 499 } // namespace net |
OLD | NEW |