summaryrefslogtreecommitdiff
path: root/cpp/src
diff options
context:
space:
mode:
authorDwayne Boone <dwayne@zeroc.com>2007-05-28 13:47:20 +0000
committerDwayne Boone <dwayne@zeroc.com>2007-05-28 13:47:20 +0000
commit1cf6107ab5f200b2a224acd711d572341ec1a22f (patch)
tree5545fdc8d560982fbf8b6bc3ae87a089bc1889cc /cpp/src
parentRemove Ice.UseEventLog property from head. Remove code in Glacier2 that (diff)
downloadice-1cf6107ab5f200b2a224acd711d572341ec1a22f.tar.bz2
ice-1cf6107ab5f200b2a224acd711d572341ec1a22f.tar.xz
ice-1cf6107ab5f200b2a224acd711d572341ec1a22f.zip
Added udp multicast support
Diffstat (limited to 'cpp/src')
-rw-r--r--cpp/src/Ice/Network.cpp72
-rw-r--r--cpp/src/Ice/Network.h7
-rw-r--r--cpp/src/Ice/UdpEndpointI.cpp359
-rw-r--r--cpp/src/Ice/UdpEndpointI.h5
-rw-r--r--cpp/src/Ice/UdpTransceiver.cpp54
-rw-r--r--cpp/src/Ice/UdpTransceiver.h5
6 files changed, 335 insertions, 167 deletions
diff --git a/cpp/src/Ice/Network.cpp b/cpp/src/Ice/Network.cpp
index 8e02559e8c6..a1710cd34ae 100644
--- a/cpp/src/Ice/Network.cpp
+++ b/cpp/src/Ice/Network.cpp
@@ -15,6 +15,7 @@
#if defined(_WIN32)
# include <winsock2.h>
+# include <ws2tcpip.h>
#elif defined(__linux) || defined(__APPLE__) || defined(__FreeBSD__)
# include <ifaddrs.h>
#else
@@ -195,6 +196,19 @@ IceInternal::recvTruncated()
#endif
}
+bool
+IceInternal::isMulticast(struct sockaddr_in& addr)
+{
+ string ip = inetAddrToString(addr.sin_addr);
+ int i;
+ istringstream p(ip.substr(0, ip.find('.')));
+ if(!(p >> i) || !p.eof() || i < 224 || i > 239)
+ {
+ return false;
+ }
+ return true;
+}
+
SOCKET
IceInternal::createSocket(bool udp)
{
@@ -468,10 +482,48 @@ IceInternal::getRecvBufferSize(SOCKET fd)
}
void
-IceInternal::doBind(SOCKET fd, struct sockaddr_in& addr)
+IceInternal::setMcastGroup(SOCKET fd, const struct in_addr& group, const struct in_addr& interface)
{
-#ifndef _WIN32
- int flag = 1;
+ struct ip_mreq mreq;
+ mreq.imr_multiaddr = group;
+ mreq.imr_interface = interface;
+ if(setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mreq, int(sizeof(mreq))) == SOCKET_ERROR)
+ {
+ closeSocketNoThrow(fd);
+ SocketException ex(__FILE__, __LINE__);
+ ex.error = getSocketErrno();
+ throw ex;
+ }
+}
+
+void
+IceInternal::setMcastInterface(SOCKET fd, const struct in_addr& interface)
+{
+ if(setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, (char*)&interface, int(sizeof(interface))) == SOCKET_ERROR)
+ {
+ closeSocketNoThrow(fd);
+ SocketException ex(__FILE__, __LINE__);
+ ex.error = getSocketErrno();
+ throw ex;
+ }
+}
+
+void
+IceInternal::setMcastTtl(SOCKET fd, int ttl)
+{
+ if(setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, int(sizeof(int))) == SOCKET_ERROR)
+ {
+ closeSocketNoThrow(fd);
+ SocketException ex(__FILE__, __LINE__);
+ ex.error = getSocketErrno();
+ throw ex;
+ }
+}
+
+void
+IceInternal::setReuseAddress(SOCKET fd, bool reuse)
+{
+ int flag = reuse ? 1 : 0;
if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&flag, int(sizeof(int))) == SOCKET_ERROR)
{
closeSocketNoThrow(fd);
@@ -479,6 +531,13 @@ IceInternal::doBind(SOCKET fd, struct sockaddr_in& addr)
ex.error = getSocketErrno();
throw ex;
}
+}
+
+void
+IceInternal::doBind(SOCKET fd, struct sockaddr_in& addr)
+{
+#ifndef _WIN32
+ setReuseAddress(fd, true);
#endif
if(bind(fd, reinterpret_cast<struct sockaddr*>(&addr), int(sizeof(addr))) == SOCKET_ERROR)
@@ -1205,6 +1264,13 @@ IceInternal::fdToString(SOCKET fd)
struct sockaddr_in remoteAddr;
bool peerConnected = fdToRemoteAddress(fd, remoteAddr);
+ return addressesToString(localAddr, remoteAddr, peerConnected);
+};
+
+std::string
+IceInternal::addressesToString(const struct sockaddr_in& localAddr, const struct sockaddr_in& remoteAddr,
+ bool peerConnected)
+{
ostringstream s;
s << "local address = " << addrToString(localAddr);
if(peerConnected)
diff --git a/cpp/src/Ice/Network.h b/cpp/src/Ice/Network.h
index 2d074c17dc7..eb2c9235ca4 100644
--- a/cpp/src/Ice/Network.h
+++ b/cpp/src/Ice/Network.h
@@ -76,6 +76,8 @@ ICE_API bool connectionLost();
ICE_API bool notConnected();
ICE_API bool recvTruncated();
+ICE_API bool isMulticast(struct sockaddr_in&);
+
ICE_API SOCKET createSocket(bool);
ICE_API void closeSocket(SOCKET);
ICE_API void closeSocketNoThrow(SOCKET);
@@ -89,6 +91,10 @@ ICE_API void setSendBufferSize(SOCKET, int);
ICE_API int getSendBufferSize(SOCKET);
ICE_API void setRecvBufferSize(SOCKET, int);
ICE_API int getRecvBufferSize(SOCKET);
+ICE_API void setMcastGroup(SOCKET, const struct in_addr&, const struct in_addr&);
+ICE_API void setMcastInterface(SOCKET, const struct in_addr&);
+ICE_API void setMcastTtl(SOCKET, int);
+ICE_API void setReuseAddress(SOCKET, bool);
ICE_API void doBind(SOCKET, struct sockaddr_in&);
ICE_API void doListen(SOCKET, int);
@@ -105,6 +111,7 @@ ICE_API std::string errorToStringDNS(int);
ICE_API std::string lastErrorToString();
ICE_API std::string fdToString(SOCKET);
+ICE_API std::string addressesToString(const struct sockaddr_in&, const struct sockaddr_in&, bool);
ICE_API void fdToLocalAddress(SOCKET, struct sockaddr_in&);
ICE_API bool fdToRemoteAddress(SOCKET, struct sockaddr_in&);
ICE_API std::string addrToString(const struct sockaddr_in&);
diff --git a/cpp/src/Ice/UdpEndpointI.cpp b/cpp/src/Ice/UdpEndpointI.cpp
index e6bfffa3818..dac2d3717ee 100644
--- a/cpp/src/Ice/UdpEndpointI.cpp
+++ b/cpp/src/Ice/UdpEndpointI.cpp
@@ -20,11 +20,13 @@ using namespace std;
using namespace Ice;
using namespace IceInternal;
-IceInternal::UdpEndpointI::UdpEndpointI(const InstancePtr& instance, const string& ho, Int po, bool conn,
- const string& conId, bool co, bool pub) :
+IceInternal::UdpEndpointI::UdpEndpointI(const InstancePtr& instance, const string& ho, Int po, const string& mif,
+ Int mttl, bool conn, const string& conId, bool co, bool pub) :
_instance(instance),
_host(ho),
_port(po),
+ _mcastInterface(mif),
+ _mcastTtl(mttl),
_protocolMajor(protocolMajor),
_protocolMinor(protocolMinor),
_encodingMajor(encodingMajor),
@@ -39,6 +41,7 @@ IceInternal::UdpEndpointI::UdpEndpointI(const InstancePtr& instance, const strin
IceInternal::UdpEndpointI::UdpEndpointI(const InstancePtr& instance, const string& str) :
_instance(instance),
_port(0),
+ _mcastTtl(-1),
_protocolMajor(protocolMajor),
_protocolMinor(protocolMinor),
_encodingMajor(encodingMajor),
@@ -67,7 +70,7 @@ IceInternal::UdpEndpointI::UdpEndpointI(const InstancePtr& instance, const strin
}
string option = str.substr(beg, end - beg);
- if(option.length() != 2 || option[0] != '-')
+ if(option[0] != '-')
{
EndpointParseException ex(__FILE__, __LINE__);
ex.str = "udp " + str;
@@ -87,182 +90,185 @@ IceInternal::UdpEndpointI::UdpEndpointI(const InstancePtr& instance, const strin
argument = str.substr(beg, end - beg);
}
- switch(option[1])
+ if(option == "-v")
{
- case 'v':
+ if(argument.empty())
{
- if(argument.empty())
- {
- EndpointParseException ex(__FILE__, __LINE__);
- ex.str = "udp " + str;
- throw ex;
- }
-
- string::size_type pos = argument.find('.');
- if(pos == string::npos)
- {
- EndpointParseException ex(__FILE__, __LINE__);
- ex.str = "udp " + str;
- throw ex;
- }
- string majorStr = argument.substr(0, pos);
- string minorStr = argument.substr(pos + 1, string::npos);
-
- istringstream majStr(majorStr);
- Int majVersion;
- if(!(majStr >> majVersion) || !majStr.eof())
- {
- EndpointParseException ex(__FILE__, __LINE__);
- ex.str = "udp " + str;
- throw ex;
- }
-
- istringstream minStr(minorStr);
- Int minVersion;
- if(!(minStr >> minVersion) || !minStr.eof())
- {
- EndpointParseException ex(__FILE__, __LINE__);
- ex.str = "udp " + str;
- throw ex;
- }
-
- if(majVersion < 1 || majVersion > 255 || minVersion < 0 || minVersion > 255)
- {
- EndpointParseException ex(__FILE__, __LINE__);
- ex.str = "udp " + str;
- throw ex;
- }
-
- if(majVersion != protocolMajor)
- {
- UnsupportedProtocolException ex(__FILE__, __LINE__);
- ex.badMajor = majVersion;
- ex.badMinor = minVersion;
- ex.major = static_cast<unsigned char>(protocolMajor);
- ex.minor = static_cast<unsigned char>(protocolMinor);
- throw ex;
- }
-
- const_cast<Byte&>(_protocolMajor) = majVersion;
- const_cast<Byte&>(_protocolMinor) = minVersion;
-
- break;
+ EndpointParseException ex(__FILE__, __LINE__);
+ ex.str = "udp " + str;
+ throw ex;
+ }
+
+ string::size_type pos = argument.find('.');
+ if(pos == string::npos)
+ {
+ EndpointParseException ex(__FILE__, __LINE__);
+ ex.str = "udp " + str;
+ throw ex;
+ }
+ string majorStr = argument.substr(0, pos);
+ string minorStr = argument.substr(pos + 1, string::npos);
+
+ istringstream majStr(majorStr);
+ Int majVersion;
+ if(!(majStr >> majVersion) || !majStr.eof())
+ {
+ EndpointParseException ex(__FILE__, __LINE__);
+ ex.str = "udp " + str;
+ throw ex;
+ }
+
+ istringstream minStr(minorStr);
+ Int minVersion;
+ if(!(minStr >> minVersion) || !minStr.eof())
+ {
+ EndpointParseException ex(__FILE__, __LINE__);
+ ex.str = "udp " + str;
+ throw ex;
+ }
+
+ if(majVersion < 1 || majVersion > 255 || minVersion < 0 || minVersion > 255)
+ {
+ EndpointParseException ex(__FILE__, __LINE__);
+ ex.str = "udp " + str;
+ throw ex;
+ }
+
+ if(majVersion != protocolMajor)
+ {
+ UnsupportedProtocolException ex(__FILE__, __LINE__);
+ ex.badMajor = majVersion;
+ ex.badMinor = minVersion;
+ ex.major = static_cast<unsigned char>(protocolMajor);
+ ex.minor = static_cast<unsigned char>(protocolMinor);
+ throw ex;
}
- case 'e':
+ const_cast<Byte&>(_protocolMajor) = majVersion;
+ const_cast<Byte&>(_protocolMinor) = minVersion;
+ }
+ else if(option == "-e")
+ {
+ if(argument.empty())
{
- if(argument.empty())
- {
- EndpointParseException ex(__FILE__, __LINE__);
- ex.str = "udp " + str;
- throw ex;
- }
- string::size_type pos = argument.find('.');
- string majorStr = argument.substr(0, pos);
- string minorStr = argument.substr(pos + 1, string::npos);
-
- istringstream majStr(majorStr);
- Int majVersion;
- if(!(majStr >> majVersion) || !majStr.eof())
- {
- EndpointParseException ex(__FILE__, __LINE__);
- ex.str = "udp " + str;
- throw ex;
- }
-
- istringstream minStr(minorStr);
- Int minVersion;
- if(!(minStr >> minVersion) || !minStr.eof())
- {
- EndpointParseException ex(__FILE__, __LINE__);
- ex.str = "udp " + str;
- throw ex;
- }
-
- if(majVersion < 1 || majVersion > 255 || minVersion < 0 || minVersion > 255)
- {
- EndpointParseException ex(__FILE__, __LINE__);
- ex.str = "udp " + str;
- throw ex;
- }
-
- if(majVersion != static_cast<unsigned char>(encodingMajor))
- {
- UnsupportedEncodingException ex(__FILE__, __LINE__);
- ex.badMajor = majVersion;
- ex.badMinor = minVersion;
- ex.major = static_cast<unsigned char>(encodingMajor);
- ex.minor = static_cast<unsigned char>(encodingMinor);
- throw ex;
- }
-
- const_cast<Byte&>(_encodingMajor) = majVersion;
- const_cast<Byte&>(_encodingMinor) = minVersion;
-
- break;
+ EndpointParseException ex(__FILE__, __LINE__);
+ ex.str = "udp " + str;
+ throw ex;
}
+ string::size_type pos = argument.find('.');
+ string majorStr = argument.substr(0, pos);
+ string minorStr = argument.substr(pos + 1, string::npos);
- case 'h':
+ istringstream majStr(majorStr);
+ Int majVersion;
+ if(!(majStr >> majVersion) || !majStr.eof())
{
- if(argument.empty())
- {
- EndpointParseException ex(__FILE__, __LINE__);
- ex.str = "udp " + str;
- throw ex;
- }
- const_cast<string&>(_host) = argument;
- break;
+ EndpointParseException ex(__FILE__, __LINE__);
+ ex.str = "udp " + str;
+ throw ex;
}
- case 'p':
+ istringstream minStr(minorStr);
+ Int minVersion;
+ if(!(minStr >> minVersion) || !minStr.eof())
{
- istringstream p(argument);
- if(!(p >> const_cast<Int&>(_port)) || !p.eof() || _port < 0 || _port > 65535)
- {
- EndpointParseException ex(__FILE__, __LINE__);
- ex.str = "udp " + str;
- throw ex;
- }
- break;
+ EndpointParseException ex(__FILE__, __LINE__);
+ ex.str = "udp " + str;
+ throw ex;
}
- case 'c':
+ if(majVersion < 1 || majVersion > 255 || minVersion < 0 || minVersion > 255)
{
- if(!argument.empty())
- {
- EndpointParseException ex(__FILE__, __LINE__);
- ex.str = "udp " + str;
- throw ex;
- }
- const_cast<bool&>(_connect) = true;
- break;
+ EndpointParseException ex(__FILE__, __LINE__);
+ ex.str = "udp " + str;
+ throw ex;
}
- case 'z':
+ if(majVersion != static_cast<unsigned char>(encodingMajor))
{
- if(!argument.empty())
- {
- EndpointParseException ex(__FILE__, __LINE__);
- ex.str = "udp " + str;
- throw ex;
- }
- const_cast<bool&>(_compress) = true;
- break;
+ UnsupportedEncodingException ex(__FILE__, __LINE__);
+ ex.badMajor = majVersion;
+ ex.badMinor = minVersion;
+ ex.major = static_cast<unsigned char>(encodingMajor);
+ ex.minor = static_cast<unsigned char>(encodingMinor);
+ throw ex;
}
- default:
+ const_cast<Byte&>(_encodingMajor) = majVersion;
+ const_cast<Byte&>(_encodingMinor) = minVersion;
+ }
+ else if(option == "-h")
+ {
+ if(argument.empty())
+ {
+ EndpointParseException ex(__FILE__, __LINE__);
+ ex.str = "udp " + str;
+ throw ex;
+ }
+ const_cast<string&>(_host) = argument;
+ }
+ else if(option == "-p")
+ {
+ istringstream p(argument);
+ if(!(p >> const_cast<Int&>(_port)) || !p.eof() || _port < 0 || _port > 65535)
{
EndpointParseException ex(__FILE__, __LINE__);
ex.str = "udp " + str;
throw ex;
}
}
+ else if(option == "-c")
+ {
+ if(!argument.empty())
+ {
+ EndpointParseException ex(__FILE__, __LINE__);
+ ex.str = "udp " + str;
+ throw ex;
+ }
+ const_cast<bool&>(_connect) = true;
+ }
+ else if(option == "-z")
+ {
+ if(!argument.empty())
+ {
+ EndpointParseException ex(__FILE__, __LINE__);
+ ex.str = "udp " + str;
+ throw ex;
+ }
+ const_cast<bool&>(_compress) = true;
+ }
+ else if(option == "--interface")
+ {
+ if(argument.empty())
+ {
+ EndpointParseException ex(__FILE__, __LINE__);
+ ex.str = "udp " + str;
+ throw ex;
+ }
+ const_cast<string&>(_mcastInterface) = argument;
+ }
+ else if(option == "--ttl")
+ {
+ istringstream p(argument);
+ if(!(p >> const_cast<Int&>(_mcastTtl)) || !p.eof())
+ {
+ EndpointParseException ex(__FILE__, __LINE__);
+ ex.str = "udp " + str;
+ throw ex;
+ }
+ }
+ else
+ {
+ EndpointParseException ex(__FILE__, __LINE__);
+ ex.str = "udp " + str;
+ }
}
}
IceInternal::UdpEndpointI::UdpEndpointI(BasicStream* s) :
_instance(s->instance()),
_port(0),
+ _mcastTtl(-1),
_protocolMajor(protocolMajor),
_protocolMinor(protocolMinor),
_encodingMajor(encodingMajor),
@@ -349,6 +355,16 @@ IceInternal::UdpEndpointI::toString() const
s << " -h " << _host << " -p " << _port;
+ if(_mcastInterface.length() > 0)
+ {
+ s << " --interface " << _mcastInterface;
+ }
+
+ if(_mcastTtl != -1)
+ {
+ s << " --ttl " << _mcastTtl;
+ }
+
if(_connect)
{
s << " -c";
@@ -389,7 +405,8 @@ IceInternal::UdpEndpointI::connectionId(const string& connectionId) const
}
else
{
- return new UdpEndpointI(_instance, _host, _port, _connect, connectionId, _compress, _publish);
+ return new UdpEndpointI(_instance, _host, _port, _mcastInterface, _mcastTtl, _connect, connectionId,
+ _compress, _publish);
}
}
@@ -408,7 +425,8 @@ IceInternal::UdpEndpointI::compress(bool compress) const
}
else
{
- return new UdpEndpointI(_instance, _host, _port, _connect, _connectionId, compress, _publish);
+ return new UdpEndpointI(_instance, _host, _port, _mcastInterface, _mcastTtl, _connect, _connectionId,
+ compress, _publish);
}
}
@@ -439,12 +457,12 @@ IceInternal::UdpEndpointI::clientTransceivers() const
{
for(unsigned int i = 0; i < hosts.size(); ++i)
{
- transceivers.push_back(new UdpTransceiver(_instance, hosts[i], _port));
+ transceivers.push_back(new UdpTransceiver(_instance, hosts[i], _port, _mcastInterface, _mcastTtl));
}
}
else
{
- transceivers.push_back(new UdpTransceiver(_instance, _host, _port));
+ transceivers.push_back(new UdpTransceiver(_instance, _host, _port, _mcastInterface, _mcastTtl));
}
return transceivers;
}
@@ -452,8 +470,9 @@ IceInternal::UdpEndpointI::clientTransceivers() const
TransceiverPtr
IceInternal::UdpEndpointI::serverTransceiver(EndpointIPtr& endp) const
{
- UdpTransceiver* p = new UdpTransceiver(_instance, _host, _port, _connect);
- endp = new UdpEndpointI(_instance, _host, p->effectivePort(), _connect, _connectionId, _compress, _publish);
+ UdpTransceiver* p = new UdpTransceiver(_instance, _host, _port, _mcastInterface, _connect);
+ endp = new UdpEndpointI(_instance, _host, p->effectivePort(), _mcastInterface, _mcastTtl, _connect, _connectionId,
+ _compress, _publish);
return p;
}
@@ -500,8 +519,8 @@ IceInternal::UdpEndpointI::expand(bool server) const
vector<string> hosts = getLocalHosts();
for(unsigned int i = 0; i < hosts.size(); ++i)
{
- endps.push_back(new UdpEndpointI(_instance, hosts[i], _port, _connect, _connectionId, _compress,
- hosts.size() == 1 || hosts[i] != "127.0.0.1"));
+ endps.push_back(new UdpEndpointI(_instance, hosts[i], _port, _mcastInterface, _mcastTtl, _connect,
+ _connectionId, _compress, hosts.size() == 1 || hosts[i] != "127.0.0.1"));
}
}
else
@@ -588,6 +607,16 @@ IceInternal::UdpEndpointI::operator==(const EndpointI& r) const
return false;
}
+ if(_mcastTtl != p->_mcastTtl)
+ {
+ return false;
+ }
+
+ if(_mcastInterface != p->_mcastInterface)
+ {
+ return false;
+ }
+
if(_host != p->_host)
{
//
@@ -703,6 +732,24 @@ IceInternal::UdpEndpointI::operator<(const EndpointI& r) const
return false;
}
+ if(_mcastTtl < p->_mcastTtl)
+ {
+ return true;
+ }
+ else if(p->_mcastTtl < _mcastTtl)
+ {
+ return false;
+ }
+
+ if(_mcastInterface < p->_mcastInterface)
+ {
+ return true;
+ }
+ else if(p->_mcastInterface < _mcastInterface)
+ {
+ return false;
+ }
+
if(_host != p->_host)
{
//
diff --git a/cpp/src/Ice/UdpEndpointI.h b/cpp/src/Ice/UdpEndpointI.h
index 7e5b5a87175..dccb0a78947 100644
--- a/cpp/src/Ice/UdpEndpointI.h
+++ b/cpp/src/Ice/UdpEndpointI.h
@@ -22,7 +22,8 @@ class UdpEndpointI : public EndpointI
{
public:
- UdpEndpointI(const InstancePtr&, const std::string&, Ice::Int, bool, const std::string&, bool, bool);
+ UdpEndpointI(const InstancePtr&, const std::string&, Ice::Int, const std::string&, Ice::Int, bool,
+ const std::string&, bool, bool);
UdpEndpointI(const InstancePtr&, const std::string&);
UdpEndpointI(BasicStream*);
@@ -68,6 +69,8 @@ private:
const InstancePtr _instance;
const std::string _host;
const Ice::Int _port;
+ const std::string _mcastInterface;
+ const Ice::Int _mcastTtl;
const Ice::Byte _protocolMajor;
const Ice::Byte _protocolMinor;
const Ice::Byte _encodingMajor;
diff --git a/cpp/src/Ice/UdpTransceiver.cpp b/cpp/src/Ice/UdpTransceiver.cpp
index 4853d98aaa9..67e2b33bc78 100644
--- a/cpp/src/Ice/UdpTransceiver.cpp
+++ b/cpp/src/Ice/UdpTransceiver.cpp
@@ -339,7 +339,16 @@ IceInternal::UdpTransceiver::type() const
string
IceInternal::UdpTransceiver::toString() const
{
- return fdToString(_fd);
+ if(_mcastServer && _fd != INVALID_SOCKET)
+ {
+ struct sockaddr_in remoteAddr;
+ bool peerConnected = fdToRemoteAddress(_fd, remoteAddr);
+ return addressesToString(_addr, remoteAddr, peerConnected);
+ }
+ else
+ {
+ return fdToString(_fd);
+ }
}
void
@@ -375,7 +384,8 @@ IceInternal::UdpTransceiver::effectivePort() const
return ntohs(_addr.sin_port);
}
-IceInternal::UdpTransceiver::UdpTransceiver(const InstancePtr& instance, const string& host, int port) :
+IceInternal::UdpTransceiver::UdpTransceiver(const InstancePtr& instance, const string& host, int port,
+ const string& mcastInterface, int mcastTtl) :
_traceLevels(instance->traceLevels()),
_logger(instance->initializationData().logger),
_stats(instance->initializationData().stats),
@@ -392,6 +402,19 @@ IceInternal::UdpTransceiver::UdpTransceiver(const InstancePtr& instance, const s
getAddress(host, port, _addr);
doConnect(_fd, _addr, -1);
_connect = false; // We're connected now
+ if(isMulticast(_addr))
+ {
+ if(mcastInterface.length() > 0)
+ {
+ struct sockaddr_in addr;
+ getAddress(mcastInterface, port, addr);
+ setMcastInterface(_fd, addr.sin_addr);
+ }
+ if(mcastTtl != -1)
+ {
+ setMcastTtl(_fd, mcastTtl);
+ }
+ }
if(_traceLevels->network >= 1)
{
@@ -411,7 +434,8 @@ IceInternal::UdpTransceiver::UdpTransceiver(const InstancePtr& instance, const s
#endif
}
-IceInternal::UdpTransceiver::UdpTransceiver(const InstancePtr& instance, const string& host, int port, bool connect) :
+IceInternal::UdpTransceiver::UdpTransceiver(const InstancePtr& instance, const string& host, int port,
+ const string& mcastInterface, bool connect) :
_traceLevels(instance->traceLevels()),
_logger(instance->initializationData().logger),
_stats(instance->initializationData().stats),
@@ -431,8 +455,28 @@ IceInternal::UdpTransceiver::UdpTransceiver(const InstancePtr& instance, const s
Trace out(_logger, _traceLevels->networkCat);
out << "attempting to bind to udp socket " << addrToString(_addr);
}
- doBind(_fd, _addr);
-
+ if(isMulticast(_addr))
+ {
+ struct sockaddr_in addr;
+ getAddress("0.0.0.0", port, addr);
+ setReuseAddress(_fd, true);
+ doBind(_fd, addr);
+ if(mcastInterface.length() > 0)
+ {
+ getAddress(mcastInterface, port, addr);
+ }
+ else
+ {
+ addr.sin_addr.s_addr = INADDR_ANY;
+ }
+ setMcastGroup(_fd, _addr.sin_addr, addr.sin_addr);
+ _mcastServer = true;
+ }
+ else
+ {
+ doBind(_fd, _addr);
+ }
+
if(_traceLevels->network >= 1)
{
Trace out(_logger, _traceLevels->networkCat);
diff --git a/cpp/src/Ice/UdpTransceiver.h b/cpp/src/Ice/UdpTransceiver.h
index c39bd3f0a19..85d82e36fdd 100644
--- a/cpp/src/Ice/UdpTransceiver.h
+++ b/cpp/src/Ice/UdpTransceiver.h
@@ -48,8 +48,8 @@ public:
private:
- UdpTransceiver(const InstancePtr&, const std::string&, int);
- UdpTransceiver(const InstancePtr&, const std::string&, int, bool);
+ UdpTransceiver(const InstancePtr&, const std::string&, int, const std::string&, int);
+ UdpTransceiver(const InstancePtr&, const std::string&, int, const std::string&, bool);
virtual ~UdpTransceiver();
void setBufSize(const InstancePtr&);
@@ -63,6 +63,7 @@ private:
SOCKET _fd;
struct sockaddr_in _addr;
+ bool _mcastServer;
#ifdef _WIN32
fd_set _rFdSet;
fd_set _wFdSet;