Introduce Multicast Socket API

Allow Chrome Apps developer to receive multicast socket packets by exposing join/leave group ability to UDP socket.

Introducing:
1. chrome.socket.joinGroup / chrome.socket.leaveGroup / chrome.socket.getJoinedGroups to manipulate multicast group membership.
2. Socket permission 'udp-multicast-membership'.
3. chrome.socket.setMulticastTimeToLive / chrome.socket.setMulticastLoopbackMode to control the multicast packet sending for UDP sender.

To expose the ability of manipulating multicast group membership and controlling multicast packet sending, new methods are added into network stack (net::UDPSocket class):
1. JoinGroup/LeaveGroup
2. SetMulticastTimeToLive/SetMulticastLoopbackMode

To demo the ability, a demo app is created:
https://github.com/GoogleChrome/chrome-app-samples/pull/92

TEST=Open the demo app at /chrome-app-samples/multicast in two machines of the same network. Open them and chat, they can talk to each other.

NOTRY=true
BUG=140681

Review URL: https://chromiumcodereview.appspot.com/12684008

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@197192 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/net/udp/udp_socket_libevent.h b/net/udp/udp_socket_libevent.h
index ce8a0f2..ceec17e4 100644
--- a/net/udp/udp_socket_libevent.h
+++ b/net/udp/udp_socket_libevent.h
@@ -113,12 +113,51 @@
   // called before Bind().
   void AllowBroadcast();
 
+  // Join the multicast group.
+  // |group_address| is the group address to join, could be either
+  // an IPv4 or IPv6 address.
+  // Return a network error code.
+  int JoinGroup(const IPAddressNumber& group_address) const;
+
+  // Leave the multicast group.
+  // |group_address| is the group address to leave, could be either
+  // an IPv4 or IPv6 address. If the socket hasn't joined the group,
+  // it will be ignored.
+  // It's optional to leave the multicast group before destroying
+  // the socket. It will be done by the OS.
+  // Return a network error code.
+  int LeaveGroup(const IPAddressNumber& group_address) const;
+
+  // Set the time-to-live option for UDP packets sent to the multicast
+  // group address. The default value of this option is 1.
+  // Cannot be negative or more than 255.
+  // Should be called before Bind().
+  // Return a network error code.
+  int SetMulticastTimeToLive(int time_to_live);
+
+  // Set the loopback flag for UDP socket. If this flag is true, the host
+  // will receive packets sent to the joined group from itself.
+  // The default value of this option is true.
+  // Should be called before Bind().
+  // Return a network error code.
+  //
+  // Note: the behavior of |SetMulticastLoopbackMode| is slightly
+  // different between Windows and Unix-like systems. The inconsistency only
+  // happens when there are more than one applications on the same host
+  // joined to the same multicast group while having different settings on
+  // multicast loopback mode. On Windows, the applications with loopback off
+  // will not RECEIVE the loopback packets; while on Unix-like systems, the
+  // applications with loopback off will not SEND the loopback packets to
+  // other applications on the same host. See MSDN: http://goo.gl/6vqbj
+  int SetMulticastLoopbackMode(bool loopback);
+
  private:
   static const int kInvalidSocket = -1;
 
   enum SocketOptions {
-    SOCKET_OPTION_REUSE_ADDRESS = 1 << 0,
-    SOCKET_OPTION_BROADCAST     = 1 << 1
+    SOCKET_OPTION_REUSE_ADDRESS  = 1 << 0,
+    SOCKET_OPTION_BROADCAST      = 1 << 1,
+    SOCKET_OPTION_MULTICAST_LOOP = 1 << 2
   };
 
   class ReadWatcher : public MessageLoopForIO::Watcher {
@@ -188,11 +227,16 @@
   int RandomBind(const IPEndPoint& address);
 
   int socket_;
+  int addr_family_;
 
   // Bitwise-or'd combination of SocketOptions. Specifies the set of
   // options that should be applied to |socket_| before Bind().
   int socket_options_;
 
+  // Multicast socket options cached for SetSocketOption.
+  // Cannot be used after Bind().
+  int multicast_time_to_live_;
+
   // How to do source port binding, used only when UDPSocket is part of
   // UDPClientSocket, since UDPServerSocket provides Bind.
   DatagramSocket::BindType bind_type_;