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

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 tests 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 24 matching lines...) Expand all
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 socket_options_(0),
45 multicast_time_to_live_(1),
46 multicast_loopback_mode_(true),
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 sock_addr_family_ = address.GetSockAddrFamily();
369 socket_ = socket(sock_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); 483 rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &true_value,
mmenke 2013/04/12 21:07:41 Why get rid of this?
Bei Zhang 2013/04/15 22:30:26 I simply moved this out side of the #if to elimina
484 sizeof(true_value));
mmenke 2013/04/12 21:07:41 I don't think we need to do this twice on platform
Bei Zhang 2013/04/15 22:30:26 Done.
481 #endif // defined(OS_MACOSX) 485 #endif // defined(OS_MACOSX)
482 rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &true_value, 486 rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &true_value,
483 sizeof(true_value)); 487 sizeof(true_value));
484 if (rv < 0) 488 if (rv < 0)
485 return MapSystemError(errno); 489 return MapSystemError(errno);
486 } 490 }
491 if (multicast_time_to_live_ != 1) {
492 int rv = SetMulticastTimeToLive(multicast_time_to_live_);
493 if (rv != OK)
494 return rv;
495 }
496 if (!multicast_loopback_mode_) {
497 int rv = SetMulticastLoopbackMode(multicast_loopback_mode_);
498 if (rv != OK)
499 return rv;
500 }
487 return OK; 501 return OK;
488 } 502 }
489 503
490 int UDPSocketLibevent::DoBind(const IPEndPoint& address) { 504 int UDPSocketLibevent::DoBind(const IPEndPoint& address) {
491 SockaddrStorage storage; 505 SockaddrStorage storage;
492 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) 506 if (!address.ToSockAddr(storage.addr, &storage.addr_len))
493 return ERR_UNEXPECTED; 507 return ERR_UNEXPECTED;
494 int rv = bind(socket_, storage.addr, storage.addr_len); 508 int rv = bind(socket_, storage.addr, storage.addr_len);
495 return rv < 0 ? MapSystemError(errno) : rv; 509 return rv < 0 ? MapSystemError(errno) : rv;
496 } 510 }
497 511
498 int UDPSocketLibevent::RandomBind(const IPEndPoint& address) { 512 int UDPSocketLibevent::RandomBind(const IPEndPoint& address) {
499 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null()); 513 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null());
500 514
501 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s. 515 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s.
502 IPAddressNumber ip(address.address().size()); 516 IPAddressNumber ip(address.address().size());
503 517
504 for (int i = 0; i < kBindRetries; ++i) { 518 for (int i = 0; i < kBindRetries; ++i) {
505 int rv = DoBind(IPEndPoint(ip, rand_int_cb_.Run(kPortStart, kPortEnd))); 519 int rv = DoBind(IPEndPoint(ip, rand_int_cb_.Run(kPortStart, kPortEnd)));
506 if (rv == OK || rv != ERR_ADDRESS_IN_USE) 520 if (rv == OK || rv != ERR_ADDRESS_IN_USE)
507 return rv; 521 return rv;
508 } 522 }
509 return DoBind(IPEndPoint(ip, 0)); 523 return DoBind(IPEndPoint(ip, 0));
510 } 524 }
511 525
526 int UDPSocketLibevent::JoinGroup(
527 const net::IPAddressNumber& group_address) const {
528 DCHECK(CalledOnValidThread());
529 DCHECK(is_connected());
530
531 int rv = -1;
532 switch(group_address.size()) {
mmenke 2013/04/12 21:07:41 Space after switch.
Bei Zhang 2013/04/15 22:30:26 Done.
533 case kIPv4AddressSize: {
534 if (sock_addr_family_ != AF_INET) {
535 return ERR_ADDRESS_INVALID;
536 }
mmenke 2013/04/12 21:07:41 Braces are generally discouraged in single line if
Bei Zhang 2013/04/15 22:30:26 Done.
537 ip_mreq mreq;
538 memset(&mreq, 0, sizeof(mreq));
539 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
540 rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP,
541 &mreq, sizeof(mreq));
542 break;
543 }
544 case kIPv6AddressSize: {
545 if (sock_addr_family_ != AF_INET6) {
546 return ERR_ADDRESS_INVALID;
547 }
548 ipv6_mreq mreq;
549 memset(&mreq, 0, sizeof(mreq));
550 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
551 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_JOIN_GROUP,
552 &mreq, sizeof(mreq));
553 break;
554 }
555 }
556
557 return MapSystemError(rv);
558 }
559
560 int UDPSocketLibevent::LeaveGroup(
561 const net::IPAddressNumber& group_address) const {
562 DCHECK(CalledOnValidThread());
563 DCHECK(is_connected());
564
565 int rv = -1;
566 switch(group_address.size()) {
567 case kIPv4AddressSize: {
568 if (sock_addr_family_ != AF_INET) {
569 return ERR_ADDRESS_INVALID;
570 }
571 ip_mreq mreq;
572 memset(&mreq, 0, sizeof(mreq));
573 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
574 rv = setsockopt(socket_, IPPROTO_IP, IP_DROP_MEMBERSHIP,
575 &mreq, sizeof(mreq));
mmenke 2013/04/12 21:07:41 Fix indent.
Bei Zhang 2013/04/15 22:30:26 Done.
576 break;
577 }
578 case kIPv6AddressSize: {
579 if (sock_addr_family_ != AF_INET6) {
580 return ERR_ADDRESS_INVALID;
581 }
582 ipv6_mreq mreq;
583 memset(&mreq, 0, sizeof(mreq));
584 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
585 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
586 &mreq, sizeof(mreq));
mmenke 2013/04/12 21:07:41 Fix indent.
Bei Zhang 2013/04/15 22:30:26 Done.
587 break;
588 }
589 }
590
591 return MapSystemError(rv);
592 }
593
594 int UDPSocketLibevent::SetMulticastTimeToLive(int timeToLive) {
mmenke 2013/04/12 21:07:41 Rename, per comment in header.
Bei Zhang 2013/04/15 22:30:26 Done.
595 DCHECK(CalledOnValidThread());
596 if (timeToLive < 0 || timeToLive > 255) {
597 return ERR_INVALID_ARGUMENT;
598 }
599 if(is_connected()) {
mmenke 2013/04/12 21:07:41 Space after if.
Bei Zhang 2013/04/15 22:30:26 Done.
600 uint8 ttl = timeToLive;
601 int ip_family = sock_addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
602 return MapSystemError(setsockopt(socket_,
603 ip_family,
604 IP_MULTICAST_TTL,
605 &ttl, sizeof(ttl)));
606 } else {
607 multicast_time_to_live_ = timeToLive;
608 return OK;
609 }
610 }
611
612 int UDPSocketLibevent::SetMulticastLoopbackMode(bool loopback) {
613 DCHECK(CalledOnValidThread());
614 if(is_connected()) {
mmenke 2013/04/12 21:07:41 Space after if.
Bei Zhang 2013/04/15 22:30:26 Done.
615 uint8 loop = loopback;
616 int ip_family = sock_addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
617 return MapSystemError(setsockopt(socket_,
618 ip_family,
619 IP_MULTICAST_LOOP,
620 &loop, sizeof(loop)));
621 } else {
622 multicast_loopback_mode_ = loopback;
623 return OK;
624 }
625 }
512 } // namespace net 626 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698