bool SetHops(int sock, const address &addr, int ttl) { if (addr.optlevel() == IPPROTO_IPV6) { if (setsockopt(sock, addr.optlevel(), IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)) != 0) { return false; } } else { TTLType _ttl = ttl; if (setsockopt(sock, addr.optlevel(), IP_MULTICAST_TTL, &_ttl, sizeof(_ttl)) != 0) { return false; } } return true; }
int _McastListenNewAPI(int sock, const address &grpaddr) { _loc_group_req grp; memset(&grp, 0, sizeof(grp)); grp.gr_interface = mcastInterface; set_address(grp.gr_group, grpaddr); return setsockopt(sock, grpaddr.optlevel(), MCAST_JOIN_GROUP, &grp, sizeof(grp)); }
static int SSMJoinLeave(int sock, int type, const address &grpaddr, const address &srcaddr) { _loc_group_source_req req; memset(&req, 0, sizeof(req)); req.gsr_interface = mcastInterface; set_address(req.gsr_group, grpaddr); set_address(req.gsr_source, srcaddr); return setsockopt(sock, srcaddr.optlevel(), type, &req, sizeof(req)); }
int SetupSocket(const address &addr, bool shouldbind, bool ssm) { int af_family = addr.family(); int level = addr.optlevel(); int sock = socket(af_family, SOCK_DGRAM, 0); if (sock < 0) { perror("Failed to create multicast socket"); return -1; } int on = 1; if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) != 0) { perror("setsockopt"); return -1; } if (shouldbind) { if (bind(sock, addr.saddr(), addr.addrlen()) != 0) { perror("Failed to bind multicast socket"); return -1; } } #ifdef SO_TIMESTAMP if (setsockopt(sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)) != 0) { perror("setsockopt(SO_TIMESTAMP)"); return -1; } #endif int type = level == IPPROTO_IPV6 ? #ifdef IPV6_RECVHOPLIMIT IPV6_RECVHOPLIMIT #else IPV6_HOPLIMIT #endif : #ifdef IP_RECVTTL IP_RECVTTL; #else IP_TTL; #endif if (setsockopt(sock, level, type, &on, sizeof(on)) != 0) { perror("receiving hop limit/ttl setsockopt()"); return -1; } if (!SetHops(sock, addr, defaultTTL)) { perror("SetHops"); return -1; } if (!ssm && addr.is_multicast()) { if (MulticastListen(sock, addr) != 0) { perror("Failed to join multicast group"); return -1; } } return sock; }