| 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/basictypes.h" | 9 #include "base/basictypes.h" |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 248 | 248 |
| 249 | 249 |
| 250 //----------------------------------------------------------------------------- | 250 //----------------------------------------------------------------------------- |
| 251 | 251 |
| 252 UDPSocketWin::UDPSocketWin(DatagramSocket::BindType bind_type, | 252 UDPSocketWin::UDPSocketWin(DatagramSocket::BindType bind_type, |
| 253 const RandIntCallback& rand_int_cb, | 253 const RandIntCallback& rand_int_cb, |
| 254 net::NetLog* net_log, | 254 net::NetLog* net_log, |
| 255 const net::NetLog::Source& source) | 255 const net::NetLog::Source& source) |
| 256 : socket_(INVALID_SOCKET), | 256 : socket_(INVALID_SOCKET), |
| 257 addr_family_(0), | 257 addr_family_(0), |
| 258 is_connected_(false), |
| 258 socket_options_(SOCKET_OPTION_MULTICAST_LOOP), | 259 socket_options_(SOCKET_OPTION_MULTICAST_LOOP), |
| 259 multicast_interface_(0), | 260 multicast_interface_(0), |
| 260 multicast_time_to_live_(1), | 261 multicast_time_to_live_(1), |
| 261 bind_type_(bind_type), | 262 bind_type_(bind_type), |
| 262 rand_int_cb_(rand_int_cb), | 263 rand_int_cb_(rand_int_cb), |
| 263 recv_from_address_(NULL), | 264 recv_from_address_(NULL), |
| 264 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)), | 265 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)), |
| 265 qos_handle_(NULL), | 266 qos_handle_(NULL), |
| 266 qos_flow_id_(0) { | 267 qos_flow_id_(0) { |
| 267 EnsureWinsockInit(); | 268 EnsureWinsockInit(); |
| 268 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, | 269 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, |
| 269 source.ToEventParametersCallback()); | 270 source.ToEventParametersCallback()); |
| 270 if (bind_type == DatagramSocket::RANDOM_BIND) | 271 if (bind_type == DatagramSocket::RANDOM_BIND) |
| 271 DCHECK(!rand_int_cb.is_null()); | 272 DCHECK(!rand_int_cb.is_null()); |
| 272 } | 273 } |
| 273 | 274 |
| 274 UDPSocketWin::~UDPSocketWin() { | 275 UDPSocketWin::~UDPSocketWin() { |
| 275 Close(); | 276 Close(); |
| 276 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); | 277 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); |
| 277 } | 278 } |
| 278 | 279 |
| 280 int UDPSocketWin::Open(AddressFamily address_family) { |
| 281 DCHECK(CalledOnValidThread()); |
| 282 DCHECK_EQ(socket_, INVALID_SOCKET); |
| 283 |
| 284 addr_family_ = ConvertAddressFamily(address_family); |
| 285 socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, IPPROTO_UDP); |
| 286 if (socket_ == INVALID_SOCKET) |
| 287 return MapSystemError(WSAGetLastError()); |
| 288 core_ = new Core(this); |
| 289 return OK; |
| 290 } |
| 291 |
| 279 void UDPSocketWin::Close() { | 292 void UDPSocketWin::Close() { |
| 280 DCHECK(CalledOnValidThread()); | 293 DCHECK(CalledOnValidThread()); |
| 281 | 294 |
| 282 if (!is_connected()) | 295 if (socket_ == INVALID_SOCKET) |
| 283 return; | 296 return; |
| 284 | 297 |
| 285 if (qos_handle_) { | 298 if (qos_handle_) { |
| 286 QwaveAPI::Get().CloseHandle(qos_handle_); | 299 QwaveAPI::Get().CloseHandle(qos_handle_); |
| 287 } | 300 } |
| 288 | 301 |
| 289 // Zero out any pending read/write callback state. | 302 // Zero out any pending read/write callback state. |
| 290 read_callback_.Reset(); | 303 read_callback_.Reset(); |
| 291 recv_from_address_ = NULL; | 304 recv_from_address_ = NULL; |
| 292 write_callback_.Reset(); | 305 write_callback_.Reset(); |
| 293 | 306 |
| 294 base::TimeTicks start_time = base::TimeTicks::Now(); | 307 base::TimeTicks start_time = base::TimeTicks::Now(); |
| 295 closesocket(socket_); | 308 closesocket(socket_); |
| 296 UMA_HISTOGRAM_TIMES("Net.UDPSocketWinClose", | 309 UMA_HISTOGRAM_TIMES("Net.UDPSocketWinClose", |
| 297 base::TimeTicks::Now() - start_time); | 310 base::TimeTicks::Now() - start_time); |
| 298 socket_ = INVALID_SOCKET; | 311 socket_ = INVALID_SOCKET; |
| 299 addr_family_ = 0; | 312 addr_family_ = 0; |
| 313 is_connected_ = false; |
| 300 | 314 |
| 301 core_->Detach(); | 315 core_->Detach(); |
| 302 core_ = NULL; | 316 core_ = NULL; |
| 303 } | 317 } |
| 304 | 318 |
| 305 int UDPSocketWin::GetPeerAddress(IPEndPoint* address) const { | 319 int UDPSocketWin::GetPeerAddress(IPEndPoint* address) const { |
| 306 DCHECK(CalledOnValidThread()); | 320 DCHECK(CalledOnValidThread()); |
| 307 DCHECK(address); | 321 DCHECK(address); |
| 308 if (!is_connected()) | 322 if (!is_connected()) |
| 309 return ERR_SOCKET_NOT_CONNECTED; | 323 return ERR_SOCKET_NOT_CONNECTED; |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 400 if (nwrite != ERR_IO_PENDING) | 414 if (nwrite != ERR_IO_PENDING) |
| 401 return nwrite; | 415 return nwrite; |
| 402 | 416 |
| 403 if (address) | 417 if (address) |
| 404 send_to_address_.reset(new IPEndPoint(*address)); | 418 send_to_address_.reset(new IPEndPoint(*address)); |
| 405 write_callback_ = callback; | 419 write_callback_ = callback; |
| 406 return ERR_IO_PENDING; | 420 return ERR_IO_PENDING; |
| 407 } | 421 } |
| 408 | 422 |
| 409 int UDPSocketWin::Connect(const IPEndPoint& address) { | 423 int UDPSocketWin::Connect(const IPEndPoint& address) { |
| 424 DCHECK_NE(socket_, INVALID_SOCKET); |
| 410 net_log_.BeginEvent(NetLog::TYPE_UDP_CONNECT, | 425 net_log_.BeginEvent(NetLog::TYPE_UDP_CONNECT, |
| 411 CreateNetLogUDPConnectCallback(&address)); | 426 CreateNetLogUDPConnectCallback(&address)); |
| 412 int rv = InternalConnect(address); | 427 int rv = InternalConnect(address); |
| 413 if (rv != OK) | |
| 414 Close(); | |
| 415 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT, rv); | 428 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT, rv); |
| 429 is_connected_ = (rv == OK); |
| 416 return rv; | 430 return rv; |
| 417 } | 431 } |
| 418 | 432 |
| 419 int UDPSocketWin::InternalConnect(const IPEndPoint& address) { | 433 int UDPSocketWin::InternalConnect(const IPEndPoint& address) { |
| 420 DCHECK(!is_connected()); | 434 DCHECK(!is_connected()); |
| 421 DCHECK(!remote_address_.get()); | 435 DCHECK(!remote_address_.get()); |
| 422 int addr_family = address.GetSockAddrFamily(); | |
| 423 int rv = CreateSocket(addr_family); | |
| 424 if (rv < 0) | |
| 425 return rv; | |
| 426 | 436 |
| 437 int rv = 0; |
| 427 if (bind_type_ == DatagramSocket::RANDOM_BIND) { | 438 if (bind_type_ == DatagramSocket::RANDOM_BIND) { |
| 428 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s, | 439 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s, |
| 429 // representing INADDR_ANY or in6addr_any. | 440 // representing INADDR_ANY or in6addr_any. |
| 430 size_t addr_size = | 441 size_t addr_size = (address.GetSockAddrFamily() == AF_INET) ? |
| 431 addr_family == AF_INET ? kIPv4AddressSize : kIPv6AddressSize; | 442 kIPv4AddressSize : kIPv6AddressSize; |
| 432 IPAddressNumber addr_any(addr_size); | 443 IPAddressNumber addr_any(addr_size); |
| 433 rv = RandomBind(addr_any); | 444 rv = RandomBind(addr_any); |
| 434 } | 445 } |
| 435 // else connect() does the DatagramSocket::DEFAULT_BIND | 446 // else connect() does the DatagramSocket::DEFAULT_BIND |
| 436 | 447 |
| 437 if (rv < 0) { | 448 if (rv < 0) { |
| 438 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketRandomBindErrorCode", -rv); | 449 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketRandomBindErrorCode", -rv); |
| 439 Close(); | |
| 440 return rv; | 450 return rv; |
| 441 } | 451 } |
| 442 | 452 |
| 443 SockaddrStorage storage; | 453 SockaddrStorage storage; |
| 444 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) | 454 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) |
| 445 return ERR_ADDRESS_INVALID; | 455 return ERR_ADDRESS_INVALID; |
| 446 | 456 |
| 447 rv = connect(socket_, storage.addr, storage.addr_len); | 457 rv = connect(socket_, storage.addr, storage.addr_len); |
| 448 if (rv < 0) { | 458 if (rv < 0) |
| 449 // Close() may change the last error. Map it beforehand. | 459 return MapSystemError(WSAGetLastError()); |
| 450 int result = MapSystemError(WSAGetLastError()); | |
| 451 Close(); | |
| 452 return result; | |
| 453 } | |
| 454 | 460 |
| 455 remote_address_.reset(new IPEndPoint(address)); | 461 remote_address_.reset(new IPEndPoint(address)); |
| 456 return rv; | 462 return rv; |
| 457 } | 463 } |
| 458 | 464 |
| 459 int UDPSocketWin::Bind(const IPEndPoint& address) { | 465 int UDPSocketWin::Bind(const IPEndPoint& address) { |
| 466 DCHECK_NE(socket_, INVALID_SOCKET); |
| 460 DCHECK(!is_connected()); | 467 DCHECK(!is_connected()); |
| 461 int rv = CreateSocket(address.GetSockAddrFamily()); | 468 |
| 469 int rv = SetMulticastOptions(); |
| 462 if (rv < 0) | 470 if (rv < 0) |
| 463 return rv; | 471 return rv; |
| 464 rv = SetSocketOptions(); | 472 |
| 465 if (rv < 0) { | 473 rv = DoBind(address); |
| 466 Close(); | 474 if (rv < 0) |
| 467 return rv; | 475 return rv; |
| 468 } | 476 |
| 469 rv = DoBind(address); | |
| 470 if (rv < 0) { | |
| 471 Close(); | |
| 472 return rv; | |
| 473 } | |
| 474 local_address_.reset(); | 477 local_address_.reset(); |
| 478 is_connected_ = true; |
| 475 return rv; | 479 return rv; |
| 476 } | 480 } |
| 477 | 481 |
| 478 int UDPSocketWin::CreateSocket(int addr_family) { | |
| 479 addr_family_ = addr_family; | |
| 480 socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, IPPROTO_UDP); | |
| 481 if (socket_ == INVALID_SOCKET) | |
| 482 return MapSystemError(WSAGetLastError()); | |
| 483 core_ = new Core(this); | |
| 484 return OK; | |
| 485 } | |
| 486 | |
| 487 int UDPSocketWin::SetReceiveBufferSize(int32 size) { | 482 int UDPSocketWin::SetReceiveBufferSize(int32 size) { |
| 483 DCHECK_NE(socket_, INVALID_SOCKET); |
| 488 DCHECK(CalledOnValidThread()); | 484 DCHECK(CalledOnValidThread()); |
| 489 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, | 485 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, |
| 490 reinterpret_cast<const char*>(&size), sizeof(size)); | 486 reinterpret_cast<const char*>(&size), sizeof(size)); |
| 491 if (rv != 0) | 487 if (rv != 0) |
| 492 return MapSystemError(WSAGetLastError()); | 488 return MapSystemError(WSAGetLastError()); |
| 493 | 489 |
| 494 // According to documentation, setsockopt may succeed, but we need to check | 490 // According to documentation, setsockopt may succeed, but we need to check |
| 495 // the results via getsockopt to be sure it works on Windows. | 491 // the results via getsockopt to be sure it works on Windows. |
| 496 int32 actual_size = 0; | 492 int32 actual_size = 0; |
| 497 int option_size = sizeof(actual_size); | 493 int option_size = sizeof(actual_size); |
| 498 rv = getsockopt(socket_, SOL_SOCKET, SO_RCVBUF, | 494 rv = getsockopt(socket_, SOL_SOCKET, SO_RCVBUF, |
| 499 reinterpret_cast<char*>(&actual_size), &option_size); | 495 reinterpret_cast<char*>(&actual_size), &option_size); |
| 500 if (rv != 0) | 496 if (rv != 0) |
| 501 return MapSystemError(WSAGetLastError()); | 497 return MapSystemError(WSAGetLastError()); |
| 502 if (actual_size >= size) | 498 if (actual_size >= size) |
| 503 return OK; | 499 return OK; |
| 504 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableReceiveBuffer", | 500 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableReceiveBuffer", |
| 505 actual_size, 1000, 1000000, 50); | 501 actual_size, 1000, 1000000, 50); |
| 506 return ERR_SOCKET_RECEIVE_BUFFER_SIZE_UNCHANGEABLE; | 502 return ERR_SOCKET_RECEIVE_BUFFER_SIZE_UNCHANGEABLE; |
| 507 } | 503 } |
| 508 | 504 |
| 509 int UDPSocketWin::SetSendBufferSize(int32 size) { | 505 int UDPSocketWin::SetSendBufferSize(int32 size) { |
| 506 DCHECK_NE(socket_, INVALID_SOCKET); |
| 510 DCHECK(CalledOnValidThread()); | 507 DCHECK(CalledOnValidThread()); |
| 511 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, | 508 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, |
| 512 reinterpret_cast<const char*>(&size), sizeof(size)); | 509 reinterpret_cast<const char*>(&size), sizeof(size)); |
| 513 if (rv != 0) | 510 if (rv != 0) |
| 514 return MapSystemError(WSAGetLastError()); | 511 return MapSystemError(WSAGetLastError()); |
| 515 // According to documentation, setsockopt may succeed, but we need to check | 512 // According to documentation, setsockopt may succeed, but we need to check |
| 516 // the results via getsockopt to be sure it works on Windows. | 513 // the results via getsockopt to be sure it works on Windows. |
| 517 int32 actual_size = 0; | 514 int32 actual_size = 0; |
| 518 int option_size = sizeof(actual_size); | 515 int option_size = sizeof(actual_size); |
| 519 rv = getsockopt(socket_, SOL_SOCKET, SO_SNDBUF, | 516 rv = getsockopt(socket_, SOL_SOCKET, SO_SNDBUF, |
| 520 reinterpret_cast<char*>(&actual_size), &option_size); | 517 reinterpret_cast<char*>(&actual_size), &option_size); |
| 521 if (rv != 0) | 518 if (rv != 0) |
| 522 return MapSystemError(WSAGetLastError()); | 519 return MapSystemError(WSAGetLastError()); |
| 523 if (actual_size >= size) | 520 if (actual_size >= size) |
| 524 return OK; | 521 return OK; |
| 525 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableSendBuffer", | 522 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableSendBuffer", |
| 526 actual_size, 1000, 1000000, 50); | 523 actual_size, 1000, 1000000, 50); |
| 527 return ERR_SOCKET_SEND_BUFFER_SIZE_UNCHANGEABLE; | 524 return ERR_SOCKET_SEND_BUFFER_SIZE_UNCHANGEABLE; |
| 528 } | 525 } |
| 529 | 526 |
| 530 void UDPSocketWin::AllowAddressReuse() { | 527 int UDPSocketWin::AllowAddressReuse() { |
| 528 DCHECK_NE(socket_, INVALID_SOCKET); |
| 531 DCHECK(CalledOnValidThread()); | 529 DCHECK(CalledOnValidThread()); |
| 532 DCHECK(!is_connected()); | 530 DCHECK(!is_connected()); |
| 533 | 531 |
| 534 socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS; | 532 BOOL true_value = TRUE; |
| 533 int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, |
| 534 reinterpret_cast<const char*>(&true_value), |
| 535 sizeof(true_value)); |
| 536 return rv == 0 ? OK : MapSystemError(WSAGetLastError()); |
| 535 } | 537 } |
| 536 | 538 |
| 537 void UDPSocketWin::AllowBroadcast() { | 539 int UDPSocketWin::SetBroadcast(bool broadcast) { |
| 540 DCHECK_NE(socket_, INVALID_SOCKET); |
| 538 DCHECK(CalledOnValidThread()); | 541 DCHECK(CalledOnValidThread()); |
| 539 DCHECK(!is_connected()); | |
| 540 | 542 |
| 541 socket_options_ |= SOCKET_OPTION_BROADCAST; | 543 BOOL value = broadcast ? TRUE : FALSE; |
| 544 int rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, |
| 545 reinterpret_cast<const char*>(&value), sizeof(value)); |
| 546 return rv == 0 ? OK : MapSystemError(WSAGetLastError()); |
| 542 } | 547 } |
| 543 | 548 |
| 544 void UDPSocketWin::DoReadCallback(int rv) { | 549 void UDPSocketWin::DoReadCallback(int rv) { |
| 545 DCHECK_NE(rv, ERR_IO_PENDING); | 550 DCHECK_NE(rv, ERR_IO_PENDING); |
| 546 DCHECK(!read_callback_.is_null()); | 551 DCHECK(!read_callback_.is_null()); |
| 547 | 552 |
| 548 // since Run may result in Read being called, clear read_callback_ up front. | 553 // since Run may result in Read being called, clear read_callback_ up front. |
| 549 CompletionCallback c = read_callback_; | 554 CompletionCallback c = read_callback_; |
| 550 read_callback_.Reset(); | 555 read_callback_.Reset(); |
| 551 c.Run(rv); | 556 c.Run(rv); |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 711 LogWrite(result, NULL, NULL); | 716 LogWrite(result, NULL, NULL); |
| 712 return result; | 717 return result; |
| 713 } | 718 } |
| 714 } | 719 } |
| 715 | 720 |
| 716 core_->WatchForWrite(); | 721 core_->WatchForWrite(); |
| 717 core_->write_iobuffer_ = buf; | 722 core_->write_iobuffer_ = buf; |
| 718 return ERR_IO_PENDING; | 723 return ERR_IO_PENDING; |
| 719 } | 724 } |
| 720 | 725 |
| 721 int UDPSocketWin::SetSocketOptions() { | 726 int UDPSocketWin::SetMulticastOptions() { |
| 722 BOOL true_value = 1; | |
| 723 if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) { | |
| 724 int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, | |
| 725 reinterpret_cast<const char*>(&true_value), | |
| 726 sizeof(true_value)); | |
| 727 if (rv < 0) | |
| 728 return MapSystemError(WSAGetLastError()); | |
| 729 } | |
| 730 if (socket_options_ & SOCKET_OPTION_BROADCAST) { | |
| 731 int rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, | |
| 732 reinterpret_cast<const char*>(&true_value), | |
| 733 sizeof(true_value)); | |
| 734 if (rv < 0) | |
| 735 return MapSystemError(WSAGetLastError()); | |
| 736 } | |
| 737 if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) { | 727 if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) { |
| 738 DWORD loop = 0; | 728 DWORD loop = 0; |
| 739 int protocol_level = | 729 int protocol_level = |
| 740 addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; | 730 addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; |
| 741 int option = | 731 int option = |
| 742 addr_family_ == AF_INET ? IP_MULTICAST_LOOP: IPV6_MULTICAST_LOOP; | 732 addr_family_ == AF_INET ? IP_MULTICAST_LOOP: IPV6_MULTICAST_LOOP; |
| 743 int rv = setsockopt(socket_, protocol_level, option, | 733 int rv = setsockopt(socket_, protocol_level, option, |
| 744 reinterpret_cast<const char*>(&loop), sizeof(loop)); | 734 reinterpret_cast<const char*>(&loop), sizeof(loop)); |
| 745 if (rv < 0) | 735 if (rv < 0) |
| 746 return MapSystemError(WSAGetLastError()); | 736 return MapSystemError(WSAGetLastError()); |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1020 NULL); | 1010 NULL); |
| 1021 | 1011 |
| 1022 return OK; | 1012 return OK; |
| 1023 } | 1013 } |
| 1024 | 1014 |
| 1025 void UDPSocketWin::DetachFromThread() { | 1015 void UDPSocketWin::DetachFromThread() { |
| 1026 base::NonThreadSafe::DetachFromThread(); | 1016 base::NonThreadSafe::DetachFromThread(); |
| 1027 } | 1017 } |
| 1028 | 1018 |
| 1029 } // namespace net | 1019 } // namespace net |
| OLD | NEW |