@@ -233,15 +233,16 @@ void *pool = objc_autoreleasePoolPush(); OFCharacterSet *whitespaceCharacterSet = [OFCharacterSet whitespaceCharacterSet]; of_socket_address_t ret; - struct sockaddr_in *addrIn = (struct sockaddr_in *)&ret.address; + struct sockaddr_in *addrIn = &ret.sockaddr.in; OFArray OF_GENERIC(OFString *) *components; uint32_t addr; memset(&ret, '\0', sizeof(ret)); + ret.family = OF_SOCKET_ADDRESS_FAMILY_IPV4; ret.length = sizeof(struct sockaddr_in); addrIn->sin_family = AF_INET; addrIn->sin_port = OF_BSWAP16_IF_LE(port); @@ -275,11 +276,10 @@ objc_autoreleasePoolPop(pool); return ret; } -#ifdef OF_HAVE_IPV6 static uint16_t parseIPv6Component(OFString *component) { uintmax_t number; @@ -298,17 +298,22 @@ of_socket_address_t of_socket_address_parse_ipv6(OFString *IPv6, uint16_t port) { void *pool = objc_autoreleasePoolPush(); of_socket_address_t ret; - struct sockaddr_in6 *addrIn6 = (struct sockaddr_in6 *)&ret.address; + struct sockaddr_in6 *addrIn6 = &ret.sockaddr.in6; size_t doubleColon; memset(&ret, '\0', sizeof(ret)); + ret.family = OF_SOCKET_ADDRESS_FAMILY_IPV6; ret.length = sizeof(struct sockaddr_in6); +#ifdef AF_INET6 addrIn6->sin6_family = AF_INET6; +#else + addrIn6->sin6_family = AF_UNSPEC; +#endif addrIn6->sin6_port = OF_BSWAP16_IF_LE(port); doubleColon = [IPv6 rangeOfString: @"::"].location; if (doubleColon != OF_NOT_FOUND) { @@ -368,76 +373,67 @@ objc_autoreleasePoolPop(pool); return ret; } -#endif of_socket_address_t of_socket_address_parse_ip(OFString *IP, uint16_t port) { -#ifdef OF_HAVE_IPV6 @try { return of_socket_address_parse_ipv6(IP, port); } @catch (OFInvalidFormatException *e) { -#endif return of_socket_address_parse_ipv4(IP, port); -#ifdef OF_HAVE_IPV6 } -#endif } bool of_socket_address_equal(of_socket_address_t *address1, of_socket_address_t *address2) { struct sockaddr_in *addrIn1, *addrIn2; -#ifdef OF_HAVE_IPV6 struct sockaddr_in6 *addrIn6_1, *addrIn6_2; -#endif - if (address1->address.ss_family != address2->address.ss_family) + if (address1->family != address2->family) return false; - switch (address1->address.ss_family) { - case AF_INET: + switch (address1->family) { + case OF_SOCKET_ADDRESS_FAMILY_IPV4: #if !defined(OF_WII) && !defined(OF_NINTENDO_3DS) if (address1->length < (socklen_t)sizeof(struct sockaddr_in) || address2->length < (socklen_t)sizeof(struct sockaddr_in)) @throw [OFInvalidArgumentException exception]; #else if (address1->length < 8 || address2->length < 8) @throw [OFInvalidArgumentException exception]; #endif - addrIn1 = (struct sockaddr_in *)&address1->address; - addrIn2 = (struct sockaddr_in *)&address2->address; + addrIn1 = &address1->sockaddr.in; + addrIn2 = &address2->sockaddr.in; if (addrIn1->sin_port != addrIn2->sin_port) return false; if (addrIn1->sin_addr.s_addr != addrIn2->sin_addr.s_addr) return false; break; -#ifdef OF_HAVE_IPV6 - case AF_INET6: + case OF_SOCKET_ADDRESS_FAMILY_IPV6: if (address1->length < (socklen_t)sizeof(struct sockaddr_in6) || address2->length < (socklen_t)sizeof(struct sockaddr_in6)) @throw [OFInvalidArgumentException exception]; - addrIn6_1 = (struct sockaddr_in6 *)&address1->address; - addrIn6_2 = (struct sockaddr_in6 *)&address2->address; + addrIn6_1 = &address1->sockaddr.in6; + addrIn6_2 = &address2->sockaddr.in6; if (addrIn6_1->sin6_port != addrIn6_2->sin6_port) return false; if (memcmp(addrIn6_1->sin6_addr.s6_addr, addrIn6_2->sin6_addr.s6_addr, sizeof(addrIn6_1->sin6_addr.s6_addr)) != 0) return false; break; -#endif default: @throw [OFInvalidArgumentException exception]; } return true; @@ -444,67 +440,59 @@ } uint32_t of_socket_address_hash(of_socket_address_t *address) { - uint32_t hash = of_hash_seed; - struct sockaddr_in *addrIn; -#ifdef OF_HAVE_IPV6 - struct sockaddr_in6 *addrIn6; - uint32_t subhash; -#endif - - hash += address->address.ss_family; - - switch (address->address.ss_family) { - case AF_INET: + uint32_t hash; + + OF_HASH_INIT(hash); + OF_HASH_ADD(hash, address->family); + + switch (address->family) { + case OF_SOCKET_ADDRESS_FAMILY_IPV4: #if !defined(OF_WII) && !defined(OF_NINTENDO_3DS) if (address->length < (socklen_t)sizeof(struct sockaddr_in)) @throw [OFInvalidArgumentException exception]; #else if (address->length < 8) @throw [OFInvalidArgumentException exception]; #endif - addrIn = (struct sockaddr_in *)&address->address; - - hash += (addrIn->sin_port << 1); - hash ^= addrIn->sin_addr.s_addr; + OF_HASH_ADD(hash, address->sockaddr.in.sin_port >> 8); + OF_HASH_ADD(hash, address->sockaddr.in.sin_port); + OF_HASH_ADD(hash, address->sockaddr.in.sin_addr.s_addr >> 24); + OF_HASH_ADD(hash, address->sockaddr.in.sin_addr.s_addr >> 16); + OF_HASH_ADD(hash, address->sockaddr.in.sin_addr.s_addr >> 8); + OF_HASH_ADD(hash, address->sockaddr.in.sin_addr.s_addr); break; -#ifdef OF_HAVE_IPV6 - case AF_INET6: + case OF_SOCKET_ADDRESS_FAMILY_IPV6: if (address->length < (socklen_t)sizeof(struct sockaddr_in6)) @throw [OFInvalidArgumentException exception]; - addrIn6 = (struct sockaddr_in6 *)&address->address; - - hash += (addrIn6->sin6_port << 1); - - OF_HASH_INIT(subhash); - - for (size_t i = 0; i < sizeof(addrIn6->sin6_addr.s6_addr); i++) - OF_HASH_ADD(subhash, addrIn6->sin6_addr.s6_addr[i]); - - OF_HASH_FINALIZE(subhash); - - hash ^= subhash; + OF_HASH_ADD(hash, address->sockaddr.in6.sin6_port >> 8); + OF_HASH_ADD(hash, address->sockaddr.in6.sin6_port); + + for (size_t i = 0; + i < sizeof(address->sockaddr.in6.sin6_addr.s6_addr); i++) + OF_HASH_ADD(hash, + address->sockaddr.in6.sin6_addr.s6_addr[i]); break; -#endif default: @throw [OFInvalidArgumentException exception]; } + + OF_HASH_FINALIZE(hash); return hash; } static OFString * IPv4String(const of_socket_address_t *address, uint16_t *port) { - const struct sockaddr_in *addrIn = - (const struct sockaddr_in *)&address->address; + const struct sockaddr_in *addrIn = &address->sockaddr.in; uint32_t addr = OF_BSWAP32_IF_LE(addrIn->sin_addr.s_addr); OFString *string; string = [OFString stringWithFormat: @"%u.%u.%u.%u", (addr & 0xFF000000) >> 24, (addr & 0x00FF0000) >> 16, @@ -514,17 +502,15 @@ *port = OF_BSWAP16_IF_LE(addrIn->sin_port); return string; } -#ifdef OF_HAVE_IPV6 static OFString * IPv6String(const of_socket_address_t *address, uint16_t *port) { OFMutableString *string = [OFMutableString string]; - const struct sockaddr_in6 *addrIn6 = - (const struct sockaddr_in6 *)&address->address; + const struct sockaddr_in6 *addrIn6 = &address->sockaddr.in6; int_fast8_t zerosStart = -1, maxZerosStart = -1; uint_fast8_t zerosCount = 0, maxZerosCount = 0; bool first = true; for (uint_fast8_t i = 0; i < 16; i += 2) { @@ -585,21 +571,33 @@ if (port != NULL) *port = OF_BSWAP16_IF_LE(addrIn6->sin6_port); return string; } -#endif OFString * of_socket_address_ip_string(const of_socket_address_t *address, uint16_t *port) { - switch (address->address.ss_family) { - case AF_INET: + switch (address->family) { + case OF_SOCKET_ADDRESS_FAMILY_IPV4: return IPv4String(address, port); -#ifdef OF_HAVE_IPV6 - case AF_INET6: + case OF_SOCKET_ADDRESS_FAMILY_IPV6: return IPv6String(address, port); -#endif + default: + @throw [OFInvalidArgumentException exception]; + } +} + +void +of_socket_address_set_port(of_socket_address_t *address, uint16_t port) +{ + switch (address->family) { + case OF_SOCKET_ADDRESS_FAMILY_IPV4: + address->sockaddr.in.sin_port = OF_BSWAP16_IF_LE(port); + break; + case OF_SOCKET_ADDRESS_FAMILY_IPV6: + address->sockaddr.in6.sin6_port = OF_BSWAP16_IF_LE(port); + break; default: @throw [OFInvalidArgumentException exception]; } }