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

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 code style 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 sock_addr_family_(0),
44 socket_options_(0), 45 socket_options_(0),
46 multicast_time_to_live_(1),
47 multicast_loopback_mode_(true),
45 bind_type_(bind_type), 48 bind_type_(bind_type),
46 rand_int_cb_(rand_int_cb), 49 rand_int_cb_(rand_int_cb),
47 read_watcher_(this), 50 read_watcher_(this),
48 write_watcher_(this), 51 write_watcher_(this),
49 read_buf_len_(0), 52 read_buf_len_(0),
50 recv_from_address_(NULL), 53 recv_from_address_(NULL),
51 write_buf_len_(0), 54 write_buf_len_(0),
52 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) { 55 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) {
53 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, 56 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE,
54 source.ToEventParametersCallback()); 57 source.ToEventParametersCallback());
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 CreateNetLogUDPDataTranferCallback( 359 CreateNetLogUDPDataTranferCallback(
357 result, bytes, 360 result, bytes,
358 is_address_valid ? &address : NULL)); 361 is_address_valid ? &address : NULL));
359 } 362 }
360 363
361 base::StatsCounter read_bytes("udp.read_bytes"); 364 base::StatsCounter read_bytes("udp.read_bytes");
362 read_bytes.Add(result); 365 read_bytes.Add(result);
363 } 366 }
364 367
365 int UDPSocketLibevent::CreateSocket(const IPEndPoint& address) { 368 int UDPSocketLibevent::CreateSocket(const IPEndPoint& address) {
366 socket_ = socket(address.GetSockAddrFamily(), SOCK_DGRAM, 0); 369 sock_addr_family_ = address.GetSockAddrFamily();
370 socket_ = socket(sock_addr_family_, SOCK_DGRAM, 0);
367 if (socket_ == kInvalidSocket) 371 if (socket_ == kInvalidSocket)
368 return MapSystemError(errno); 372 return MapSystemError(errno);
369 if (SetNonBlocking(socket_)) { 373 if (SetNonBlocking(socket_)) {
370 const int err = MapSystemError(errno); 374 const int err = MapSystemError(errno);
371 Close(); 375 Close();
372 return err; 376 return err;
373 } 377 }
374 return OK; 378 return OK;
375 } 379 }
376 380
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
469 return MapSystemError(errno); 473 return MapSystemError(errno);
470 } 474 }
471 if (socket_options_ & SOCKET_OPTION_BROADCAST) { 475 if (socket_options_ & SOCKET_OPTION_BROADCAST) {
472 int rv; 476 int rv;
473 #if defined(OS_MACOSX) 477 #if defined(OS_MACOSX)
474 // SO_REUSEPORT on OSX permits multiple processes to each receive 478 // SO_REUSEPORT on OSX permits multiple processes to each receive
475 // UDP multicast or broadcast datagrams destined for the bound 479 // UDP multicast or broadcast datagrams destined for the bound
476 // port. 480 // port.
477 rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEPORT, &true_value, 481 rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEPORT, &true_value,
478 sizeof(true_value)); 482 sizeof(true_value));
483 #else
484 rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &true_value,
485 sizeof(true_value));
mmenke 2013/04/16 18:09:49 This needs to be done on OSX, too.
Bei Zhang 2013/04/17 17:53:03 It's done in the other #if branch.
486 #endif // defined(OS_MACOSX)
479 if (rv < 0) 487 if (rv < 0)
480 return MapSystemError(errno); 488 return MapSystemError(errno);
481 #endif // defined(OS_MACOSX) 489 }
482 rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &true_value, 490 if (multicast_time_to_live_ != 1) {
483 sizeof(true_value)); 491 int rv = SetMulticastTimeToLive(multicast_time_to_live_);
484 if (rv < 0) 492 if (rv != OK)
485 return MapSystemError(errno); 493 return rv;
494 }
495 if (!multicast_loopback_mode_) {
496 int rv = SetMulticastLoopbackMode(multicast_loopback_mode_);
497 if (rv != OK)
498 return rv;
486 } 499 }
487 return OK; 500 return OK;
488 } 501 }
489 502
490 int UDPSocketLibevent::DoBind(const IPEndPoint& address) { 503 int UDPSocketLibevent::DoBind(const IPEndPoint& address) {
491 SockaddrStorage storage; 504 SockaddrStorage storage;
492 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) 505 if (!address.ToSockAddr(storage.addr, &storage.addr_len))
493 return ERR_UNEXPECTED; 506 return ERR_UNEXPECTED;
494 int rv = bind(socket_, storage.addr, storage.addr_len); 507 int rv = bind(socket_, storage.addr, storage.addr_len);
495 return rv < 0 ? MapSystemError(errno) : rv; 508 return rv < 0 ? MapSystemError(errno) : rv;
496 } 509 }
497 510
498 int UDPSocketLibevent::RandomBind(const IPEndPoint& address) { 511 int UDPSocketLibevent::RandomBind(const IPEndPoint& address) {
499 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null()); 512 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null());
500 513
501 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s. 514 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s.
502 IPAddressNumber ip(address.address().size()); 515 IPAddressNumber ip(address.address().size());
503 516
504 for (int i = 0; i < kBindRetries; ++i) { 517 for (int i = 0; i < kBindRetries; ++i) {
505 int rv = DoBind(IPEndPoint(ip, rand_int_cb_.Run(kPortStart, kPortEnd))); 518 int rv = DoBind(IPEndPoint(ip, rand_int_cb_.Run(kPortStart, kPortEnd)));
506 if (rv == OK || rv != ERR_ADDRESS_IN_USE) 519 if (rv == OK || rv != ERR_ADDRESS_IN_USE)
507 return rv; 520 return rv;
508 } 521 }
509 return DoBind(IPEndPoint(ip, 0)); 522 return DoBind(IPEndPoint(ip, 0));
510 } 523 }
511 524
525 int UDPSocketLibevent::JoinGroup(
526 const net::IPAddressNumber& group_address) const {
527 DCHECK(CalledOnValidThread());
528 DCHECK(is_connected());
529
530 int rv = -1;
mmenke 2013/04/16 18:09:49 Sending a -1 through MapSystemError on fall throug
Bei Zhang 2013/04/17 17:53:03 Done.
531 switch (group_address.size()) {
532 case kIPv4AddressSize: {
533 if (sock_addr_family_ != AF_INET)
534 return ERR_ADDRESS_INVALID;
535 ip_mreq mreq;
536 memset(&mreq, 0, sizeof(mreq));
537 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
mmenke 2013/04/16 18:09:49 Seems like we should be explicitely using IN_ADDRA
Bei Zhang 2013/04/17 17:53:03 Done.
538 rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP,
539 &mreq, sizeof(mreq));
540 break;
541 }
542 case kIPv6AddressSize: {
543 if (sock_addr_family_ != AF_INET6)
544 return ERR_ADDRESS_INVALID;
545 ipv6_mreq mreq;
546 memset(&mreq, 0, sizeof(mreq));
547 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
548 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_JOIN_GROUP,
549 &mreq, sizeof(mreq));
mmenke 2013/04/16 18:09:49 Seems like we should be explicitely using in6addr_
Bei Zhang 2013/04/17 17:53:03 Done.
550 break;
551 }
552 }
553
554 return MapSystemError(rv);
555 }
556
557 int UDPSocketLibevent::LeaveGroup(
558 const net::IPAddressNumber& group_address) const {
559 DCHECK(CalledOnValidThread());
560 DCHECK(is_connected());
561
562 int rv = -1;
563 switch (group_address.size()) {
564 case kIPv4AddressSize: {
565 if (sock_addr_family_ != AF_INET)
566 return ERR_ADDRESS_INVALID;
567 ip_mreq mreq;
568 memset(&mreq, 0, sizeof(mreq));
569 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
570 rv = setsockopt(socket_, IPPROTO_IP, IP_DROP_MEMBERSHIP,
571 &mreq, sizeof(mreq));
572 break;
573 }
574 case kIPv6AddressSize: {
575 if (sock_addr_family_ != AF_INET6)
576 return ERR_ADDRESS_INVALID;
577 ipv6_mreq mreq;
578 memset(&mreq, 0, sizeof(mreq));
579 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
580 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
581 &mreq, sizeof(mreq));
582 break;
583 }
584 }
585
586 return MapSystemError(rv);
587 }
588
589 int UDPSocketLibevent::SetMulticastTimeToLive(int time_to_live) {
590 DCHECK(CalledOnValidThread());
591 if (time_to_live < 0 || time_to_live > 255)
592 return ERR_INVALID_ARGUMENT;
593 if (is_connected()) {
mmenke 2013/04/16 18:09:49 Do we need these to be dynamically configurable?
Bei Zhang 2013/04/17 17:53:03 I thought about this for a while. I think you are
594 uint8 ttl = time_to_live;
595 int ip_family = sock_addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
596 return MapSystemError(setsockopt(socket_,
597 ip_family,
598 IP_MULTICAST_TTL,
599 &ttl, sizeof(ttl)));
600 } else {
mmenke 2013/04/16 18:09:49 Preferred style in Chrome is not to have an else h
Bei Zhang 2013/04/17 17:53:03 Done.
601 multicast_time_to_live_ = time_to_live;
602 return OK;
603 }
604 }
605
606 int UDPSocketLibevent::SetMulticastLoopbackMode(bool loopback) {
607 DCHECK(CalledOnValidThread());
608 if (is_connected()) {
609 uint8 loop = loopback;
610 int ip_family = sock_addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
611 return MapSystemError(setsockopt(socket_,
612 ip_family,
613 IP_MULTICAST_LOOP,
614 &loop, sizeof(loop)));
615 } else {
616 multicast_loopback_mode_ = loopback;
617 return OK;
618 }
619 }
512 } // namespace net 620 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698