http://www.mediawiki.org/wiki/Special:Code/MediaWiki/100788
Revision: 100788 Author: tstarling Date: 2011-10-26 04:49:14 +0000 (Wed, 26 Oct 2011) Log Message: ----------- * Moved the multicast join function out of the generic Socket class and into UDPSocket where it belongs, renamed it to JoinMulticast. Have it accept an IPAddress instead of char* per convention. * Rewrote JoinMulticast, implemented IPv6 multicast group join support. * Fixed the non-functional char* constructor of IPAddress. * Added a constructor from std::string to IPAddress, for convenience. * Added some IPAddress wrappers for INADDR_ANY and in6addr_any. * Sprinkled in some const modifiers. * Enforced the non-copyable nature of Socket with a private constructor. * Enforced the fact that Socket is a pure base class and should not be instantiated, by making all constructors private or protected. * In udp2log, fixed the ridiculous attempt at polymorphic object construction introduced in r75452, mimicked in r95725. * Moved -lboost_program_options to the end of the object list, the linker now seems to want this. Modified Paths: -------------- trunk/udplog/Makefile trunk/udplog/srclib/IPAddress.cpp trunk/udplog/srclib/IPAddress.h trunk/udplog/srclib/Socket.cpp trunk/udplog/srclib/Socket.h trunk/udplog/srclib/SocketAddress.h trunk/udplog/udp2log/udp2log.cpp Modified: trunk/udplog/Makefile =================================================================== --- trunk/udplog/Makefile 2011-10-26 04:47:48 UTC (rev 100787) +++ trunk/udplog/Makefile 2011-10-26 04:49:14 UTC (rev 100788) @@ -17,7 +17,7 @@ g++ $(CFLAGS) $(HOST_OBJS) -o host log2udp: $(LOG2UDP_OBJS) - g++ $(CFLAGS) -lboost_program_options $(LOG2UDP_OBJS) -o log2udp + g++ $(CFLAGS) $(LOG2UDP_OBJS) -lboost_program_options -o log2udp udprecv: $(UDPRECV_OBJS) g++ $(CFLAGS) -Wall $(UDPRECV_OBJS) -o udprecv @@ -29,7 +29,7 @@ g++ $(CFLAGS) -o packet-loss srcmisc/packet-loss.cpp udp2log/udp2log: $(UDP2LOG_OBJS) - g++ $(CFLAGS) -o udp2log/udp2log -lboost_program_options $(UDP2LOG_OBJS) + g++ $(CFLAGS) -o udp2log/udp2log $(UDP2LOG_OBJS) -lboost_program_options install: install log2udp $(DESTDIR)/usr/bin/log2udp Modified: trunk/udplog/srclib/IPAddress.cpp =================================================================== --- trunk/udplog/srclib/IPAddress.cpp 2011-10-26 04:47:48 UTC (rev 100787) +++ trunk/udplog/srclib/IPAddress.cpp 2011-10-26 04:49:14 UTC (rev 100788) @@ -2,6 +2,9 @@ #include "Exception.h" #include "SocketAddress.h" +const IPAddress IPAddress::any4(INADDR_ANY); +const IPAddress IPAddress::any6(&in6addr_any); + std::string & IPAddress::ToString() { if (!presentation.size()) { @@ -19,8 +22,17 @@ return presentation; } -IPAddress::IPAddress(int type, char *presentation) +void IPAddress::InitFromString(const char *presentation) { + domain = PF_INET; + if (strstr(presentation, ":")) { + type = AF_INET6; + length = sizeof(in6_addr); + } else { + type = AF_INET; + length = sizeof(in_addr); + } + int ret = inet_pton(type, presentation, &data); if (!ret ) { throw std::runtime_error("Invalid IP address"); Modified: trunk/udplog/srclib/IPAddress.h =================================================================== --- trunk/udplog/srclib/IPAddress.h 2011-10-26 04:47:48 UTC (rev 100787) +++ trunk/udplog/srclib/IPAddress.h 2011-10-26 04:49:14 UTC (rev 100788) @@ -5,6 +5,8 @@ #include <netinet/in.h> #include <string> #include <boost/shared_ptr.hpp> +#include <stdexcept> +#include <memory.h> class SocketAddress; @@ -13,13 +15,13 @@ IPAddress() : type(AF_INET), domain(PF_INET), length(sizeof(in_addr)) {} - IPAddress(struct in_addr * src) + IPAddress(const struct in_addr * src) : type(AF_INET), domain(PF_INET), length(sizeof(in_addr)) { data.v4 = *src; } - IPAddress(struct in6_addr * src) + IPAddress(const struct in6_addr * src) : type(AF_INET6), domain(PF_INET6), length(sizeof(in6_addr)) { data.v6 = *src; @@ -31,16 +33,34 @@ data.v4.s_addr = addr; } - IPAddress(int type, char * presentation); + IPAddress(const char * presentation) { + InitFromString(presentation); + } - void* GetBinaryData() { return &data; } - size_t GetBinaryLength() { return length; } - int GetType() { return type; } - int GetDomain() { return domain; } + IPAddress(const std::string & s) { + if (s.find('\0') != std::string::npos) { + throw std::runtime_error("Invalid IP address"); + } + InitFromString(s.c_str()); + } + + const void* GetBinaryData() const { return &data; } + size_t GetBinaryLength() const { return length; } + + void CopyBinaryData(void * dest) const { + memcpy(dest, GetBinaryData(), GetBinaryLength()); + } + + int GetType() const { return type; } + int GetDomain() const { return domain; } std::string & ToString(); boost::shared_ptr<SocketAddress> NewSocketAddress(unsigned short int port); + static const IPAddress any4; + static const IPAddress any6; protected: + void InitFromString(const char * presentation); + enum { BUFSIZE = 200 }; std::string presentation; @@ -49,6 +69,8 @@ struct in_addr v4; } data; int type, domain, length; + + }; #endif Modified: trunk/udplog/srclib/Socket.cpp =================================================================== --- trunk/udplog/srclib/Socket.cpp 2011-10-26 04:47:48 UTC (rev 100787) +++ trunk/udplog/srclib/Socket.cpp 2011-10-26 04:49:14 UTC (rev 100788) @@ -19,3 +19,35 @@ } } +int UDPSocket::JoinMulticast(const IPAddress & addr) { + int level, optname; + void *optval; + socklen_t optlen; + struct ip_mreqn mreq4; + struct ipv6_mreq mreq6; + + if (addr.GetType() == AF_INET) { + addr.CopyBinaryData(&mreq4.imr_multiaddr.s_addr); + IPAddress::any4.CopyBinaryData(&mreq4.imr_address); + mreq4.imr_ifindex = 0; + level = IPPROTO_IP; + optname = IP_ADD_MEMBERSHIP; + optval = &mreq4; + optlen = sizeof(mreq4); + } else { + addr.CopyBinaryData(&mreq6.ipv6mr_multiaddr); + mreq6.ipv6mr_interface = 0; + level = IPPROTO_IPV6; + optname = IPV6_JOIN_GROUP; + optval = &mreq6; + optlen = sizeof(mreq6); + } + + if (setsockopt(fd, level, optname, optval, optlen)) { + RaiseError("UDPSocket::JoinMulticast"); + return errno; + } else { + return 0; + } +} + Modified: trunk/udplog/srclib/Socket.h =================================================================== --- trunk/udplog/srclib/Socket.h 2011-10-26 04:47:48 UTC (rev 100787) +++ trunk/udplog/srclib/Socket.h 2011-10-26 04:49:14 UTC (rev 100788) @@ -14,8 +14,14 @@ // Do not instantiate this directly class Socket { -public: +private: + // Not default constructible Socket(){} + + // Not copyable + Socket(const Socket & s) {} + +protected: Socket(int domain, int type, int protocol) : fd(-1) { @@ -28,6 +34,8 @@ } } +public: + operator bool() { return good; } @@ -62,22 +70,6 @@ } } - int Mcast(const char* multicastAddr) { - IPAddress any(INADDR_ANY); - struct ip_mreq imreq; - - bzero(&imreq, sizeof(struct ip_mreq)); - imreq.imr_multiaddr.s_addr = inet_addr(multicastAddr); - imreq.imr_interface.s_addr = INADDR_ANY; - if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const void *)&imreq, - sizeof(struct ip_mreq))) { - RaiseError("Socket::Mcast"); - return errno; - } else { - return 0; - } - } - boost::shared_ptr<SocketAddress> GetPeerAddress() { if (connect(fd, SocketAddress::GetBuffer(), SocketAddress::GetBufferLength()) < 0) { RaiseError("Socket::GetPeerAddress"); @@ -168,6 +160,11 @@ good = false; } } + + int JoinMulticast(const IPAddress & addr); +private: + int JoinMulticast4(const IPAddress & addr); + int JoinMulticast6(const IPAddress & addr); }; #endif Modified: trunk/udplog/srclib/SocketAddress.h =================================================================== --- trunk/udplog/srclib/SocketAddress.h 2011-10-26 04:47:48 UTC (rev 100787) +++ trunk/udplog/srclib/SocketAddress.h 2011-10-26 04:49:14 UTC (rev 100788) @@ -36,7 +36,7 @@ data.v6.sin6_family = AF_INET6; } - SocketAddress(IPAddress & ip, unsigned short int port) + SocketAddress(const IPAddress & ip, unsigned short int port) { switch (ip.GetType()) { case AF_INET: Modified: trunk/udplog/udp2log/udp2log.cpp =================================================================== --- trunk/udplog/udp2log/udp2log.cpp 2011-10-26 04:47:48 UTC (rev 100787) +++ trunk/udplog/udp2log/udp2log.cpp 2011-10-26 04:49:14 UTC (rev 100788) @@ -182,17 +182,22 @@ signal(SIGPIPE, SIG_IGN); // Open the receiving socket - IPAddress any(INADDR_ANY); - SocketAddress saddr(any, (unsigned short int)port); - Socket socket; - socket = *(new UDPSocket()); + SocketAddress saddr(IPAddress::any4, (unsigned short int)port); + UDPSocket socket; if (!socket) { cerr << "Unable to open socket\n"; return 1; } socket.Bind(saddr); - if(strcmp("0", multicastAddr.c_str())){ //if multicast - socket.Mcast(multicastAddr.c_str()); + + // Join a multicast group if requested + if (multicastAddr != "0") { + try { + socket.JoinMulticast(multicastAddr); + } catch (runtime_error & e) { + cerr << "Error joining multicast group: " << e.what() << endl; + return 1; + } } // Process received packets boost::shared_ptr<SocketAddress> address; _______________________________________________ MediaWiki-CVS mailing list MediaWiki-CVS@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs