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

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: Fix windows build 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 uint8 loop = 0;
wtc 2013/04/17 22:06:50 BUG: it seems that this variable needs to be a u_i
Bei Zhang 2013/04/19 19:40:14 Done. Now we use different branches for IPv4 and I
492 int ip_family =
wtc 2013/04/17 22:06:50 This variable should be named 'level' or 'protocol
Bei Zhang 2013/04/19 19:40:14 Done.
493 addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
494 int option =
495 addr_family_ == AF_INET ? IP_MULTICAST_LOOP: IPV6_MULTICAST_LOOP;
496 int rv = setsockopt(socket_, ip_family, option, &loop, sizeof(loop));
497 if (rv < 0)
498 return MapSystemError(errno);
499 }
500 if (multicast_time_to_live_ != IP_DEFAULT_MULTICAST_TTL) {
501 uint8 ttl = multicast_time_to_live_;
502 int ip_family =
503 addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
504 int option =
505 addr_family_ == AF_INET ? IP_MULTICAST_TTL: IP_MULTICAST_TTL;
wtc 2013/04/17 22:06:50 BUG?: I think we need to use IPV6_MULTICAST_HOPS f
Bei Zhang 2013/04/19 19:40:14 Done.
506 int rv = setsockopt(socket_, ip_family, option, &ttl, sizeof(ttl));
507 if (rv < 0)
508 return MapSystemError(errno);
509 }
487 return OK; 510 return OK;
488 } 511 }
489 512
490 int UDPSocketLibevent::DoBind(const IPEndPoint& address) { 513 int UDPSocketLibevent::DoBind(const IPEndPoint& address) {
491 SockaddrStorage storage; 514 SockaddrStorage storage;
492 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) 515 if (!address.ToSockAddr(storage.addr, &storage.addr_len))
493 return ERR_UNEXPECTED; 516 return ERR_UNEXPECTED;
494 int rv = bind(socket_, storage.addr, storage.addr_len); 517 int rv = bind(socket_, storage.addr, storage.addr_len);
495 return rv < 0 ? MapSystemError(errno) : rv; 518 return rv < 0 ? MapSystemError(errno) : rv;
496 } 519 }
497 520
498 int UDPSocketLibevent::RandomBind(const IPEndPoint& address) { 521 int UDPSocketLibevent::RandomBind(const IPEndPoint& address) {
499 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null()); 522 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null());
500 523
501 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s. 524 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s.
502 IPAddressNumber ip(address.address().size()); 525 IPAddressNumber ip(address.address().size());
503 526
504 for (int i = 0; i < kBindRetries; ++i) { 527 for (int i = 0; i < kBindRetries; ++i) {
505 int rv = DoBind(IPEndPoint(ip, rand_int_cb_.Run(kPortStart, kPortEnd))); 528 int rv = DoBind(IPEndPoint(ip, rand_int_cb_.Run(kPortStart, kPortEnd)));
506 if (rv == OK || rv != ERR_ADDRESS_IN_USE) 529 if (rv == OK || rv != ERR_ADDRESS_IN_USE)
507 return rv; 530 return rv;
508 } 531 }
509 return DoBind(IPEndPoint(ip, 0)); 532 return DoBind(IPEndPoint(ip, 0));
510 } 533 }
511 534
535 int UDPSocketLibevent::JoinGroup(const IPAddressNumber& group_address) const {
536 DCHECK(CalledOnValidThread());
537 DCHECK(is_connected());
538
539 switch (group_address.size()) {
540 case kIPv4AddressSize: {
541 if (addr_family_ != AF_INET)
542 return ERR_ADDRESS_INVALID;
543 ip_mreq mreq;
544 mreq.imr_interface.s_addr = INADDR_ANY;
545 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
546 int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP,
547 &mreq, sizeof(mreq));
548 if (rv < 0)
549 return MapSystemError(errno);
550 return OK;
551 }
552 case kIPv6AddressSize: {
553 if (addr_family_ != AF_INET6)
554 return ERR_ADDRESS_INVALID;
555 ipv6_mreq mreq;
556 mreq.ipv6mr_interface = 0; // 0 indicates default multicast interface.
557 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
558 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_JOIN_GROUP,
559 &mreq, sizeof(mreq));
560 if (rv < 0)
561 return MapSystemError(errno);
562 return OK;
563 }
564 default:
565 NOTREACHED() << "Invalid address family";
566 return ERR_ADDRESS_INVALID;
567 }
568 }
569
570 int UDPSocketLibevent::LeaveGroup(const IPAddressNumber& group_address) const {
571 DCHECK(CalledOnValidThread());
572 DCHECK(is_connected());
573
574 switch (group_address.size()) {
575 case kIPv4AddressSize: {
576 if (addr_family_ != AF_INET)
577 return ERR_ADDRESS_INVALID;
578 ip_mreq mreq;
579 mreq.imr_interface.s_addr = INADDR_ANY;
580 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
581 int rv = setsockopt(socket_, IPPROTO_IP, IP_DROP_MEMBERSHIP,
582 &mreq, sizeof(mreq));
583 if (rv < 0)
584 return MapSystemError(errno);
585 return OK;
586 }
587 case kIPv6AddressSize: {
588 if (addr_family_ != AF_INET6)
589 return ERR_ADDRESS_INVALID;
590 ipv6_mreq mreq;
591 mreq.ipv6mr_interface = 0; // 0 indicates default multicast interface.
592 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
593 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
594 &mreq, sizeof(mreq));
595 if (rv < 0)
596 return MapSystemError(errno);
597 return OK;
598 }
599 default:
600 NOTREACHED() << "Invalid address family";
601 return ERR_ADDRESS_INVALID;
602 }
603 }
604
605 int UDPSocketLibevent::SetMulticastTimeToLive(int time_to_live) {
606 DCHECK(CalledOnValidThread());
607 DCHECK(!is_connected());
608 if (time_to_live < 0 || time_to_live > 255)
609 return ERR_INVALID_ARGUMENT;
610 multicast_time_to_live_ = time_to_live;
611 return OK;
612 }
613
614 int UDPSocketLibevent::SetMulticastLoopbackMode(bool loopback) {
615 DCHECK(CalledOnValidThread());
616 DCHECK(!is_connected());
617 if (loopback)
618 socket_options_ |= SOCKET_OPTION_MULTICAST_LOOP;
619 else
620 socket_options_ &= ~SOCKET_OPTION_MULTICAST_LOOP;
621 return OK;
622 }
512 } // namespace net 623 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698