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

Side by Side Diff: net/udp/udp_socket_win.cc

Issue 721273002: Remove timing limitation to set Broadcast, ReceiveBuffer, and SendBuffer options from UDPSocket. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years 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
« no previous file with comments | « net/udp/udp_socket_win.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « net/udp/udp_socket_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698