local multicast implemented

This commit is contained in:
Matej Sekoranja
2014-09-01 14:10:36 +02:00
parent c1115437e3
commit e6ca9ea7f2
4 changed files with 90 additions and 25 deletions

View File

@@ -4,6 +4,11 @@
* in file LICENSE that is included with this distribution.
*/
#ifdef _WIN32
// needed for ip_mreq
#include <Ws2tcpip.h>
#endif
#include <pv/blockingUDP.h>
#include <pv/pvaConstants.h>
#include <pv/inetAddressUtil.h>
@@ -408,5 +413,58 @@ inline int sendto(int s, const char *buf, size_t len, int flags, const struct so
((BlockingUDPTransport*)param)->processRead();
}
void BlockingUDPTransport::join(const osiSockAddr & mcastAddr, const osiSockAddr & nifAddr)
{
struct ip_mreq imreq;
memset(&imreq, 0, sizeof(struct ip_mreq));
imreq.imr_multiaddr.s_addr = mcastAddr.ia.sin_addr.s_addr;
imreq.imr_interface.s_addr = nifAddr.ia.sin_addr.s_addr;
// join multicast group on default interface
int status = ::setsockopt(_channel, IPPROTO_IP, IP_ADD_MEMBERSHIP,
(char*)&imreq, sizeof(struct ip_mreq));
if (status)
{
char errStr[64];
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
throw std::runtime_error(
string("Failed to join to the multicast group '") +
inetAddressToString(mcastAddr) + "' on network interface '" +
inetAddressToString(nifAddr, false) + "': " + errStr);
}
}
void BlockingUDPTransport::setMutlicastNIF(const osiSockAddr & nifAddr, bool loopback)
{
// set the multicast outgoing interface
int status = ::setsockopt(_channel, IPPROTO_IP, IP_MULTICAST_IF,
(char*)&nifAddr.ia.sin_addr, sizeof(struct in_addr));
if (status)
{
char errStr[64];
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
throw std::runtime_error(
string("Failed to set multicast network inteface '") +
inetAddressToString(nifAddr, false) + "': " + errStr);
}
// send multicast traffic to myself too
unsigned char mcast_loop = (loopback ? 1 : 0);
status = ::setsockopt(_channel, IPPROTO_IP, IP_MULTICAST_LOOP,
(char*)&mcast_loop, sizeof(unsigned char));
if (status)
{
char errStr[64];
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
throw std::runtime_error(
string("Failed to enable multicast loopback on network inteface '") +
inetAddressToString(nifAddr, false) + "': " + errStr);
}
}
}
}