diff --git a/core/src/utils/net.cpp b/core/src/utils/net.cpp index 3ce6b5c2..4095e7ea 100644 --- a/core/src/utils/net.cpp +++ b/core/src/utils/net.cpp @@ -86,14 +86,14 @@ namespace net { addr.sin_port = htons(port); } - std::string Address::getIPStr() { + std::string Address::getIPStr() const { char buf[128]; IP_t ip = getIP(); sprintf(buf, "%d.%d.%d.%d", (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, ip & 0xFF); return buf; } - IP_t Address::getIP() { + IP_t Address::getIP() const { return htonl(addr.sin_addr.s_addr); } @@ -101,7 +101,7 @@ namespace net { addr.sin_addr.s_addr = htonl(ip); } - int Address::getPort() { + int Address::getPort() const { return htons(addr.sin_port); } @@ -109,6 +109,11 @@ namespace net { addr.sin_port = htons(port); } + bool Address::isMulticast() const { + IP_t ip = getIP(); + return (ip >> 28) == 0b1110; + } + // === Socket functions === Socket::Socket(SockHandle_t sock, const Address* raddr) { @@ -160,8 +165,8 @@ namespace net { // Set timeout timeval tv; - tv.tv_sec = 0; - tv.tv_usec = timeout * 1000; + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout - tv.tv_sec*1000) * 1000; // Wait for data int err = select(sock+1, &set, NULL, &set, (timeout > 0) ? &tv : NULL); @@ -225,8 +230,8 @@ namespace net { // Define timeout timeval tv; - tv.tv_sec = 0; - tv.tv_usec = timeout * 1000; + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout - tv.tv_sec*1000) * 1000; // Wait for data or error if (timeout != NONBLOCKING) { @@ -382,6 +387,18 @@ namespace net { // Create socket SockHandle_t s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + // If the remote address is multicast, allow multicast connections +#ifdef _WIN32 + const char enable = raddr.isMulticast(); +#else + int enable = raddr.isMulticast(); +#endif + if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0) { + closeSocket(s); + throw std::runtime_error("Could not configure socket"); + return NULL; + } + // Bind socket to local port if (bind(s, (sockaddr*)&laddr.addr, sizeof(sockaddr_in))) { closeSocket(s); diff --git a/core/src/utils/net.h b/core/src/utils/net.h index 2196fc09..a2137441 100644 --- a/core/src/utils/net.h +++ b/core/src/utils/net.h @@ -67,13 +67,13 @@ namespace net { * Get the IP address. * @return IP address in standard string format. */ - std::string getIPStr(); + std::string getIPStr() const; /** * Get the IP address. * @return IP address in host byte order. */ - IP_t getIP(); + IP_t getIP() const; /** * Set the IP address. @@ -85,7 +85,7 @@ namespace net { * Get the TCP/UDP port. * @return TCP/UDP port number. */ - int getPort(); + int getPort() const; /** * Set the TCP/UDP port. @@ -93,6 +93,12 @@ namespace net { */ void setPort(int port); + /** + * Check if the address is multicast. + * @return True if multicast, false if not. + */ + bool isMulticast() const; + struct sockaddr_in addr; }; @@ -246,7 +252,7 @@ namespace net { /** * Create UDP socket. - * @param raddr Remote address. + * @param raddr Remote address. Set to a multicast address to allow multicast. * @param laddr Local address to bind the socket to. * @return Socket instance on success, Throws runtime_error otherwise. */ @@ -254,7 +260,7 @@ namespace net { /** * Create UDP socket. - * @param rhost Remote hostname or IP address. + * @param rhost Remote hostname or IP address. Set to a multicast address to allow multicast. * @param rport Remote port. * @param laddr Local address to bind the socket to. * @return Socket instance on success, Throws runtime_error otherwise. @@ -263,7 +269,7 @@ namespace net { /** * Create UDP socket. - * @param raddr Remote address. + * @param raddr Remote address. Set to a multicast address to allow multicast. * @param lhost Local hostname or IP used to bind the socket (optional, "0.0.0.0" for Any). * @param lpost Local port used to bind the socket to (optional, 0 to allocate automatically). * @return Socket instance on success, Throws runtime_error otherwise. @@ -272,7 +278,7 @@ namespace net { /** * Create UDP socket. - * @param rhost Remote hostname or IP address. + * @param rhost Remote hostname or IP address. Set to a multicast address to allow multicast. * @param rport Remote port. * @param lhost Local hostname or IP used to bind the socket (optional, "0.0.0.0" for Any). * @param lpost Local port used to bind the socket to (optional, 0 to allocate automatically).