diff --git a/Source/Additions/NSURL+GNUstepBase.m b/Source/Additions/NSURL+GNUstepBase.m index 70c4302845..2143911851 100644 --- a/Source/Additions/NSURL+GNUstepBase.m +++ b/Source/Additions/NSURL+GNUstepBase.m @@ -87,7 +87,7 @@ - (id) initWithScheme: (NSString*)scheme if ([host length] > 0) { [urlString appendString: - [host stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]]; + [host stringByAddingPercentEncodingWithAllowedCharacters: [NSCharacterSet URLHostAllowedCharacterSet]]]; } if ([port intValue] > 0) { diff --git a/Source/GSSocketStream.h b/Source/GSSocketStream.h index d7d44f7477..4ec703949e 100644 --- a/Source/GSSocketStream.h +++ b/Source/GSSocketStream.h @@ -30,7 +30,7 @@ #import "GSNetwork.h" typedef union { - struct sockaddr s; + struct sockaddr_storage s; /* Increased memory allocation for IPv6 addresses*/ struct sockaddr_in i4; #ifdef AF_INET6 struct sockaddr_in6 i6; @@ -62,12 +62,12 @@ SOCKIVARS /** * get the sockaddr */ -- (struct sockaddr*) _address; +- (struct sockaddr_storage*) _address; /** * set the sockaddr */ -- (void) _setAddress: (struct sockaddr*)address; +- (void) _setAddress: (struct sockaddr_storage*)address; /** * setter for closing flag ... the remote end has stopped either sending @@ -119,8 +119,8 @@ SOCKIVARS SOCKIVARS @end @interface GSSocketInputStream (AddedBehaviors) -- (struct sockaddr*) _address; -- (void) _setAddress: (struct sockaddr*)address; +- (struct sockaddr_storage*) _address; +- (void) _setAddress: (struct sockaddr_storage*)address; - (NSInteger) _read: (uint8_t *)buffer maxLength: (NSUInteger)len; - (void) _setClosing: (BOOL)passive; - (void) _setHandler: (id)h; @@ -161,8 +161,8 @@ SOCKIVARS SOCKIVARS @end @interface GSSocketOutputStream (AddedBehaviors) -- (struct sockaddr*) _address; -- (void) _setAddress: (struct sockaddr*)address; +- (struct sockaddr_storage*) _address; +- (void) _setAddress: (struct sockaddr_storage*)address; - (void) _setClosing: (BOOL)passive; - (void) _setHandler: (id)h; - (void) _setPassive: (BOOL)passive; @@ -217,8 +217,8 @@ SOCKIVARS @end @interface GSSocketServerStream (AddedBehaviors) -- (struct sockaddr*) _address; -- (void) _setAddress: (struct sockaddr*)address; +- (struct sockaddr_storage*) _address; +- (void) _setAddress: (struct sockaddr_storage*)address; - (void) _setClosing: (BOOL)passive; - (void) _setHandler: (id)h; - (void) _setPassive: (BOOL)passive; diff --git a/Source/GSSocketStream.m b/Source/GSSocketStream.m index 323001fdab..2bffd9e15a 100644 --- a/Source/GSSocketStream.m +++ b/Source/GSSocketStream.m @@ -943,7 +943,7 @@ + (void) tryInput: (GSSocketInputStream*)i output: (GSSocketOutputStream*)o if (conf != nil) { GSSOCKS *h; - struct sockaddr *sa = [i _address]; + struct sockaddr_storage *sa = [i _address]; NSString *v; BOOL i6 = NO; @@ -958,15 +958,15 @@ + (void) tryInput: (GSSocketInputStream*)i output: (GSSocketOutputStream*)o } #if defined(AF_INET6) - if (sa->sa_family == AF_INET6) + if (sa->ss_family == AF_INET6) { i6 = YES; } else #endif - if (sa->sa_family != AF_INET) + if (sa->ss_family != AF_INET) { - GSOnceMLog(@"SOCKS not supported for socket type %d", sa->sa_family); + GSOnceMLog(@"SOCKS not supported for socket type %d", sa->ss_family); return; } @@ -1563,12 +1563,12 @@ - (id) init #endif _sock = INVALID_SOCKET; _handler = nil; - _address.s.sa_family = AF_UNSPEC; + _address.s.ss_family = AF_UNSPEC; } return self; } -- (struct sockaddr*) _address +- (struct sockaddr_storage*) _address { return &_address.s; } @@ -1577,7 +1577,7 @@ - (id) propertyForKey: (NSString *)key { id result = [super propertyForKey: key]; - if (result == nil && _address.s.sa_family != AF_UNSPEC) + if (result == nil && _address.s.ss_family != AF_UNSPEC) { SOCKET s = [self _sock]; sockaddr_any sin; @@ -1645,6 +1645,11 @@ - (void) _sendEvent: (NSStreamEvent)event } } +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-align" + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wincompatible-pointer-types" - (BOOL) _setSocketAddress: (NSString*)address port: (NSInteger)port family: (NSInteger)family @@ -1670,7 +1675,7 @@ - (BOOL) _setSocketAddress: (NSString*)address } else { - [self _setAddress: (struct sockaddr*)&peer]; + [self _setAddress: (struct sockaddr_storage*)&peer]; return YES; } } @@ -1693,7 +1698,7 @@ - (BOOL) _setSocketAddress: (NSString*)address } else { - [self _setAddress: (struct sockaddr*)&peer]; + [self _setAddress: (struct sockaddr_storage*)&peer]; return YES; } } @@ -1715,7 +1720,7 @@ - (BOOL) _setSocketAddress: (NSString*)address else { strncpy(peer.sun_path, c_addr, sizeof(peer.sun_path)-1); - [self _setAddress: (struct sockaddr*)&peer]; + [self _setAddress: (struct sockaddr_storage*)&peer]; return YES; } } @@ -1726,7 +1731,7 @@ - (BOOL) _setSocketAddress: (NSString*)address } } -- (void) _setAddress: (struct sockaddr*)address +- (void) _setAddress: (struct sockaddr_storage*)address { memcpy(&_address.s, address, GSPrivateSockaddrLength(address)); } @@ -1831,7 +1836,7 @@ - (void) open { [GSSOCKS tryInput: self output: _sibling]; } - s = socket(_address.s.sa_family, SOCK_STREAM, 0); + s = socket(_address.s.ss_family, SOCK_STREAM, 0); if (BADSOCKET(s)) { [self _recordError]; @@ -1849,7 +1854,7 @@ - (void) open [GSTLSHandler tryInput: self output: _sibling]; } - result = connect([self _sock], &_address.s, + result = connect([self _sock], (struct sockaddr*)&_address.s, GSPrivateSockaddrLength(&_address.s)); if (socketError(result)) { @@ -2352,7 +2357,7 @@ - (void) open { [GSSOCKS tryInput: _sibling output: self]; } - s = socket(_address.s.sa_family, SOCK_STREAM, 0); + s = socket(_address.s.ss_family, SOCK_STREAM, 0); if (BADSOCKET(s)) { [self _recordError]; @@ -2370,7 +2375,7 @@ - (void) open [GSTLSHandler tryInput: _sibling output: self]; } - result = connect([self _sock], &_address.s, + result = connect([self _sock], (struct sockaddr*)&_address.s, GSPrivateSockaddrLength(&_address.s)); if (socketError(result)) { @@ -2756,7 +2761,7 @@ - (void) open return; } - s = socket(_address.s.sa_family, SOCK_STREAM, 0); + s = socket(_address.s.ss_family, SOCK_STREAM, 0); if (BADSOCKET(s)) { [self _recordError]; @@ -2769,9 +2774,9 @@ - (void) open } #ifndef BROKEN_SO_REUSEADDR - if (_address.s.sa_family == AF_INET + if (_address.s.ss_family == AF_INET #ifdef AF_INET6 - || _address.s.sa_family == AF_INET6 + || _address.s.ss_family == AF_INET6 #endif ) { @@ -2792,7 +2797,7 @@ - (void) open #endif bindReturn = bind([self _sock], - &_address.s, GSPrivateSockaddrLength(&_address.s)); + (struct sockaddr*)&_address.s, GSPrivateSockaddrLength(&_address.s)); if (socketError(bindReturn)) { [self _recordError]; @@ -2854,11 +2859,11 @@ - (void) acceptWithInputStream: (NSInputStream **)inputStream struct { uint8_t bytes[BUFSIZ]; } __attribute__((aligned(2)))buf; - struct sockaddr *addr = (struct sockaddr*)&buf; + struct sockaddr_storage *addr = (struct sockaddr_storage*)&buf; socklen_t len = sizeof(buf); int acceptReturn; - acceptReturn = accept([self _sock], addr, (OPTLEN*)&len); + acceptReturn = accept([self _sock], (struct sockaddr*)addr, (OPTLEN*)&len); _events &= ~NSStreamEventHasBytesAvailable; if (socketError(acceptReturn)) { // test for real error @@ -2934,6 +2939,11 @@ - (void) acceptWithInputStream: (NSInputStream **)inputStream */ } +#pragma GCC diagnostic pop // cast align + +#pragma GCC diagnostic pop // incompatible pointer types... + + - (void) _dispatch { #if defined(_WIN32) diff --git a/Source/win32/NSStream.m b/Source/win32/NSStream.m index b66e78deed..eab31f7045 100644 --- a/Source/win32/NSStream.m +++ b/Source/win32/NSStream.m @@ -961,6 +961,15 @@ + (void) getStreamsToHost: (NSHost *)host #endif } + //IPv6 + if(!ins) + { + #if defined(AF_INET6) + ins = (GSSocketStream*)AUTORELEASE([[GSInet6InputStream alloc] initToAddr: address port: port]); + outs = (GSSocketStream*)AUTORELEASE([[GSInet6OutputStream alloc] initToAddr: address port: port]); + #endif + } + /* * Windows only permits a single event to be associated with a socket * at any time, but the runloop system only allows an event handle to diff --git a/Tests/base/NSStream/ipv6test.m b/Tests/base/NSStream/ipv6test.m new file mode 100644 index 0000000000..be6757a410 --- /dev/null +++ b/Tests/base/NSStream/ipv6test.m @@ -0,0 +1,84 @@ +#if defined(GNUSTEP_BASE_LIBRARY) +/** + * This test tests IPv6 using NSStream + */ +#import +#import "Testing.h" + +@interface IPV6Server : NSObject + +- (void) main; + +@end + +@implementation IPV6Server + +- (void) main +{ +} + +@end + +int main() +{ + NSAutoreleasePool *arp = [NSAutoreleasePool new]; + + NSInputStream *inputStream; + NSOutputStream *outputStream; + IPV6Server *svr = [[IPV6Server alloc] init]; + + NSString *ipv6ServerAddress = @"::1"; // Replace with your actual IPv6 server address + uint16_t port = 12345; // Replace with the actual port number + + // Resolve the IPv6 address using NSHost + NSHost *host = [NSHost hostWithName: ipv6ServerAddress]; + NSArray *addresses = [host addresses]; + + PASS([addresses count] > 0, "Resolve IPv6 address"); + + NSString *ipv6Address = [addresses objectAtIndex: 0]; + NSThread *thread = [[NSThread alloc] initWithTarget: svr selector: @selector(main) object: nil]; + + PASS(thread != nil, "Created thread for server"); + + [thread start]; + + [NSStream getStreamsToHost: [NSHost hostWithName: ipv6Address] + port: port + inputStream: &inputStream + outputStream: &outputStream]; + + [inputStream open]; + [outputStream open]; + + // Perform your tests here to validate the IPv6 stream + // You can write and read data from the stream and assert the expected results + // For example: + + NSString *testData = @"Test Data"; + NSData *dataToWrite = [testData dataUsingEncoding:NSUTF8StringEncoding]; + NSInteger bytesWritten = [outputStream write: [dataToWrite bytes] maxLength: [dataToWrite length]]; + + PASS(bytesWritten > 0, "Write data to the stream"); + + uint8_t buffer[1024]; + NSInteger bytesRead = [inputStream read:buffer maxLength:1024]; + NSString *receivedString = [[NSString alloc] initWithBytes:buffer length:bytesRead encoding:NSUTF8StringEncoding]; + + PASS(bytesRead > 0, "Read data from the stream"); + PASS([receivedString isEqualToString: testData], "Received data matches the expected data"); + + [inputStream close]; + [outputStream close]; + + [arp release]; + arp = nil; + + return 0; +} +#else +int main() +{ + return 0; +} +#endif diff --git a/base.xcodeproj/project.pbxproj b/base.xcodeproj/project.pbxproj index a2b66c3642..72908ac6de 100644 --- a/base.xcodeproj/project.pbxproj +++ b/base.xcodeproj/project.pbxproj @@ -4062,6 +4062,7 @@ ); INFOPLIST_FILE = "Support/Foundation/Foundation-Info.plist"; LIBRARY_SEARCH_PATHS = /opt/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.14; OTHER_CFLAGS = ( "-DGNUSTEP", "-DNeXT_RUNTIME", @@ -4100,6 +4101,7 @@ ); INFOPLIST_FILE = "Support/Foundation/Foundation-Info.plist"; LIBRARY_SEARCH_PATHS = /opt/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.14; OTHER_CFLAGS = ( "-DGNUSTEP", "-DNeXT_RUNTIME",