Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -24,15 +24,10 @@ OFDate.m \ OFDictionary.m \ OFEnumerator.m \ OFGZIPStream.m \ OFHMAC.m \ - ${OFHTTPCLIENT_M} \ - OFHTTPCookie.m \ - OFHTTPCookieManager.m \ - OFHTTPRequest.m \ - OFHTTPResponse.m \ OFInflate64Stream.m \ OFInflateStream.m \ OFIntrospection.m \ OFInvocation.m \ OFLHAArchive.m \ @@ -128,10 +123,15 @@ OFSettings.m \ OFString+PathAdditions.m SRCS_PLUGINS = OFPlugin.m SRCS_SOCKETS = OFDNSResolver.m \ OFDNSResourceRecord.m \ + ${OFHTTPCLIENT_M} \ + OFHTTPCookie.m \ + OFHTTPCookieManager.m \ + OFHTTPRequest.m \ + OFHTTPResponse.m \ OFHTTPServer.m \ OFStreamSocket.m \ OFTCPSocket.m \ OFUDPSocket.m \ resolver.m \ Index: src/OFDNSResolver.m ================================================================== --- src/OFDNSResolver.m +++ src/OFDNSResolver.m @@ -1207,33 +1207,36 @@ repeats: false]]; address = of_socket_address_parse_ip( [[query nameServers] firstObject], 53); + switch (address.family) { #ifdef OF_HAVE_IPV6 - if (address.address.ss_family == AF_INET6) { + case OF_SOCKET_ADDRESS_FAMILY_IPV6: if (_IPv6Socket == nil) { _IPv6Socket = [[OFUDPSocket alloc] init]; [_IPv6Socket bindToHost: @"::" port: 0]; [_IPv6Socket setBlocking: false]; } sock = _IPv6Socket; - } else { + break; #endif + case OF_SOCKET_ADDRESS_FAMILY_IPV4: if (_IPv4Socket == nil) { _IPv4Socket = [[OFUDPSocket alloc] init]; [_IPv4Socket bindToHost: @"0.0.0.0" port: 0]; [_IPv4Socket setBlocking: false]; } sock = _IPv4Socket; -#ifdef OF_HAVE_IPV6 + break; + default: + @throw [OFInvalidArgumentException exception]; } -#endif [sock asyncSendBuffer: [[query queryData] items] length: [[query queryData] count] receiver: address target: self Index: src/OFHTTPRequest.h ================================================================== --- src/OFHTTPRequest.h +++ src/OFHTTPRequest.h @@ -15,10 +15,12 @@ * file. */ #import "OFObject.h" #import "OFString.h" + +#import "socket.h" OF_ASSUME_NONNULL_BEGIN @class OFURL; @class OFDictionary OF_GENERIC(KeyType, ObjectType); @@ -71,11 +73,11 @@ { OFURL *_URL; of_http_request_method_t _method; of_http_request_protocol_version_t _protocolVersion; OFDictionary OF_GENERIC(OFString *, OFString *) *_Nullable _headers; - OFString *_Nullable _remoteAddress; + of_socket_address_t _remoteAddress; } /*! * @brief The URL of the HTTP request. */ @@ -103,11 +105,12 @@ OFDictionary OF_GENERIC(OFString *, OFString *) *headers; /*! * @brief The remote address from which the request originates. */ -@property OF_NULLABLE_PROPERTY (copy, nonatomic) OFString *remoteAddress; +@property OF_NULLABLE_PROPERTY (nonatomic) + const of_socket_address_t *remoteAddress; /*! * @brief Creates a new OFHTTPRequest. * * @return A new, autoreleased OFHTTPRequest Index: src/OFHTTPRequest.m ================================================================== --- src/OFHTTPRequest.m +++ src/OFHTTPRequest.m @@ -78,11 +78,10 @@ @throw [OFInvalidFormatException exception]; } @implementation OFHTTPRequest @synthesize URL = _URL, method = _method, headers = _headers; -@synthesize remoteAddress = _remoteAddress; + (instancetype)request { return [[[self alloc] init] autorelease]; } @@ -119,14 +118,23 @@ - (void)dealloc { [_URL release]; [_headers release]; - [_remoteAddress release]; [super dealloc]; } + +- (void)setRemoteAddress: (const of_socket_address_t *)remoteAddress +{ + _remoteAddress = *remoteAddress; +} + +- (const of_socket_address_t *)remoteAddress +{ + return &_remoteAddress; +} - (id)copy { OFHTTPRequest *copy = [[OFHTTPRequest alloc] init]; @@ -133,11 +141,11 @@ @try { copy->_method = _method; copy->_protocolVersion = _protocolVersion; [copy setURL: _URL]; [copy setHeaders: _headers]; - [copy setRemoteAddress: _remoteAddress]; + [copy setRemoteAddress: &_remoteAddress]; } @catch (id e) { [copy release]; @throw e; } @@ -159,11 +167,11 @@ if (request->_method != _method || request->_protocolVersion.major != _protocolVersion.major || request->_protocolVersion.minor != _protocolVersion.minor || ![request->_URL isEqual: _URL] || ![request->_headers isEqual: _headers] || - ![request->_remoteAddress isEqual: _remoteAddress]) + !of_socket_address_equal(&request->_remoteAddress, &_remoteAddress)) return false; return true; } @@ -176,11 +184,11 @@ OF_HASH_ADD(hash, _method); OF_HASH_ADD(hash, _protocolVersion.major); OF_HASH_ADD(hash, _protocolVersion.minor); OF_HASH_ADD_HASH(hash, [_URL hash]); OF_HASH_ADD_HASH(hash, [_headers hash]); - OF_HASH_ADD_HASH(hash, [_remoteAddress hash]); + OF_HASH_ADD_HASH(hash, of_socket_address_hash(&_remoteAddress)); OF_HASH_FINALIZE(hash); return hash; } @@ -246,12 +254,13 @@ @"<%@:\n\tURL = %@\n" @"\tMethod = %s\n" @"\tHeaders = %@\n" @"\tRemote address = %@\n" @">", - [self class], _URL, method, indentedHeaders, _remoteAddress]; + [self class], _URL, method, indentedHeaders, + of_socket_address_ip_string(&_remoteAddress, NULL)]; objc_autoreleasePoolPop(pool); return [ret autorelease]; } @end Index: src/OFTCPSocket.h ================================================================== --- src/OFTCPSocket.h +++ src/OFTCPSocket.h @@ -60,12 +60,11 @@ * To create a server, create a socket, bind it and listen on it. */ @interface OFTCPSocket: OFStreamSocket { bool _listening; - struct sockaddr *_Nullable _address; - socklen_t _addressLength; + of_socket_address_t _remoteAddress; OFString *_Nullable _SOCKS5Host; uint16_t _SOCKS5Port; #ifdef OF_WII uint16_t _port; #endif @@ -80,15 +79,15 @@ * @brief Whether the socket is a listening socket. */ @property (readonly, nonatomic, getter=isListening) bool listening; /*! - * @brief The remote address as a string + * @brief The remote address. * * @note This only works for accepted sockets! */ -@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFString *remoteAddress; +@property (readonly, nonatomic) const of_socket_address_t *remoteAddress; #if !defined(OF_WII) && !defined(OF_NINTENDO_3DS) /*! * @brief Whether keep alives are enabled for the connection. * Index: src/OFTCPSocket.m ================================================================== --- src/OFTCPSocket.m +++ src/OFTCPSocket.m @@ -364,20 +364,11 @@ - (uint16_t)bindToHost: (OFString *)host port: (uint16_t)port { of_resolver_result_t **results; const int one = 1; -#if !defined(OF_WII) && !defined(OF_NINTENDO_3DS) - union { - struct sockaddr_storage storage; - struct sockaddr_in in; -# ifdef OF_HAVE_IPV6 - struct sockaddr_in6 in6; -# endif - } addr; - socklen_t addrLen; -#endif + of_socket_address_t address; if (_socket != INVALID_SOCKET) @throw [OFAlreadyConnectedException exceptionWithSocket: self]; if (_SOCKS5Host != nil) @@ -481,13 +472,13 @@ if (port > 0) return port; #if !defined(OF_WII) && !defined(OF_NINTENDO_3DS) - addrLen = (socklen_t)sizeof(addr.storage); - if (of_getsockname(_socket, (struct sockaddr *)&addr.storage, - &addrLen) != 0) { + address.length = (socklen_t)sizeof(address.sockaddr); + if (of_getsockname(_socket, &address.sockaddr.sockaddr, + &address.length) != 0) { int errNo = of_socket_errno(); closesocket(_socket); _socket = INVALID_SOCKET; @@ -495,15 +486,15 @@ port: port socket: self errNo: errNo]; } - if (addr.storage.ss_family == AF_INET) - return OF_BSWAP16_IF_LE(addr.in.sin_port); + if (address.sockaddr.sockaddr.sa_family == AF_INET) + return OF_BSWAP16_IF_LE(address.sockaddr.in.sin_port); # ifdef OF_HAVE_IPV6 - if (addr.storage.ss_family == AF_INET6) - return OF_BSWAP16_IF_LE(addr.in6.sin6_port); + if (address.sockaddr.sockaddr.sa_family == AF_INET6) + return OF_BSWAP16_IF_LE(address.sockaddr.in6.sin6_port); # endif #endif closesocket(_socket); _socket = INVALID_SOCKET; @@ -539,29 +530,32 @@ # if defined(HAVE_FCNTL) && defined(FD_CLOEXEC) int flags; # endif #endif - client->_address = [client - allocMemoryWithSize: sizeof(struct sockaddr_storage)]; - client->_addressLength = (socklen_t)sizeof(struct sockaddr_storage); + client->_remoteAddress.length = + (socklen_t)sizeof(client->_remoteAddress.sockaddr); #if defined(HAVE_PACCEPT) && defined(SOCK_CLOEXEC) - if ((client->_socket = paccept(_socket, client->_address, - &client->_addressLength, NULL, SOCK_CLOEXEC)) == INVALID_SOCKET) + if ((client->_socket = paccept(_socket, + &client->_remoteAddress.sockaddr.sockaddr, + &client->_remoteAddress.length, NULL, SOCK_CLOEXEC)) == + INVALID_SOCKET) @throw [OFAcceptFailedException exceptionWithSocket: self errNo: of_socket_errno()]; #elif defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) - if ((client->_socket = accept4(_socket, client->_address, - &client->_addressLength, SOCK_CLOEXEC)) == INVALID_SOCKET) + if ((client->_socket = accept4(_socket, + &client->_remoteAddress.sockaddr.sockaddr, + &client->_remoteAddress.length, SOCK_CLOEXEC)) == INVALID_SOCKET) @throw [OFAcceptFailedException exceptionWithSocket: self errNo: of_socket_errno()]; #else - if ((client->_socket = accept(_socket, client->_address, - &client->_addressLength)) == INVALID_SOCKET) + if ((client->_socket = accept(_socket, + &client->_remoteAddress.sockaddr.sockaddr, + &client->_remoteAddress.length)) == INVALID_SOCKET) @throw [OFAcceptFailedException exceptionWithSocket: self errNo: of_socket_errno()]; # if defined(HAVE_FCNTL) && defined(FD_CLOEXEC) @@ -568,21 +562,26 @@ if ((flags = fcntl(client->_socket, F_GETFD, 0)) != -1) fcntl(client->_socket, F_SETFD, flags | FD_CLOEXEC); # endif #endif - assert(client->_addressLength <= - (socklen_t)sizeof(struct sockaddr_storage)); - - if (client->_addressLength != sizeof(struct sockaddr_storage)) { - @try { - client->_address = [client - resizeMemory: client->_address - size: client->_addressLength]; - } @catch (OFOutOfMemoryException *e) { - /* We don't care, as we only made it smaller */ - } + assert(client->_remoteAddress.length <= + (socklen_t)sizeof(client->_remoteAddress.sockaddr)); + + switch (client->_remoteAddress.sockaddr.sockaddr.sa_family) { + case AF_INET: + client->_remoteAddress.family = OF_SOCKET_ADDRESS_FAMILY_IPV4; + break; +#ifdef OF_HAVE_IPV6 + case AF_INET6: + client->_remoteAddress.family = OF_SOCKET_ADDRESS_FAMILY_IPV6; + break; +#endif + default: + client->_remoteAddress.family = + OF_SOCKET_ADDRESS_FAMILY_UNKNOWN; + break; } return client; } @@ -602,28 +601,22 @@ [OFRunLoop of_addAsyncAcceptForTCPSocket: self block: block]; } #endif -- (OFString *)remoteAddress +- (const of_socket_address_t *)remoteAddress { - of_socket_address_t address; - if (_socket == INVALID_SOCKET) @throw [OFNotOpenException exceptionWithObject: self]; - if (_address == NULL) + if (_remoteAddress.length == 0) @throw [OFInvalidArgumentException exception]; - if (_addressLength > (socklen_t)sizeof(address.address)) + if (_remoteAddress.length > (socklen_t)sizeof(_remoteAddress.sockaddr)) @throw [OFOutOfRangeException exception]; - memset(&address, '\0', sizeof(address)); - memcpy(&address.address, _address, _addressLength); - address.length = _addressLength; - - return of_socket_address_ip_string(&address, NULL); + return &_remoteAddress; } - (bool)isListening { return _listening; @@ -685,16 +678,14 @@ - (void)close { _listening = false; - [self freeMemory: _address]; - _address = NULL; - _addressLength = 0; + memset(&_remoteAddress, 0, sizeof(_remoteAddress)); #ifdef OF_WII _port = 0; #endif [super close]; } @end Index: src/OFUDPSocket.m ================================================================== --- src/OFUDPSocket.m +++ src/OFUDPSocket.m @@ -204,15 +204,29 @@ { of_resolver_result_t **results = of_resolve_host(host, port, SOCK_DGRAM); assert(results[0]->addressLength <= - (socklen_t)sizeof(address->address)); + (socklen_t)sizeof(address->sockaddr)); - memcpy(&address->address, results[0]->address, + memcpy(&address->sockaddr, results[0]->address, results[0]->addressLength); address->length = results[0]->addressLength; + + switch (results[0]->address->sa_family) { + case AF_INET: + address->family = OF_SOCKET_ADDRESS_FAMILY_IPV4; + break; +#ifdef OF_HAVE_IPV6 + case AF_INET6: + address->family = OF_SOCKET_ADDRESS_FAMILY_IPV6; + break; +#endif + default: + address->family = OF_SOCKET_ADDRESS_FAMILY_UNKNOWN; + break; + } of_resolver_free(results); } #ifdef OF_HAVE_THREADS @@ -316,20 +330,11 @@ - (uint16_t)bindToHost: (OFString *)host port: (uint16_t)port { of_resolver_result_t **results; -#if !defined(OF_WII) && !defined(OF_NINTENDO_3DS) - union { - struct sockaddr_storage storage; - struct sockaddr_in in; -# ifdef OF_HAVE_IPV6 - struct sockaddr_in6 in6; -# endif - } addr; - socklen_t addrLen; -#endif + of_socket_address_t address; results = of_resolve_host(host, port, SOCK_DGRAM); @try { #if SOCK_CLOEXEC == 0 && defined(HAVE_FCNTL) && defined(FD_CLOEXEC) int flags; @@ -423,13 +428,13 @@ if (port > 0) return port; #if !defined(OF_WII) && !defined(OF_NINTENDO_3DS) - addrLen = (socklen_t)sizeof(addr.storage); - if (of_getsockname(_socket, (struct sockaddr *)&addr.storage, - &addrLen) != 0) { + address.length = (socklen_t)sizeof(address.sockaddr); + if (of_getsockname(_socket, &address.sockaddr.sockaddr, + &address.length) != 0) { int errNo = of_socket_errno(); closesocket(_socket); _socket = INVALID_SOCKET; @@ -437,15 +442,15 @@ port: port socket: self errNo: errNo]; } - if (addr.storage.ss_family == AF_INET) - return OF_BSWAP16_IF_LE(addr.in.sin_port); + if (address.sockaddr.sockaddr.sa_family == AF_INET) + return OF_BSWAP16_IF_LE(address.sockaddr.in.sin_port); # ifdef OF_HAVE_IPV6 - if (addr.storage.ss_family == AF_INET6) - return OF_BSWAP16_IF_LE(addr.in6.sin6_port); + if (address.sockaddr.sockaddr.sa_family == AF_INET6) + return OF_BSWAP16_IF_LE(address.sockaddr.in6.sin6_port); # endif #endif closesocket(_socket); _socket = INVALID_SOCKET; @@ -462,30 +467,44 @@ ssize_t ret; if (_socket == INVALID_SOCKET) @throw [OFNotOpenException exceptionWithObject: self]; - sender->length = (socklen_t)sizeof(sender->address); + sender->length = (socklen_t)sizeof(sender->sockaddr); #ifndef OF_WINDOWS if ((ret = recvfrom(_socket, buffer, length, 0, - (struct sockaddr *)&sender->address, &sender->length)) < 0) + &sender->sockaddr.sockaddr, &sender->length)) < 0) @throw [OFReadFailedException exceptionWithObject: self requestedLength: length errNo: of_socket_errno()]; #else if (length > INT_MAX) @throw [OFOutOfRangeException exception]; if ((ret = recvfrom(_socket, buffer, (int)length, 0, - (struct sockaddr *)&sender->address, &sender->length)) < 0) + &sender->sockaddr.sockaddr, &sender->length)) < 0) @throw [OFReadFailedException exceptionWithObject: self requestedLength: length errNo: of_socket_errno()]; #endif + + switch (sender->sockaddr.sockaddr.sa_family) { + case AF_INET: + sender->family = OF_SOCKET_ADDRESS_FAMILY_IPV4; + break; +#ifdef OF_HAVE_IPV6 + case AF_INET6: + sender->family = OF_SOCKET_ADDRESS_FAMILY_IPV6; + break; +#endif + default: + sender->family = OF_SOCKET_ADDRESS_FAMILY_UNKNOWN; + break; + } return ret; } - (void)asyncReceiveIntoBuffer: (void *)buffer @@ -526,11 +545,11 @@ if (length > SSIZE_MAX) @throw [OFOutOfRangeException exception]; if ((bytesWritten = sendto(_socket, buffer, length, 0, - (struct sockaddr *)&receiver->address, receiver->length)) < 0) + &receiver->sockaddr.sockaddr, receiver->length)) < 0) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length bytesWritten: 0 errNo: of_socket_errno()]; @@ -539,12 +558,11 @@ if (length > INT_MAX) @throw [OFOutOfRangeException exception]; if ((bytesWritten = sendto(_socket, buffer, (int)length, 0, - (struct sockaddr *)&receiver->address, - receiver->length)) < 0) + &receiver->sockaddr.sockaddr, receiver->length)) < 0) @throw [OFWriteFailedException exceptionWithObject: self requestedLength: length bytesWritten: 0 errNo: of_socket_errno()]; Index: src/ObjFW.h ================================================================== --- src/ObjFW.h +++ src/ObjFW.h @@ -76,18 +76,18 @@ # import "OFUDPSocket.h" # import "OFTLSSocket.h" # import "OFKernelEventObserver.h" # import "OFDNSResolver.h" #endif -#import "OFHTTPCookie.h" -#import "OFHTTPCookieManager.h" -#import "OFHTTPRequest.h" -#import "OFHTTPResponse.h" #ifdef OF_HAVE_SOCKETS # ifdef OF_HAVE_THREADS # import "OFHTTPClient.h" # endif +# import "OFHTTPCookie.h" +# import "OFHTTPCookieManager.h" +# import "OFHTTPRequest.h" +# import "OFHTTPResponse.h" # import "OFHTTPServer.h" #endif #ifdef OF_HAVE_PROCESSES # import "OFProcess.h" Index: src/socket.h ================================================================== --- src/socket.h +++ src/socket.h @@ -48,45 +48,23 @@ # include #endif /*! @file */ -#if defined(OF_AMIGAOS) && defined(OF_MORPHOS_IXEMUL) -struct sockaddr_storage { - uint8_t ss_len; - sa_family_t ss_family; - char ss_data[2 + sizeof(struct in_addr) + 8]; -}; -#endif - #ifdef OF_MORPHOS typedef long socklen_t; #endif #ifdef OF_MORPHOS_IXEMUL typedef int socklen_t; #endif #ifdef OF_WII # include - -struct sockaddr_storage { - u8 ss_len; - sa_family_t ss_family; - u8 ss_data[14]; -}; #endif #ifdef OF_PSP # include - -struct sockaddr_storage { - uint8_t ss_len; - sa_family_t ss_family; - in_port_t ss_data1; - struct in_addr ss_data2; - int8_t ss_data3[8]; -}; #endif #import "macros.h" OF_ASSUME_NONNULL_BEGIN @@ -95,17 +73,50 @@ typedef int of_socket_t; #else typedef SOCKET of_socket_t; #endif +/*! + * @enum of_socket_address_type_t socket.h ObjFW/socket.h + */ +typedef enum { + OF_SOCKET_ADDRESS_FAMILY_UNKNOWN, + OF_SOCKET_ADDRESS_FAMILY_IPV4, + OF_SOCKET_ADDRESS_FAMILY_IPV6, +} of_socket_address_family_t; + +#ifndef OF_HAVE_IPV6 +struct sockaddr_in6 { + sa_family_t sin6_family; + in_port_t sin6_port; + uint32_t sin6_flowinfo; + struct in6_addr { + uint8_t s6_addr[16]; + } sin6_addr; + uint32_t sin6_scope_id; +}; +#endif + /*! * @struct of_socket_address_t socket.h ObjFW/socket.h * * @brief A struct which represents a host / port pair for a socket. */ typedef struct OF_BOXABLE { - struct sockaddr_storage address; + /* + * Even though struct sockaddr contains the family, we need to use our + * own family, as we need to support storing an IPv6 address on systems + * that don't support IPv6. These may not have AF_INET6 defined and we + * can't just define it, as the value is system-dependent and might + * clash with an existing value. + */ + of_socket_address_family_t family; + union { + struct sockaddr sockaddr; + struct sockaddr_in in; + struct sockaddr_in6 in6; + } sockaddr; socklen_t length; } of_socket_address_t; #ifdef __cplusplus extern "C" { @@ -175,10 +186,20 @@ * address or NULL if the port is not needed * @return The address as an IP string */ extern OFString *_Nonnull of_socket_address_ip_string( const of_socket_address_t *_Nonnull address, uint16_t *_Nullable port); + +/*! + * @brief Sets the port of the specified of_socket_address_t, independent of + * the address family used. + * + * @param address The address on which to set the port + * @param port The port to set on the address + */ +extern void of_socket_address_set_port(of_socket_address_t *_Nonnull address, + uint16_t port); #ifdef __cplusplus } #endif OF_ASSUME_NONNULL_END Index: src/socket.m ================================================================== --- src/socket.m +++ src/socket.m @@ -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]; } } Index: tests/OFTCPSocketTests.m ================================================================== --- tests/OFTCPSocketTests.m +++ tests/OFTCPSocketTests.m @@ -49,11 +49,12 @@ port: port])) TEST(@"-[accept]", (accepted = [server accept])) TEST(@"-[remoteAddress]", - [[accepted remoteAddress] isEqual: @"127.0.0.1"]) + [of_socket_address_ip_string([accepted remoteAddress], NULL) + isEqual: @"127.0.0.1"]) TEST(@"-[writeString:]", [client writeString: @"Hello!"]) TEST(@"-[readIntoBuffer:length:]", [accepted readIntoBuffer: buf length: 6] && Index: tests/SocketTests.m ================================================================== --- tests/SocketTests.m +++ tests/SocketTests.m @@ -24,46 +24,44 @@ #import "TestsAppDelegate.h" #import "socket.h" -#define SOCKADDR_IN(a) (*(struct sockaddr_in *)&a.address) -#define SOCKADDR_IN6(a) (*(struct sockaddr_in6 *)&a.address) #define COMPARE_V6(a, a0, a1, a2, a3, a4, a5, a6, a7) \ - (SOCKADDR_IN6(a).sin6_addr.s6_addr[0] == (a0 >> 8) && \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[1] == (a0 & 0xFF) && \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[2] == (a1 >> 8) && \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[3] == (a1 & 0xFF) && \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[4] == (a2 >> 8) && \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[5] == (a2 & 0xFF) && \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[6] == (a3 >> 8) && \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[7] == (a3 & 0xFF) && \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[8] == (a4 >> 8) && \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[9] == (a4 & 0xFF) && \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[10] == (a5 >> 8) && \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[11] == (a5 & 0xFF) && \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[12] == (a6 >> 8) && \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[13] == (a6 & 0xFF) && \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[14] == (a7 >> 8) && \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[15] == (a7 & 0xFF)) + (a.sockaddr.in6.sin6_addr.s6_addr[0] == (a0 >> 8) && \ + a.sockaddr.in6.sin6_addr.s6_addr[1] == (a0 & 0xFF) && \ + a.sockaddr.in6.sin6_addr.s6_addr[2] == (a1 >> 8) && \ + a.sockaddr.in6.sin6_addr.s6_addr[3] == (a1 & 0xFF) && \ + a.sockaddr.in6.sin6_addr.s6_addr[4] == (a2 >> 8) && \ + a.sockaddr.in6.sin6_addr.s6_addr[5] == (a2 & 0xFF) && \ + a.sockaddr.in6.sin6_addr.s6_addr[6] == (a3 >> 8) && \ + a.sockaddr.in6.sin6_addr.s6_addr[7] == (a3 & 0xFF) && \ + a.sockaddr.in6.sin6_addr.s6_addr[8] == (a4 >> 8) && \ + a.sockaddr.in6.sin6_addr.s6_addr[9] == (a4 & 0xFF) && \ + a.sockaddr.in6.sin6_addr.s6_addr[10] == (a5 >> 8) && \ + a.sockaddr.in6.sin6_addr.s6_addr[11] == (a5 & 0xFF) && \ + a.sockaddr.in6.sin6_addr.s6_addr[12] == (a6 >> 8) && \ + a.sockaddr.in6.sin6_addr.s6_addr[13] == (a6 & 0xFF) && \ + a.sockaddr.in6.sin6_addr.s6_addr[14] == (a7 >> 8) && \ + a.sockaddr.in6.sin6_addr.s6_addr[15] == (a7 & 0xFF)) #define SET_V6(a, a0, a1, a2, a3, a4, a5, a6, a7) \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[0] = a0 >> 8; \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[1] = a0 & 0xFF; \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[2] = a1 >> 8; \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[3] = a1 & 0xFF; \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[4] = a2 >> 8; \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[5] = a2 & 0xFF; \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[6] = a3 >> 8; \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[7] = a3 & 0xFF; \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[8] = a4 >> 8; \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[9] = a4 & 0xFF; \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[10] = a5 >> 8; \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[11] = a5 & 0xFF; \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[12] = a6 >> 8; \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[13] = a6 & 0xFF; \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[14] = a7 >> 8; \ - SOCKADDR_IN6(a).sin6_addr.s6_addr[15] = a7 & 0xFF; + a.sockaddr.in6.sin6_addr.s6_addr[0] = a0 >> 8; \ + a.sockaddr.in6.sin6_addr.s6_addr[1] = a0 & 0xFF; \ + a.sockaddr.in6.sin6_addr.s6_addr[2] = a1 >> 8; \ + a.sockaddr.in6.sin6_addr.s6_addr[3] = a1 & 0xFF; \ + a.sockaddr.in6.sin6_addr.s6_addr[4] = a2 >> 8; \ + a.sockaddr.in6.sin6_addr.s6_addr[5] = a2 & 0xFF; \ + a.sockaddr.in6.sin6_addr.s6_addr[6] = a3 >> 8; \ + a.sockaddr.in6.sin6_addr.s6_addr[7] = a3 & 0xFF; \ + a.sockaddr.in6.sin6_addr.s6_addr[8] = a4 >> 8; \ + a.sockaddr.in6.sin6_addr.s6_addr[9] = a4 & 0xFF; \ + a.sockaddr.in6.sin6_addr.s6_addr[10] = a5 >> 8; \ + a.sockaddr.in6.sin6_addr.s6_addr[11] = a5 & 0xFF; \ + a.sockaddr.in6.sin6_addr.s6_addr[12] = a6 >> 8; \ + a.sockaddr.in6.sin6_addr.s6_addr[13] = a6 & 0xFF; \ + a.sockaddr.in6.sin6_addr.s6_addr[14] = a7 >> 8; \ + a.sockaddr.in6.sin6_addr.s6_addr[15] = a7 & 0xFF; static OFString *module = @"Socket"; @implementation TestsAppDelegate (SocketTests) - (void)socketTests @@ -72,12 +70,12 @@ of_socket_address_t addr; uint16_t port; TEST(@"Parsing an IPv4", R(addr = of_socket_address_parse_ip(@"127.0.0.1", 1234)) && - OF_BSWAP32_IF_LE(SOCKADDR_IN(addr).sin_addr.s_addr) == 0x7F000001 && - OF_BSWAP16_IF_LE(SOCKADDR_IN(addr).sin_port) == 1234) + OF_BSWAP32_IF_LE(addr.sockaddr.in.sin_addr.s_addr) == 0x7F000001 && + OF_BSWAP16_IF_LE(addr.sockaddr.in.sin_port) == 1234) EXPECT_EXCEPTION(@"Refusing invalid IPv4 #1", OFInvalidFormatException, of_socket_address_parse_ip(@"127.0.0.0.1", 1234)) @@ -103,37 +101,36 @@ TEST(@"Converting an IPv4 to a string", [of_socket_address_ip_string(&addr, &port) isEqual: @"127.0.0.1"] && port == 1234) -#ifdef OF_HAVE_IPV6 TEST(@"Parsing an IPv6 #1", R(addr = of_socket_address_parse_ip( @"1122:3344:5566:7788:99aa:bbCc:ddee:ff00", 1234)) && COMPARE_V6(addr, 0x1122, 0x3344, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0xDDEE, 0xFF00) && - OF_BSWAP16_IF_LE(SOCKADDR_IN6(addr).sin6_port) == 1234) + OF_BSWAP16_IF_LE(addr.sockaddr.in6.sin6_port) == 1234) TEST(@"Parsing an IPv6 #2", R(addr = of_socket_address_parse_ip(@"::", 1234)) && COMPARE_V6(addr, 0, 0, 0, 0, 0, 0, 0, 0) && - OF_BSWAP16_IF_LE(SOCKADDR_IN6(addr).sin6_port) == 1234) + OF_BSWAP16_IF_LE(addr.sockaddr.in6.sin6_port) == 1234) TEST(@"Parsing an IPv6 #3", R(addr = of_socket_address_parse_ip(@"aaAa::bBbb", 1234)) && COMPARE_V6(addr, 0xAAAA, 0, 0, 0, 0, 0, 0, 0xBBBB) && - OF_BSWAP16_IF_LE(SOCKADDR_IN6(addr).sin6_port) == 1234) + OF_BSWAP16_IF_LE(addr.sockaddr.in6.sin6_port) == 1234) TEST(@"Parsing an IPv6 #4", R(addr = of_socket_address_parse_ip(@"aaAa::", 1234)) && COMPARE_V6(addr, 0xAAAA, 0, 0, 0, 0, 0, 0, 0) && - OF_BSWAP16_IF_LE(SOCKADDR_IN6(addr).sin6_port) == 1234) + OF_BSWAP16_IF_LE(addr.sockaddr.in6.sin6_port) == 1234) TEST(@"Parsing an IPv6 #5", R(addr = of_socket_address_parse_ip(@"::aaAa", 1234)) && COMPARE_V6(addr, 0, 0, 0, 0, 0, 0, 0, 0xAAAA) && - OF_BSWAP16_IF_LE(SOCKADDR_IN6(addr).sin6_port) == 1234) + OF_BSWAP16_IF_LE(addr.sockaddr.in6.sin6_port) == 1234) EXPECT_EXCEPTION(@"Refusing invalid IPv6 #1", OFInvalidFormatException, of_socket_address_parse_ip(@"1:::2", 1234)) @@ -228,10 +225,9 @@ SET_V6(addr, 0, 0, 0x5566, 0x7788, 0x99AA, 0xBBCC, 0, 0) TEST(@"Converting an IPv6 to a string #10", [of_socket_address_ip_string(&addr, &port) isEqual: @"::5566:7788:99aa:bbcc:0:0"] && port == 1234) -#endif [pool drain]; } @end