UDP socket edits by Erik Zandvliet
This commit is contained in:
		
							parent
							
								
									d56e7f1408
								
							
						
					
					
						commit
						243595ff4d
					
				
					 2 changed files with 59 additions and 24 deletions
				
			
		|  | @ -971,12 +971,18 @@ int Socket::Server::getSocket() { | ||||||
| /// If both fail, prints an DLVL_FAIL debug message.
 | /// If both fail, prints an DLVL_FAIL debug message.
 | ||||||
| /// \param nonblock Whether the socket should be nonblocking.
 | /// \param nonblock Whether the socket should be nonblocking.
 | ||||||
| Socket::UDPConnection::UDPConnection(bool nonblock) { | Socket::UDPConnection::UDPConnection(bool nonblock) { | ||||||
|  | #ifdef __CYGWIN__ | ||||||
|  | #warning UDP over IPv6 is currently disabled on windows | ||||||
|  |   isIPv6 = false; | ||||||
|  |   sock = socket(AF_INET, SOCK_DGRAM, 0); | ||||||
|  | #else | ||||||
|   isIPv6 = true; |   isIPv6 = true; | ||||||
|   sock = socket(AF_INET6, SOCK_DGRAM, 0); |   sock = socket(AF_INET6, SOCK_DGRAM, 0); | ||||||
|   if (sock == -1) { |   if (sock == -1) { | ||||||
|     sock = socket(AF_INET, SOCK_DGRAM, 0); |     sock = socket(AF_INET, SOCK_DGRAM, 0); | ||||||
|     isIPv6 = false; |     isIPv6 = false; | ||||||
|   } |   } | ||||||
|  | #endif | ||||||
|   if (sock == -1) { |   if (sock == -1) { | ||||||
|     DEBUG_MSG(DLVL_FAIL, "Could not create UDP socket: %s", strerror(errno)); |     DEBUG_MSG(DLVL_FAIL, "Could not create UDP socket: %s", strerror(errno)); | ||||||
|   } |   } | ||||||
|  | @ -995,18 +1001,18 @@ Socket::UDPConnection::UDPConnection(bool nonblock) { | ||||||
| /// Copies a UDP socket, re-allocating local copies of any needed structures.
 | /// Copies a UDP socket, re-allocating local copies of any needed structures.
 | ||||||
| /// The data/data_size/data_len variables are *not* copied over.
 | /// The data/data_size/data_len variables are *not* copied over.
 | ||||||
| Socket::UDPConnection::UDPConnection(const UDPConnection & o) { | Socket::UDPConnection::UDPConnection(const UDPConnection & o) { | ||||||
|  | #ifdef __CYGWIN__ | ||||||
|  | #warning UDP over IPv6 is currently disabled on windows | ||||||
|  |   isIPv6 = false; | ||||||
|  |   sock = socket(AF_INET, SOCK_DGRAM, 0); | ||||||
|  | #else | ||||||
|   isIPv6 = true; |   isIPv6 = true; | ||||||
|   sock = socket(AF_INET6, SOCK_DGRAM, 0); |   sock = socket(AF_INET6, SOCK_DGRAM, 0); | ||||||
|   if (sock == -1) { |   if (sock == -1) { | ||||||
|     sock = socket(AF_INET, SOCK_DGRAM, 0); |     sock = socket(AF_INET, SOCK_DGRAM, 0); | ||||||
|     isIPv6 = false; |     isIPv6 = false; | ||||||
|   }else{ |  | ||||||
| #ifdef __CYGWIN__ |  | ||||||
|     // Under windows, turn IPv6-only mode off.
 |  | ||||||
|     int on = 0; |  | ||||||
|     setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)); |  | ||||||
| #endif |  | ||||||
|   } |   } | ||||||
|  | #endif | ||||||
|   if (sock == -1) { |   if (sock == -1) { | ||||||
|     DEBUG_MSG(DLVL_FAIL, "Could not create UDP socket: %s", strerror(errno)); |     DEBUG_MSG(DLVL_FAIL, "Could not create UDP socket: %s", strerror(errno)); | ||||||
|   } |   } | ||||||
|  | @ -1144,7 +1150,8 @@ void Socket::UDPConnection::SendNow(const char * sdata, size_t len) { | ||||||
| /// If that fails too, gives up and returns zero.
 | /// If that fails too, gives up and returns zero.
 | ||||||
| /// Prints a debug message at DLVL_FAIL level if binding failed.
 | /// Prints a debug message at DLVL_FAIL level if binding failed.
 | ||||||
| /// \return Actually bound port number, or zero on error.
 | /// \return Actually bound port number, or zero on error.
 | ||||||
| int Socket::UDPConnection::bind(int port, std::string iface) { | int Socket::UDPConnection::bind(int port, std::string iface, const std::string & multicastInterfaces) { | ||||||
|  |   int result = 0; | ||||||
|   if (isIPv6) { |   if (isIPv6) { | ||||||
|     struct sockaddr_in6 s6; |     struct sockaddr_in6 s6; | ||||||
|     memset(&s6, 0, sizeof(s6)); |     memset(&s6, 0, sizeof(s6)); | ||||||
|  | @ -1157,32 +1164,60 @@ int Socket::UDPConnection::bind(int port, std::string iface) { | ||||||
|     s6.sin6_port = htons(port); |     s6.sin6_port = htons(port); | ||||||
|     int r = ::bind(sock, (sockaddr *)&s6, sizeof(s6)); |     int r = ::bind(sock, (sockaddr *)&s6, sizeof(s6)); | ||||||
|     if (r == 0) { |     if (r == 0) { | ||||||
|       return ntohs(s6.sin6_port); |       result = ntohs(s6.sin6_port); | ||||||
|     } |     } | ||||||
|   } else { |   } else { | ||||||
|     struct sockaddr_in s4; |     struct sockaddr_in s4; | ||||||
|     memset(&s4, 0, sizeof(s4)); |     memset(&s4, 0, sizeof(s4)); | ||||||
|     s4.sin_family = AF_INET; |     s4.sin_family = AF_INET; | ||||||
|     if (iface == "0.0.0.0" || iface.length() == 0) { |     if (iface == "0.0.0.0" || iface.length() == 0) { | ||||||
|       s4.sin_addr.s_addr = INADDR_ANY; |       s4.sin_addr.s_addr = htonl(INADDR_ANY); | ||||||
|     } else { |     } else { | ||||||
|       inet_pton(AF_INET, iface.c_str(), &s4.sin_addr); |       inet_pton(AF_INET, iface.c_str(), &s4.sin_addr); | ||||||
|     } |     } | ||||||
|     s4.sin_port = htons(port); |     s4.sin_port = htons(port); | ||||||
|     int r = ::bind(sock, (sockaddr *)&s4, sizeof(s4)); |     int r = ::bind(sock, (sockaddr *)&s4, sizeof(s4)); | ||||||
|     if (r == 0) { |     if (r == 0) { | ||||||
|       return ntohs(s4.sin_port); |       result = ntohs(s4.sin_port); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |   if (!result){ | ||||||
|     DEBUG_MSG(DLVL_FAIL, "Could not bind %s UDP socket to port %d: %s", isIPv6 ? "IPv6" : "IPv4", port, strerror(errno)); |     DEBUG_MSG(DLVL_FAIL, "Could not bind %s UDP socket to port %d: %s", isIPv6 ? "IPv6" : "IPv4", port, strerror(errno)); | ||||||
|     return 0; |     return 0; | ||||||
|   } |   } | ||||||
|  |   //Detect multicast
 | ||||||
|  |   if (iface.length() && ((atoi(iface.c_str()) & 0xE0) == 0xE0)){ | ||||||
|  |     if (!multicastInterfaces.length()){ | ||||||
|  |       WARN_MSG("Multicast IP given without any defined interfaces"); | ||||||
|  |     }else{ | ||||||
|  |       struct ip_mreq group; | ||||||
|  |       inet_pton(AF_INET, iface.c_str(), &group.imr_multiaddr.s_addr); | ||||||
|  |       size_t loc = 0; | ||||||
|  |       while (loc != std::string::npos){ | ||||||
|  |         size_t nxtPos = multicastInterfaces.find(',', loc); | ||||||
|  |         std::string curIface = multicastInterfaces.substr(loc, (nxtPos == std::string::npos ? nxtPos : nxtPos - loc)); | ||||||
|  |         inet_pton(AF_INET, curIface.c_str(), &group.imr_interface.s_addr); | ||||||
|  |         if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group)) < 0) { | ||||||
|  |           WARN_MSG("Unable to register for multicast on interface %s: %s", curIface.c_str() , strerror(errno)); | ||||||
|  |         } | ||||||
|  |         loc = (nxtPos == std::string::npos ? nxtPos : nxtPos + 1); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return result; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| /// Attempt to receive a UDP packet.
 | /// Attempt to receive a UDP packet.
 | ||||||
| /// This will automatically allocate or resize the internal data buffer if needed.
 | /// This will automatically allocate or resize the internal data buffer if needed.
 | ||||||
| /// If a packet is received, it will be placed in the "data" member, with it's length in "data_len".
 | /// If a packet is received, it will be placed in the "data" member, with it's length in "data_len".
 | ||||||
| /// \return True if a packet was received, false otherwise.
 | /// \return True if a packet was received, false otherwise.
 | ||||||
| bool Socket::UDPConnection::Receive() { | bool Socket::UDPConnection::Receive() { | ||||||
|  | #ifdef __CYGWIN__ | ||||||
|  |   if (data_size != SOCKETSIZE){ | ||||||
|  |     data = (char *)realloc(data, SOCKETSIZE); | ||||||
|  |     data_size = SOCKETSIZE; | ||||||
|  |   } | ||||||
|  | #endif | ||||||
|   int r = recvfrom(sock, data, data_size, MSG_PEEK | MSG_TRUNC, 0, 0); |   int r = recvfrom(sock, data, data_size, MSG_PEEK | MSG_TRUNC, 0, 0); | ||||||
|   if (r == -1) { |   if (r == -1) { | ||||||
|     if (errno != EAGAIN) { |     if (errno != EAGAIN) { | ||||||
|  |  | ||||||
|  | @ -137,7 +137,7 @@ namespace Socket { | ||||||
|       UDPConnection(bool nonblock = false); |       UDPConnection(bool nonblock = false); | ||||||
|       ~UDPConnection(); |       ~UDPConnection(); | ||||||
|       int getSock(); |       int getSock(); | ||||||
|       int bind(int port, std::string iface = ""); |       int bind(int port, std::string iface = "", const std::string & multicastAddress = ""); | ||||||
|       void setBlocking(bool blocking); |       void setBlocking(bool blocking); | ||||||
|       void SetDestination(std::string hostname, uint32_t port); |       void SetDestination(std::string hostname, uint32_t port); | ||||||
|       void GetDestination(std::string & hostname, uint32_t & port); |       void GetDestination(std::string & hostname, uint32_t & port); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Thulinma
						Thulinma