fix networking library to allow multicast

This commit is contained in:
AlexandreRouma 2024-01-25 20:27:04 +01:00
parent 97c1a132a5
commit 3aa167701e
2 changed files with 37 additions and 14 deletions

View File

@ -86,14 +86,14 @@ namespace net {
addr.sin_port = htons(port); addr.sin_port = htons(port);
} }
std::string Address::getIPStr() { std::string Address::getIPStr() const {
char buf[128]; char buf[128];
IP_t ip = getIP(); IP_t ip = getIP();
sprintf(buf, "%d.%d.%d.%d", (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, ip & 0xFF); sprintf(buf, "%d.%d.%d.%d", (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, ip & 0xFF);
return buf; return buf;
} }
IP_t Address::getIP() { IP_t Address::getIP() const {
return htonl(addr.sin_addr.s_addr); return htonl(addr.sin_addr.s_addr);
} }
@ -101,7 +101,7 @@ namespace net {
addr.sin_addr.s_addr = htonl(ip); addr.sin_addr.s_addr = htonl(ip);
} }
int Address::getPort() { int Address::getPort() const {
return htons(addr.sin_port); return htons(addr.sin_port);
} }
@ -109,6 +109,11 @@ namespace net {
addr.sin_port = htons(port); addr.sin_port = htons(port);
} }
bool Address::isMulticast() const {
IP_t ip = getIP();
return (ip >> 28) == 0b1110;
}
// === Socket functions === // === Socket functions ===
Socket::Socket(SockHandle_t sock, const Address* raddr) { Socket::Socket(SockHandle_t sock, const Address* raddr) {
@ -160,8 +165,8 @@ namespace net {
// Set timeout // Set timeout
timeval tv; timeval tv;
tv.tv_sec = 0; tv.tv_sec = timeout / 1000;
tv.tv_usec = timeout * 1000; tv.tv_usec = (timeout - tv.tv_sec*1000) * 1000;
// Wait for data // Wait for data
int err = select(sock+1, &set, NULL, &set, (timeout > 0) ? &tv : NULL); int err = select(sock+1, &set, NULL, &set, (timeout > 0) ? &tv : NULL);
@ -225,8 +230,8 @@ namespace net {
// Define timeout // Define timeout
timeval tv; timeval tv;
tv.tv_sec = 0; tv.tv_sec = timeout / 1000;
tv.tv_usec = timeout * 1000; tv.tv_usec = (timeout - tv.tv_sec*1000) * 1000;
// Wait for data or error // Wait for data or error
if (timeout != NONBLOCKING) { if (timeout != NONBLOCKING) {
@ -382,6 +387,18 @@ namespace net {
// Create socket // Create socket
SockHandle_t s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 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 // Bind socket to local port
if (bind(s, (sockaddr*)&laddr.addr, sizeof(sockaddr_in))) { if (bind(s, (sockaddr*)&laddr.addr, sizeof(sockaddr_in))) {
closeSocket(s); closeSocket(s);

View File

@ -67,13 +67,13 @@ namespace net {
* Get the IP address. * Get the IP address.
* @return IP address in standard string format. * @return IP address in standard string format.
*/ */
std::string getIPStr(); std::string getIPStr() const;
/** /**
* Get the IP address. * Get the IP address.
* @return IP address in host byte order. * @return IP address in host byte order.
*/ */
IP_t getIP(); IP_t getIP() const;
/** /**
* Set the IP address. * Set the IP address.
@ -85,7 +85,7 @@ namespace net {
* Get the TCP/UDP port. * Get the TCP/UDP port.
* @return TCP/UDP port number. * @return TCP/UDP port number.
*/ */
int getPort(); int getPort() const;
/** /**
* Set the TCP/UDP port. * Set the TCP/UDP port.
@ -93,6 +93,12 @@ namespace net {
*/ */
void setPort(int port); void setPort(int port);
/**
* Check if the address is multicast.
* @return True if multicast, false if not.
*/
bool isMulticast() const;
struct sockaddr_in addr; struct sockaddr_in addr;
}; };
@ -246,7 +252,7 @@ namespace net {
/** /**
* Create UDP socket. * 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. * @param laddr Local address to bind the socket to.
* @return Socket instance on success, Throws runtime_error otherwise. * @return Socket instance on success, Throws runtime_error otherwise.
*/ */
@ -254,7 +260,7 @@ namespace net {
/** /**
* Create UDP socket. * 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 rport Remote port.
* @param laddr Local address to bind the socket to. * @param laddr Local address to bind the socket to.
* @return Socket instance on success, Throws runtime_error otherwise. * @return Socket instance on success, Throws runtime_error otherwise.
@ -263,7 +269,7 @@ namespace net {
/** /**
* Create UDP socket. * 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 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). * @param lpost Local port used to bind the socket to (optional, 0 to allocate automatically).
* @return Socket instance on success, Throws runtime_error otherwise. * @return Socket instance on success, Throws runtime_error otherwise.
@ -272,7 +278,7 @@ namespace net {
/** /**
* Create UDP socket. * 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 rport Remote port.
* @param lhost Local hostname or IP used to bind the socket (optional, "0.0.0.0" for Any). * @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). * @param lpost Local port used to bind the socket to (optional, 0 to allocate automatically).