Chromium Code Reviews| 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 allow_broadcast_(false), | |
| 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 if (allow_broadcast_) { | |
| 234 rv = DoBroadcast(); | |
| 235 if (rv < 0) | |
| 236 return rv; | |
| 237 } | |
| 232 rv = DoBind(address); | 238 rv = DoBind(address); |
| 233 if (rv < 0) | 239 if (rv < 0) |
| 234 return rv; | 240 return rv; |
| 235 local_address_.reset(); | 241 local_address_.reset(); |
| 236 return rv; | 242 return rv; |
| 237 } | 243 } |
| 238 | 244 |
| 239 int UDPSocketWin::CreateSocket(const IPEndPoint& address) { | 245 int UDPSocketWin::CreateSocket(const IPEndPoint& address) { |
| 240 socket_ = WSASocket(address.GetFamily(), SOCK_DGRAM, IPPROTO_UDP, NULL, 0, | 246 socket_ = WSASocket(address.GetFamily(), SOCK_DGRAM, IPPROTO_UDP, NULL, 0, |
| 241 WSA_FLAG_OVERLAPPED); | 247 WSA_FLAG_OVERLAPPED); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 253 } | 259 } |
| 254 | 260 |
| 255 bool UDPSocketWin::SetSendBufferSize(int32 size) { | 261 bool UDPSocketWin::SetSendBufferSize(int32 size) { |
| 256 DCHECK(CalledOnValidThread()); | 262 DCHECK(CalledOnValidThread()); |
| 257 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, | 263 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, |
| 258 reinterpret_cast<const char*>(&size), sizeof(size)); | 264 reinterpret_cast<const char*>(&size), sizeof(size)); |
| 259 DCHECK(!rv) << "Could not set socket send buffer size: " << errno; | 265 DCHECK(!rv) << "Could not set socket send buffer size: " << errno; |
| 260 return rv == 0; | 266 return rv == 0; |
| 261 } | 267 } |
| 262 | 268 |
| 269 void UDPSocketWin::AllowBroadcast() { | |
| 270 DCHECK(CalledOnValidThread()); | |
| 271 DCHECK(!is_connected()); | |
| 272 | |
| 273 allow_broadcast_ = true; | |
| 274 } | |
| 275 | |
| 263 void UDPSocketWin::DoReadCallback(int rv) { | 276 void UDPSocketWin::DoReadCallback(int rv) { |
| 264 DCHECK_NE(rv, ERR_IO_PENDING); | 277 DCHECK_NE(rv, ERR_IO_PENDING); |
| 265 DCHECK(!read_callback_.is_null()); | 278 DCHECK(!read_callback_.is_null()); |
| 266 | 279 |
| 267 // since Run may result in Read being called, clear read_callback_ up front. | 280 // since Run may result in Read being called, clear read_callback_ up front. |
| 268 CompletionCallback c = read_callback_; | 281 CompletionCallback c = read_callback_; |
| 269 read_callback_.Reset(); | 282 read_callback_.Reset(); |
| 270 c.Run(rv); | 283 c.Run(rv); |
| 271 } | 284 } |
| 272 | 285 |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 424 int result = MapSystemError(os_error); | 437 int result = MapSystemError(os_error); |
| 425 LogWrite(result, NULL, NULL); | 438 LogWrite(result, NULL, NULL); |
| 426 return result; | 439 return result; |
| 427 } | 440 } |
| 428 } | 441 } |
| 429 | 442 |
| 430 write_watcher_.StartWatching(write_overlapped_.hEvent, &write_delegate_); | 443 write_watcher_.StartWatching(write_overlapped_.hEvent, &write_delegate_); |
| 431 return ERR_IO_PENDING; | 444 return ERR_IO_PENDING; |
| 432 } | 445 } |
| 433 | 446 |
| 447 int UDPSocketWin::DoBroadcast() { | |
| 448 int true_value = 1; | |
|
wtc
2012/07/11 18:26:37
It looks nicer to use the BOOL type here:
http://m
ygorshenin1
2012/07/12 09:28:08
Done.
| |
| 449 int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, | |
| 450 reinterpret_cast<const char*>(&true_value), | |
| 451 sizeof(true_value)); | |
| 452 if (rv < 0) | |
| 453 return MapSystemError(errno); | |
| 454 rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, | |
| 455 reinterpret_cast<const char*>(&true_value), | |
| 456 sizeof(true_value)); | |
| 457 if (rv < 0) | |
| 458 return MapSystemError(errno); | |
| 459 return OK; | |
| 460 } | |
| 461 | |
| 434 int UDPSocketWin::DoBind(const IPEndPoint& address) { | 462 int UDPSocketWin::DoBind(const IPEndPoint& address) { |
| 435 SockaddrStorage storage; | 463 SockaddrStorage storage; |
| 436 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) | 464 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) |
| 437 return ERR_UNEXPECTED; | 465 return ERR_UNEXPECTED; |
| 438 int rv = bind(socket_, storage.addr, storage.addr_len); | 466 int rv = bind(socket_, storage.addr, storage.addr_len); |
| 439 return rv < 0 ? MapSystemError(WSAGetLastError()) : rv; | 467 return rv < 0 ? MapSystemError(WSAGetLastError()) : rv; |
| 440 } | 468 } |
| 441 | 469 |
| 442 int UDPSocketWin::RandomBind(const IPEndPoint& address) { | 470 int UDPSocketWin::RandomBind(const IPEndPoint& address) { |
| 443 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null()); | 471 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null()); |
| 444 | 472 |
| 445 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s. | 473 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s. |
| 446 IPAddressNumber ip(address.address().size()); | 474 IPAddressNumber ip(address.address().size()); |
| 447 | 475 |
| 448 for (int i = 0; i < kBindRetries; ++i) { | 476 for (int i = 0; i < kBindRetries; ++i) { |
| 449 int rv = DoBind(IPEndPoint(ip, rand_int_cb_.Run(kPortStart, kPortEnd))); | 477 int rv = DoBind(IPEndPoint(ip, rand_int_cb_.Run(kPortStart, kPortEnd))); |
| 450 if (rv == OK || rv != ERR_ADDRESS_IN_USE) | 478 if (rv == OK || rv != ERR_ADDRESS_IN_USE) |
| 451 return rv; | 479 return rv; |
| 452 } | 480 } |
| 453 return DoBind(IPEndPoint(ip, 0)); | 481 return DoBind(IPEndPoint(ip, 0)); |
| 454 } | 482 } |
| 455 | 483 |
| 456 bool UDPSocketWin::ReceiveAddressToIPEndpoint(IPEndPoint* address) const { | 484 bool UDPSocketWin::ReceiveAddressToIPEndpoint(IPEndPoint* address) const { |
| 457 const struct sockaddr* addr = | 485 const struct sockaddr* addr = |
| 458 reinterpret_cast<const struct sockaddr*>(&recv_addr_storage_); | 486 reinterpret_cast<const struct sockaddr*>(&recv_addr_storage_); |
| 459 return address->FromSockAddr(addr, recv_addr_len_); | 487 return address->FromSockAddr(addr, recv_addr_len_); |
| 460 } | 488 } |
| 461 | 489 |
| 462 } // namespace net | 490 } // namespace net |
| OLD | NEW |