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

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

Issue 12684008: Multicast socket API (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Changing DCHECKs to returning error code. Created 7 years, 8 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 | Annotate | Revision Log
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_libevent.h" 5 #include "net/udp/udp_socket_libevent.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #include <netdb.h> 9 #include <netdb.h>
10 #include <sys/socket.h> 10 #include <sys/socket.h>
(...skipping 23 matching lines...) Expand all
34 } // namespace net 34 } // namespace net
35 35
36 namespace net { 36 namespace net {
37 37
38 UDPSocketLibevent::UDPSocketLibevent( 38 UDPSocketLibevent::UDPSocketLibevent(
39 DatagramSocket::BindType bind_type, 39 DatagramSocket::BindType bind_type,
40 const RandIntCallback& rand_int_cb, 40 const RandIntCallback& rand_int_cb,
41 net::NetLog* net_log, 41 net::NetLog* net_log,
42 const net::NetLog::Source& source) 42 const net::NetLog::Source& source)
43 : socket_(kInvalidSocket), 43 : socket_(kInvalidSocket),
44 socket_options_(0), 44 addr_family_(0),
45 socket_options_(SOCKET_OPTION_MULTICAST_LOOP),
46 multicast_time_to_live_(1),
45 bind_type_(bind_type), 47 bind_type_(bind_type),
46 rand_int_cb_(rand_int_cb), 48 rand_int_cb_(rand_int_cb),
47 read_watcher_(this), 49 read_watcher_(this),
48 write_watcher_(this), 50 write_watcher_(this),
49 read_buf_len_(0), 51 read_buf_len_(0),
50 recv_from_address_(NULL), 52 recv_from_address_(NULL),
51 write_buf_len_(0), 53 write_buf_len_(0),
52 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) { 54 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) {
53 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, 55 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE,
54 source.ToEventParametersCallback()); 56 source.ToEventParametersCallback());
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 CreateNetLogUDPDataTranferCallback( 358 CreateNetLogUDPDataTranferCallback(
357 result, bytes, 359 result, bytes,
358 is_address_valid ? &address : NULL)); 360 is_address_valid ? &address : NULL));
359 } 361 }
360 362
361 base::StatsCounter read_bytes("udp.read_bytes"); 363 base::StatsCounter read_bytes("udp.read_bytes");
362 read_bytes.Add(result); 364 read_bytes.Add(result);
363 } 365 }
364 366
365 int UDPSocketLibevent::CreateSocket(const IPEndPoint& address) { 367 int UDPSocketLibevent::CreateSocket(const IPEndPoint& address) {
366 socket_ = socket(address.GetSockAddrFamily(), SOCK_DGRAM, 0); 368 addr_family_ = address.GetSockAddrFamily();
369 socket_ = socket(addr_family_, SOCK_DGRAM, 0);
367 if (socket_ == kInvalidSocket) 370 if (socket_ == kInvalidSocket)
368 return MapSystemError(errno); 371 return MapSystemError(errno);
369 if (SetNonBlocking(socket_)) { 372 if (SetNonBlocking(socket_)) {
370 const int err = MapSystemError(errno); 373 const int err = MapSystemError(errno);
371 Close(); 374 Close();
372 return err; 375 return err;
373 } 376 }
374 return OK; 377 return OK;
375 } 378 }
376 379
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
469 return MapSystemError(errno); 472 return MapSystemError(errno);
470 } 473 }
471 if (socket_options_ & SOCKET_OPTION_BROADCAST) { 474 if (socket_options_ & SOCKET_OPTION_BROADCAST) {
472 int rv; 475 int rv;
473 #if defined(OS_MACOSX) 476 #if defined(OS_MACOSX)
474 // SO_REUSEPORT on OSX permits multiple processes to each receive 477 // SO_REUSEPORT on OSX permits multiple processes to each receive
475 // UDP multicast or broadcast datagrams destined for the bound 478 // UDP multicast or broadcast datagrams destined for the bound
476 // port. 479 // port.
477 rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEPORT, &true_value, 480 rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEPORT, &true_value,
478 sizeof(true_value)); 481 sizeof(true_value));
479 if (rv < 0) 482 #else
480 return MapSystemError(errno);
481 #endif // defined(OS_MACOSX)
482 rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &true_value, 483 rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &true_value,
483 sizeof(true_value)); 484 sizeof(true_value));
485 #endif // defined(OS_MACOSX)
484 if (rv < 0) 486 if (rv < 0)
485 return MapSystemError(errno); 487 return MapSystemError(errno);
486 } 488 }
489
490 if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) {
491 int rv;
492 if (addr_family_ == AF_INET) {
493 u_char loop = 0;
494 rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_LOOP,
495 &loop, sizeof(loop));
496 } else {
497 u_int loop = 0;
498 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
499 &loop, sizeof(loop));
500 }
501 if (rv < 0)
502 return MapSystemError(errno);
503 }
504 if (multicast_time_to_live_ != IP_DEFAULT_MULTICAST_TTL) {
505 int rv;
506 if (addr_family_ == AF_INET) {
507 u_char ttl = multicast_time_to_live_;
508 rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_TTL,
509 &ttl, sizeof(ttl));
510 } else {
511 // Signed interger. -1 to use route default.
512 int ttl = multicast_time_to_live_;
513 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
514 &ttl, sizeof(ttl));
515 }
516 if (rv < 0)
517 return MapSystemError(errno);
518 }
487 return OK; 519 return OK;
488 } 520 }
489 521
490 int UDPSocketLibevent::DoBind(const IPEndPoint& address) { 522 int UDPSocketLibevent::DoBind(const IPEndPoint& address) {
491 SockaddrStorage storage; 523 SockaddrStorage storage;
492 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) 524 if (!address.ToSockAddr(storage.addr, &storage.addr_len))
493 return ERR_UNEXPECTED; 525 return ERR_UNEXPECTED;
494 int rv = bind(socket_, storage.addr, storage.addr_len); 526 int rv = bind(socket_, storage.addr, storage.addr_len);
495 return rv < 0 ? MapSystemError(errno) : rv; 527 return rv < 0 ? MapSystemError(errno) : rv;
496 } 528 }
497 529
498 int UDPSocketLibevent::RandomBind(const IPEndPoint& address) { 530 int UDPSocketLibevent::RandomBind(const IPEndPoint& address) {
499 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null()); 531 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null());
500 532
501 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s. 533 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s.
502 IPAddressNumber ip(address.address().size()); 534 IPAddressNumber ip(address.address().size());
503 535
504 for (int i = 0; i < kBindRetries; ++i) { 536 for (int i = 0; i < kBindRetries; ++i) {
505 int rv = DoBind(IPEndPoint(ip, rand_int_cb_.Run(kPortStart, kPortEnd))); 537 int rv = DoBind(IPEndPoint(ip, rand_int_cb_.Run(kPortStart, kPortEnd)));
506 if (rv == OK || rv != ERR_ADDRESS_IN_USE) 538 if (rv == OK || rv != ERR_ADDRESS_IN_USE)
507 return rv; 539 return rv;
508 } 540 }
509 return DoBind(IPEndPoint(ip, 0)); 541 return DoBind(IPEndPoint(ip, 0));
510 } 542 }
511 543
544 int UDPSocketLibevent::JoinGroup(const IPAddressNumber& group_address) const {
545 DCHECK(CalledOnValidThread());
546 if(!is_connected())
wtc 2013/04/23 22:15:26 Add a space between "if" and the opening parenthes
Bei Zhang 2013/04/24 16:50:50 Done.
547 return ERR_SOCKET_NOT_CONNECTED;
548
549 switch (group_address.size()) {
550 case kIPv4AddressSize: {
551 if (addr_family_ != AF_INET)
552 return ERR_ADDRESS_INVALID;
553 ip_mreq mreq;
554 mreq.imr_interface.s_addr = INADDR_ANY;
555 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
556 int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP,
557 &mreq, sizeof(mreq));
558 if (rv < 0)
559 return MapSystemError(errno);
560 return OK;
561 }
562 case kIPv6AddressSize: {
563 if (addr_family_ != AF_INET6)
564 return ERR_ADDRESS_INVALID;
565 ipv6_mreq mreq;
566 mreq.ipv6mr_interface = 0; // 0 indicates default multicast interface.
567 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
568 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_JOIN_GROUP,
569 &mreq, sizeof(mreq));
570 if (rv < 0)
571 return MapSystemError(errno);
572 return OK;
573 }
574 default:
575 NOTREACHED() << "Invalid address family";
576 return ERR_ADDRESS_INVALID;
577 }
578 }
579
580 int UDPSocketLibevent::LeaveGroup(const IPAddressNumber& group_address) const {
581 DCHECK(CalledOnValidThread());
582
583 if(!is_connected())
584 return ERR_SOCKET_NOT_CONNECTED;
585
586 switch (group_address.size()) {
587 case kIPv4AddressSize: {
588 if (addr_family_ != AF_INET)
589 return ERR_ADDRESS_INVALID;
590 ip_mreq mreq;
591 mreq.imr_interface.s_addr = INADDR_ANY;
592 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
593 int rv = setsockopt(socket_, IPPROTO_IP, IP_DROP_MEMBERSHIP,
594 &mreq, sizeof(mreq));
595 if (rv < 0)
596 return MapSystemError(errno);
597 return OK;
598 }
599 case kIPv6AddressSize: {
600 if (addr_family_ != AF_INET6)
601 return ERR_ADDRESS_INVALID;
602 ipv6_mreq mreq;
603 mreq.ipv6mr_interface = 0; // 0 indicates default multicast interface.
604 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
605 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
606 &mreq, sizeof(mreq));
607 if (rv < 0)
608 return MapSystemError(errno);
609 return OK;
610 }
611 default:
612 NOTREACHED() << "Invalid address family";
613 return ERR_ADDRESS_INVALID;
614 }
615 }
616
617 int UDPSocketLibevent::SetMulticastTimeToLive(int time_to_live) {
618 DCHECK(CalledOnValidThread());
619 if(is_connected())
620 return ERR_UNEXPECTED;
wtc 2013/04/23 22:15:26 We should add a new error code ERR_SOCKET_IS_CONNE
Bei Zhang 2013/04/24 16:50:50 Created a bug at http://crbug.com/235066 . On 201
621
622 if (time_to_live < 0 || time_to_live > 255)
623 return ERR_INVALID_ARGUMENT;
624 multicast_time_to_live_ = time_to_live;
625 return OK;
626 }
627
628 int UDPSocketLibevent::SetMulticastLoopbackMode(bool loopback) {
629 DCHECK(CalledOnValidThread());
630 if(is_connected())
631 return ERR_UNEXPECTED;
632
633 if (loopback)
634 socket_options_ |= SOCKET_OPTION_MULTICAST_LOOP;
635 else
636 socket_options_ &= ~SOCKET_OPTION_MULTICAST_LOOP;
637 return OK;
638 }
512 } // namespace net 639 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698