Provisional IPv6 support added.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@33933 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2011-10-03 16:03:19 +00:00
parent 2a419593ce
commit afc6974925
11 changed files with 369 additions and 361 deletions

View file

@ -1,3 +1,17 @@
2011-10-03 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSHost.m: Update to use inet_pton() and inet_ntop() and to
understand IPV6 addresses.
* Source/GSNetwork.h: New private functions to work with the internals
of a sockaddr irrespective of whether it's IP v4 or v6
* Source/GSSocketStream.h: Move a declaration to GSNetwork.h
* Source/GSSocketStream.m: Use new functions.
* Source/NSSocketPort.m: Change to be IP v4/v6 agnostic
* Source/NSMessagePort.m: Fix header include order.
* Source/GSFileHandle.m: Changes to be IP v4/v6 agnostic
* Headers/GNUstepBase/GSFileHandle.h: make setter use sockaddr type
rather than sockaddr_in so we can use it for ipv6
2011-10-03 Fred Kiefer <FredKiefer@gmx.de>
* Source/NSData.m (-initWithCoder:, -encodeWithCoder): Correct

View file

@ -106,7 +106,7 @@ struct sockaddr_in;
type: (RunLoopEventType)type
extra: (void*)extra
forMode: (NSString*)mode;
- (void) setAddr: (struct sockaddr_in *)sin;
- (void) setAddr: (struct sockaddr *)sin;
- (BOOL) useCompression;
- (void) watchReadDescriptorForModes: (NSArray*)modes;
- (void) watchWriteDescriptor;

View file

@ -39,8 +39,8 @@
#import "Foundation/NSByteOrder.h"
#import "Foundation/NSProcessInfo.h"
#import "Foundation/NSUserDefaults.h"
#import "GSNetwork.h"
#import "GSPrivate.h"
#import "GSNetwork.h"
#import "GNUstepBase/NSObject+GNUstepBase.h"
#import "../Tools/gdomap.h"
@ -98,6 +98,171 @@ static GSFileHandle* fh_stderr = nil;
// Key to info dictionary for operation mode.
static NSString* NotificationKey = @"NSFileHandleNotificationKey";
NSString *
GSPrivateSockaddrHost(struct sockaddr *addr)
{
char buf[40];
#if defined(AF_INET6)
if (AF_INET6 == addr->sa_family)
{
struct sockaddr_in6 *addr6 = (struct sockaddr_in6*)addr;
inet_ntop(AF_INET, &addr6->sin6_addr, buf, sizeof(buf));
return [NSString stringWithUTF8String: buf];
}
#endif
inet_ntop(AF_INET, &((struct sockaddr_in*)addr)->sin_addr, buf, sizeof(buf));
return [NSString stringWithUTF8String: buf];
}
NSString *
GSPrivateSockaddrName(struct sockaddr *addr)
{
return [NSString stringWithFormat: @"%@:%d",
GSPrivateSockaddrHost(addr),
GSPrivateSockaddrPort(addr)];
}
uint16_t
GSPrivateSockaddrPort(struct sockaddr *addr)
{
uint16_t port;
#if defined(AF_INET6)
if (AF_INET6 == addr->sa_family)
{
struct sockaddr_in6 *addr6 = (struct sockaddr_in6*)addr;
port = addr6->sin6_port;
port = GSSwapBigI16ToHost(port);
return port;
}
#endif
port = ((struct sockaddr_in*)addr)->sin_port;
port = GSSwapBigI16ToHost(port);
return port;
}
BOOL
GSPrivateSockaddrSetup(NSString *machine, uint16_t port,
NSString *service, NSString *protocol, struct sockaddr *sin)
{
memset(sin, '\0', sizeof(*sin));
sin->sa_family = AF_INET;
/* If we were given a hostname, we use any address for that host.
* Otherwise we expect the given name to be an address unless it is
* a null (any address).
*/
if (0 != [machine length])
{
const char *n;
n = [machine UTF8String];
if ((!isdigit(n[0]) || sscanf(n, "%*d.%*d.%*d.%*d") != 4)
&& 0 == strchr(n, ':'))
{
machine = [[NSHost hostWithName: machine] address];
n = [machine UTF8String];
}
if (0 == strchr(n, ':'))
{
struct sockaddr_in *addr = (struct sockaddr_in*)sin;
if (inet_pton(AF_INET, n, &addr->sin_addr) <= 0)
{
return NO;
}
}
else
{
#if defined(AF_INET6)
struct sockaddr_in6 *addr6 = (struct sockaddr_in6*)sin;
sin->sa_family = AF_INET6;
if (inet_pton(AF_INET6, n, &addr6->sin6_addr) <= 0)
{
return NO;
}
#else
return NO;
#endif
}
}
else
{
((struct sockaddr_in*)sin)->sin_addr.s_addr
= GSSwapHostI32ToBig(INADDR_ANY);
}
/* The optional service and protocol parameters may be used to
* look up the port
*/
if (nil != service)
{
const char *sname;
const char *proto;
struct servent *sp;
if (nil == protocol)
{
proto = "tcp";
}
else
{
proto = [protocol UTF8String];
}
sname = [service UTF8String];
if ((sp = getservbyname(sname, proto)) == 0)
{
const char* ptr = sname;
int val = atoi(ptr);
while (isdigit(*ptr))
{
ptr++;
}
if (*ptr == '\0' && val <= 0xffff)
{
port = val;
}
else if (strcmp(ptr, "gdomap") == 0)
{
#ifdef GDOMAP_PORT_OVERRIDE
port = GDOMAP_PORT_OVERRIDE;
#else
port = 538; // IANA allocated port
#endif
}
else
{
return NO;
}
}
else
{
port = GSSwapBigI16ToHost(sp->s_port);
}
}
#if defined(AF_INET6)
if (AF_INET6 == sin->sa_family)
{
((struct sockaddr_in6*)sin)->sin6_port = GSSwapHostI16ToBig(port);
}
else
{
((struct sockaddr_in*)sin)->sin_port = GSSwapHostI16ToBig(port);
}
#else
((struct sockaddr_ind*)sin)->sin6_port = GSSwapHostI16ToBig(port);
#endif
return YES;
}
@interface GSFileHandle(private)
- (void) receivedEventRead;
- (void) receivedEventWrite;
@ -153,90 +318,6 @@ static NSString* NotificationKey = @"NSFileHandleNotificationKey";
return len;
}
static BOOL
getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin)
{
const char *proto = "tcp";
struct servent *sp;
if (pcl)
{
proto = [pcl lossyCString];
}
memset(sin, '\0', sizeof(*sin));
sin->sin_family = AF_INET;
/*
* If we were given a hostname, we use any address for that host.
* Otherwise we expect the given name to be an address unless it is
* a null (any address).
*/
if (name)
{
NSHost* host = [NSHost hostWithName: name];
if (host != nil)
{
name = [host address];
}
#ifndef HAVE_INET_ATON
sin->sin_addr.s_addr = inet_addr([name lossyCString]);
if (sin->sin_addr.s_addr == INADDR_NONE)
#else
if (inet_aton([name lossyCString], &sin->sin_addr) == 0)
#endif
{
return NO;
}
}
else
{
sin->sin_addr.s_addr = GSSwapHostI32ToBig(INADDR_ANY);
}
if (svc == nil)
{
sin->sin_port = 0;
return YES;
}
else if ((sp = getservbyname([svc lossyCString], proto)) == 0)
{
const char* ptr = [svc lossyCString];
int val = atoi(ptr);
while (isdigit(*ptr))
{
ptr++;
}
if (*ptr == '\0' && val <= 0xffff)
{
uint16_t v = val;
sin->sin_port = GSSwapHostI16ToBig(v);
return YES;
}
else if (strcmp(ptr, "gdomap") == 0)
{
uint16_t v;
#ifdef GDOMAP_PORT_OVERRIDE
v = GDOMAP_PORT_OVERRIDE;
#else
v = 538; // IANA allocated port
#endif
sin->sin_port = GSSwapHostI16ToBig(v);
return YES;
}
else
{
return NO;
}
}
else
{
sin->sin_port = sp->s_port;
return YES;
}
}
+ (id) allocWithZone: (NSZone*)z
{
return NSAllocateObject ([self class], 0, z);
@ -664,8 +745,8 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
static NSString *dsocks = nil;
static BOOL beenHere = NO;
int net;
struct sockaddr_in sin;
struct sockaddr_in lsin;
struct sockaddr sin;
struct sockaddr lsin;
NSString *lhost = nil;
NSString *shost = nil;
NSString *sport = nil;
@ -718,7 +799,7 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
{
p = nil;
}
if (getAddr(lhost, p, @"tcp", &lsin) == NO)
if (GSPrivateSockaddrSetup(lhost, 0, p, @"tcp", &lsin) == NO)
{
NSLog(@"bad bind address specification");
DESTROY(self);
@ -765,7 +846,7 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
p = @"tcp";
}
if (getAddr(a, s, p, &sin) == NO)
if (GSPrivateSockaddrSetup(a, 0, s, p, &sin) == NO)
{
DESTROY(self);
NSLog(@"bad address-service-protocol combination");
@ -788,7 +869,7 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
}
if (shost != nil)
{
if (getAddr(shost, sport, p, &sin) == NO)
if (GSPrivateSockaddrSetup(shost, 0, sport, p, &sin) == NO)
{
NSLog(@"bad SOCKS host-port combination");
DESTROY(self);
@ -796,7 +877,7 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
}
}
if ((net = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) == -1)
if ((net = socket(sin.sa_family, SOCK_STREAM, PF_UNSPEC)) == -1)
{
NSLog(@"unable to create socket - %@", [NSError _last]);
DESTROY(self);
@ -810,10 +891,10 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
if (lhost != nil)
{
if (bind(net, (struct sockaddr *)&lsin, sizeof(lsin)) == -1)
if (bind(net, &lsin, GSPrivateSockaddrLength(&lsin)) == -1)
{
NSLog(@"unable to bind to port %s:%d - %@", inet_ntoa(lsin.sin_addr),
GSSwapBigI16ToHost(sin.sin_port), [NSError _last]);
NSLog(@"unable to bind to port %@ - %@",
GSPrivateSockaddrName(&lsin), [NSError _last]);
(void) close(net);
DESTROY(self);
return nil;
@ -827,13 +908,12 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
isSocket = YES;
[self setNonBlocking: YES];
if (connect(net, (struct sockaddr*)&sin, sizeof(sin)) == -1)
if (connect(net, &sin, GSPrivateSockaddrLength(&sin)) == -1)
{
if (errno != EINPROGRESS)
{
NSLog(@"unable to make connection to %s:%d - %@",
inet_ntoa(sin.sin_addr),
GSSwapBigI16ToHost(sin.sin_port), [NSError _last]);
NSLog(@"unable to make connection to %@ - %@",
GSPrivateSockaddrName(&sin), [NSError _last]);
DESTROY(self);
return nil;
}
@ -885,17 +965,17 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
int status = 1;
#endif
int net;
struct sockaddr_in sin;
struct sockaddr sin;
unsigned int size = sizeof(sin);
if (getAddr(a, s, p, &sin) == NO)
if (GSPrivateSockaddrSetup(a, 0, s, p, &sin) == NO)
{
DESTROY(self);
NSLog(@"bad address-service-protocol combination");
return nil;
}
if ((net = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) == -1)
if ((net = socket(sin.sa_family, SOCK_STREAM, PF_UNSPEC)) == -1)
{
NSLog(@"unable to create socket - %@", [NSError _last]);
DESTROY(self);
@ -912,10 +992,10 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
setsockopt(net, SOL_SOCKET, SO_REUSEADDR, (char *)&status, sizeof(status));
#endif
if (bind(net, (struct sockaddr *)&sin, sizeof(sin)) == -1)
if (bind(net, &sin, GSPrivateSockaddrLength(&sin)) == -1)
{
NSLog(@"unable to bind to port %s:%d - %@", inet_ntoa(sin.sin_addr),
GSSwapBigI16ToHost(sin.sin_port), [NSError _last]);
NSLog(@"unable to bind to port %@ - %@",
GSPrivateSockaddrName(&sin), [NSError _last]);
(void) close(net);
DESTROY(self);
return nil;
@ -931,7 +1011,7 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
return nil;
}
if (getsockname(net, (struct sockaddr*)&sin, &size) == -1)
if (getsockname(net, &sin, &size) == -1)
{
NSLog(@"unable to get socket name - %@", [NSError _last]);
(void) close(net);
@ -1917,11 +1997,11 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
operation = [readInfo objectForKey: NotificationKey];
if (operation == NSFileHandleConnectionAcceptedNotification)
{
struct sockaddr_in buf;
struct sockaddr buf;
int desc;
unsigned int blen = sizeof(buf);
desc = accept(descriptor, (struct sockaddr*)&buf, &blen);
desc = accept(descriptor, &buf, &blen);
if (desc == -1)
{
NSString *s;
@ -1933,7 +2013,7 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
else
{ // Accept attempt completed.
GSFileHandle *h;
struct sockaddr_in sin;
struct sockaddr sin;
unsigned int size = sizeof(sin);
int status;
@ -1947,7 +2027,7 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
h = [[[self class] alloc] initWithFileDescriptor: desc
closeOnDealloc: YES];
h->isSocket = YES;
getpeername(desc, (struct sockaddr*)&sin, &size);
getpeername(desc, &sin, &size);
[h setAddr: &sin];
[readInfo setObject: h
forKey: NSFileHandleNotificationFileHandleItem];
@ -2111,11 +2191,13 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
}
}
- (void) setAddr: (struct sockaddr_in *)sin
- (void) setAddr: (struct sockaddr *)sin
{
address = [[NSString alloc] initWithCString: (char*)inet_ntoa(sin->sin_addr)];
service = [[NSString alloc] initWithFormat: @"%d",
(int)GSSwapBigI16ToHost(sin->sin_port)];
NSString *s;
ASSIGN(address, GSPrivateSockaddrHost(sin));
s = [NSString stringWithFormat: @"%d", GSPrivateSockaddrPort(sin)];
ASSIGN(service, s);
protocol = @"tcp";
}
@ -2173,16 +2255,16 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
- (NSString*) socketLocalAddress
{
NSString *str = nil;
struct sockaddr_in sin = { 0 };
struct sockaddr sin;
unsigned size = sizeof(sin);
if (getsockname(descriptor, (struct sockaddr*)&sin, &size) == -1)
if (getsockname(descriptor, &sin, &size) == -1)
{
NSLog(@"unable to get socket name - %@", [NSError _last]);
}
else
{
str = [NSString stringWithUTF8String: (char*)inet_ntoa(sin.sin_addr)];
str = GSPrivateSockaddrHost(&sin);
}
return str;
}
@ -2190,17 +2272,16 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
- (NSString*) socketLocalService
{
NSString *str = nil;
struct sockaddr_in sin = { 0 };
struct sockaddr sin;
unsigned size = sizeof(sin);
if (getsockname(descriptor, (struct sockaddr*)&sin, &size) == -1)
if (getsockname(descriptor, &sin, &size) == -1)
{
NSLog(@"unable to get socket name - %@", [NSError _last]);
}
else
{
str = [NSString stringWithFormat: @"%d",
(int)GSSwapBigI16ToHost(sin.sin_port)];
str = [NSString stringWithFormat: @"%d", GSPrivateSockaddrPort(&sin)];
}
return str;
}

View file

@ -95,4 +95,20 @@
# endif
#endif
NSString*
GSPrivateSockaddrHost(struct sockaddr *addr) GS_ATTRIB_PRIVATE;
unsigned
GSPrivateSockaddrLength(struct sockaddr *addr) GS_ATTRIB_PRIVATE;
NSString*
GSPrivateSockaddrName(struct sockaddr *addr) GS_ATTRIB_PRIVATE;
uint16_t
GSPrivateSockaddrPort(struct sockaddr *addr) GS_ATTRIB_PRIVATE;
BOOL
GSPrivateSockaddrSetup(NSString *machine, uint16_t port, NSString *service,
NSString *protocol, struct sockaddr *sin) GS_ATTRIB_PRIVATE;
#endif

View file

@ -29,9 +29,6 @@
#include "GSNetwork.h"
unsigned
GSPrivateSockaddrLength(struct sockaddr *addr) GS_ATTRIB_PRIVATE;
typedef union {
struct sockaddr s;
struct sockaddr_in i4;

View file

@ -1321,103 +1321,40 @@ setNonBlocking(SOCKET fd)
if (result == nil && _address.s.sa_family != AF_UNSPEC)
{
SOCKET s = [self _sock];
SOCKET s = [self _sock];
struct sockaddr sin;
socklen_t size = sizeof(sin);
switch (_address.s.sa_family)
{
case AF_INET:
{
struct sockaddr_in sin = { 0 };
socklen_t size = sizeof(sin);
if ([key isEqualToString: GSStreamLocalAddressKey])
{
if (getsockname(s, (struct sockaddr*)&sin, &size) != -1)
{
result = [NSString stringWithUTF8String:
(char*)inet_ntoa(sin.sin_addr)];
}
}
else if ([key isEqualToString: GSStreamLocalPortKey])
{
if (getsockname(s, (struct sockaddr*)&sin, &size) != -1)
{
result = [NSString stringWithFormat: @"%d",
(int)GSSwapBigI16ToHost(sin.sin_port)];
}
}
else if ([key isEqualToString: GSStreamRemoteAddressKey])
{
if (getpeername(s, (struct sockaddr*)&sin, &size) != -1)
{
result = [NSString stringWithUTF8String:
(char*)inet_ntoa(sin.sin_addr)];
}
}
else if ([key isEqualToString: GSStreamRemotePortKey])
{
if (getpeername(s, (struct sockaddr*)&sin, &size) != -1)
{
result = [NSString stringWithFormat: @"%d",
(int)GSSwapBigI16ToHost(sin.sin_port)];
}
}
}
break;
#if defined(AF_INET6)
case AF_INET6:
{
struct sockaddr_in6 sin = { 0 };
socklen_t size = sizeof(sin);
if ([key isEqualToString: GSStreamLocalAddressKey])
{
if (getsockname(s, (struct sockaddr*)&sin, &size) != -1)
{
char buf[INET6_ADDRSTRLEN+1];
if (inet_ntop(AF_INET6, &(sin.sin6_addr), buf,
INET6_ADDRSTRLEN) == 0)
{
buf[INET6_ADDRSTRLEN] = '\0';
result = [NSString stringWithUTF8String: buf];
}
}
}
else if ([key isEqualToString: GSStreamLocalPortKey])
{
if (getsockname(s, (struct sockaddr*)&sin, &size) != -1)
{
result = [NSString stringWithFormat: @"%d",
(int)GSSwapBigI16ToHost(sin.sin6_port)];
}
}
else if ([key isEqualToString: GSStreamRemoteAddressKey])
{
if (getpeername(s, (struct sockaddr*)&sin, &size) != -1)
{
char buf[INET6_ADDRSTRLEN+1];
if (inet_ntop(AF_INET6, &(sin.sin6_addr), buf,
INET6_ADDRSTRLEN) == 0)
{
buf[INET6_ADDRSTRLEN] = '\0';
result = [NSString stringWithUTF8String: buf];
}
}
}
else if ([key isEqualToString: GSStreamRemotePortKey])
{
if (getpeername(s, (struct sockaddr*)&sin, &size) != -1)
{
result = [NSString stringWithFormat: @"%d",
(int)GSSwapBigI16ToHost(sin.sin6_port)];
}
}
}
break;
#endif
}
if ([key isEqualToString: GSStreamLocalAddressKey])
{
if (getsockname(s, (struct sockaddr*)&sin, &size) != -1)
{
result = GSPrivateSockaddrHost(&sin);
}
}
else if ([key isEqualToString: GSStreamLocalPortKey])
{
if (getsockname(s, (struct sockaddr*)&sin, &size) != -1)
{
result = [NSString stringWithFormat: @"%d",
(int)GSPrivateSockaddrPort(&sin)];
}
}
else if ([key isEqualToString: GSStreamRemoteAddressKey])
{
if (getpeername(s, (struct sockaddr*)&sin, &size) != -1)
{
result = GSPrivateSockaddrHost(&sin);
}
}
else if ([key isEqualToString: GSStreamRemotePortKey])
{
if (getpeername(s, (struct sockaddr*)&sin, &size) != -1)
{
result = [NSString stringWithFormat: @"%d",
(int)GSPrivateSockaddrPort(&sin)];
}
}
}
return result;
}
@ -1470,7 +1407,7 @@ setNonBlocking(SOCKET fd)
peer.sin_family = AF_INET;
peer.sin_port = GSSwapHostI16ToBig(p);
ptonReturn = inet_pton(AF_INET, addr_c, &peer.sin_addr);
if (ptonReturn == 0) // error
if (ptonReturn <= 0) // error
{
return NO;
}
@ -1493,7 +1430,7 @@ setNonBlocking(SOCKET fd)
peer.sin6_family = AF_INET6;
peer.sin6_port = GSSwapHostI16ToBig(p);
ptonReturn = inet_pton(AF_INET6, addr_c, &peer.sin6_addr);
if (ptonReturn == 0) // error
if (ptonReturn <= 0) // error
{
return NO;
}

View file

@ -63,7 +63,6 @@ static NSMutableDictionary *_hostCache = nil;
@interface NSHost (Private)
- (void) _addName: (NSString*)name;
+ (struct hostent*) _entryForAddress: (NSString*)address;
- (id) _initWithHostEntry: (struct hostent*)entry key: (NSString*)key;
+ (NSMutableSet*) _localAddresses;
@end
@ -85,36 +84,6 @@ static NSMutableDictionary *_hostCache = nil;
RELEASE(name);
}
+ (struct hostent*) _entryForAddress: (NSString*)address
{
struct hostent *h = 0;
struct in_addr hostaddr;
#ifndef HAVE_INET_ATON
hostaddr.s_addr = inet_addr([address UTF8String]);
if (hostaddr.s_addr == INADDR_NONE)
{
NSLog(@"Attempt to lookup host entry for bad IP address (%@)", address);
}
#else
if (inet_aton([address UTF8String], (struct in_addr*)&hostaddr.s_addr) == 0)
{
NSLog(@"Attempt to lookup host entry for bad IP address (%@)", address);
}
#endif
else
{
h = gethostbyaddr((char*)&hostaddr, sizeof(hostaddr), AF_INET);
if (h == 0)
{
NSDebugLog(@"Host '%@' not found using 'gethostbyaddr()' - perhaps "
@"the address is wrong, networking is not set up on your machine,"
@" or the requested address lacks a reverse-dns entry.", address);
}
}
return h;
}
- (id) _initWithAddress: (NSString*)name
{
if ((self = [super init]) == nil)
@ -187,7 +156,7 @@ static NSMutableDictionary *_hostCache = nil;
{
NSString *a = [extra anyObject];
entry = [hostClass _entryForAddress: a];
entry = gethostbyname([a UTF8String]);
if (entry == 0)
{
/*
@ -306,8 +275,8 @@ myHostName()
+ (NSHost*) hostWithName: (NSString*)name
{
BOOL tryByAddress = NO;
NSHost *host = nil;
const char *n;
if (name == nil)
{
@ -320,6 +289,16 @@ myHostName()
return nil;
}
/* If this looks like an address rather than a host name ...
* call the correct method instead of this one.
*/
n = [name UTF8String];
if ((isdigit(n[0]) && sscanf(n, "%*d.%*d.%*d.%*d") == 4)
|| 0 != strchr(n, ':'))
{
return [self hostWithAddress: name];
}
[_hostCacheLock lock];
if (_hostCacheEnabled == YES)
{
@ -338,15 +317,10 @@ myHostName()
}
else
{
struct hostent *h = 0;
const char *n = [name UTF8String];
struct hostent *h;
h = gethostbyname((char*)n);
if (h == 0 && sscanf(n, "%*d.%*d.%*d.%*d") == 4)
{
tryByAddress = YES;
}
else if (h == 0)
if (0 == h)
{
if ([name isEqualToString: myHostName()] == YES)
{
@ -377,61 +351,79 @@ myHostName()
IF_NO_GC([[host retain] autorelease];)
}
[_hostCacheLock unlock];
if (tryByAddress == YES)
{
return [self hostWithAddress: name];
}
return host;
}
+ (NSHost*) hostWithAddress: (NSString*)address
{
NSHost *host = nil;
NSHost *host = nil;
char buf[40];
const char *a;
if (address == nil)
{
NSLog(@"Nil host address sent to [NSHost +hostWithAddress:]");
return nil;
}
if ([address isEqual: @""] == YES)
a = [address UTF8String];
if (0 == a || '\0' == *a)
{
NSLog(@"Empty host address sent to [NSHost +hostWithAddress:]");
return nil;
}
/* Now check that the address is of valid format, and standardise it
* by converting from characters to binary and back.
*/
if (0 == strchr(a, ':'))
{
struct in_addr hostaddr;
if (inet_pton(AF_INET, a, (void*)&hostaddr) <= 0)
{
NSLog(@"Invalid host address sent to [NSHost +hostWithAddress:]");
return nil;
}
inet_ntop(AF_INET, (void*)&hostaddr, buf, sizeof(buf));
a = buf;
address = [NSString stringWithUTF8String: a];
}
else
#if defined(AF_INET6)
{
struct in6_addr hostaddr6;
if (inet_pton(AF_INET6, a, (void*)&hostaddr6) <= 0)
{
NSLog(@"Invalid host address sent to [NSHost +hostWithAddress:]");
return nil;
}
inet_ntop(AF_INET6, (void*)&hostaddr6, buf, sizeof(buf));
a = buf;
address = [NSString stringWithUTF8String: a];
}
#else
NSLog(@"Unsupported host address sent to [NSHost +hostWithAddress:]");
return nil;
#endif
[_hostCacheLock lock];
if (_hostCacheEnabled == YES)
{
host = [_hostCache objectForKey: address];
}
if (host == nil)
if (nil == host)
{
struct hostent *h;
h = [self _entryForAddress: address];
if (h == 0)
/* The gethostbyname() function should handle names, ipv4 addresses,
* and ipv6 addresses ... so we can use it whatever we have.
*/
h = gethostbyname(a);
if (0 == h)
{
struct in_addr hostaddr;
BOOL badAddr = NO;
#ifndef HAVE_INET_ATON
hostaddr.s_addr = inet_addr([address UTF8String]);
if (hostaddr.s_addr == INADDR_NONE)
{
badAddr = YES;
}
#else
if (inet_aton([address UTF8String],
(struct in_addr*)&hostaddr.s_addr) == 0)
{
badAddr = YES;
}
#endif
if (badAddr == NO)
{
host = [[self alloc] _initWithAddress: address];
IF_NO_GC([host autorelease];)
}
host = [[self alloc] _initWithAddress: address];
IF_NO_GC([host autorelease];)
}
else
{

View file

@ -44,8 +44,8 @@
#import "Foundation/NSFileManager.h"
#import "Foundation/NSProcessInfo.h"
#import "GSNetwork.h"
#import "GSPrivate.h"
#import "GSNetwork.h"
#import "GSPortPrivate.h"
#include <stdio.h>

View file

@ -43,9 +43,9 @@
#import "Foundation/NSThread.h"
#import "Foundation/NSConnection.h"
#import "GSNetwork.h"
#import "GSPortPrivate.h"
#import "GSPrivate.h"
#import "GSNetwork.h"
#include <stdio.h>
#ifdef HAVE_UNISTD_H
@ -216,7 +216,7 @@ typedef enum {
BOOL valid;
NSSocketPort *recvPort;
NSSocketPort *sendPort;
struct sockaddr_in sockAddr; /* Far end of connection. */
struct sockaddr sockAddr; /* Far end of connection. */
NSString *defaultAddress;
}
@ -502,7 +502,7 @@ static Class runLoopClass;
}
while (gotAddr == NO)
{
const char *addr;
NSString *addr;
if (addrNum >= [addrs count])
{
@ -511,18 +511,12 @@ static Class runLoopClass;
M_UNLOCK(myLock);
return NO;
}
addr = [[addrs objectAtIndex: addrNum++] cString];
addr = [addrs objectAtIndex: addrNum++];
memset(&sockAddr, '\0', sizeof(sockAddr));
sockAddr.sin_family = AF_INET;
#ifndef HAVE_INET_ATON
sockAddr.sin_addr.s_addr = inet_addr(addr);
if (sockAddr.sin_addr.s_addr == INADDR_NONE)
#else
if (inet_aton(addr, &sockAddr.sin_addr) == 0)
#endif
if (NO == GSPrivateSockaddrSetup(addr,
[aPort portNumber], nil, nil, &sockAddr))
{
NSLog(@"bad ip address - '%s'", addr);
NSLog(@"bad address - '%s'", addr);
}
else
{
@ -531,10 +525,9 @@ static Class runLoopClass;
addr, [aPort portNumber], desc);
}
}
sockAddr.sin_port = GSSwapHostI16ToBig([aPort portNumber]);
if (connect(desc, (struct sockaddr*)&sockAddr, sizeof(sockAddr))
== SOCKET_ERROR)
if (connect(desc, (struct sockaddr*)&sockAddr,
GSPrivateSockaddrLength(&sockAddr)) == SOCKET_ERROR)
{
#ifdef __MINGW__
if (WSAGetLastError() != WSAEWOULDBLOCK)
@ -542,9 +535,8 @@ static Class runLoopClass;
if (errno != EINPROGRESS)
#endif
{
NSLog(@"unable to make connection to %s:%d - %@",
inet_ntoa(sockAddr.sin_addr),
GSSwapBigI16ToHost(sockAddr.sin_port), [NSError _last]);
NSLog(@"unable to make connection to %d - %@",
GSPrivateSockaddrName(&sockAddr), [NSError _last]);
if (addrNum < [addrs count])
{
BOOL result;
@ -684,7 +676,7 @@ static Class runLoopClass;
- (NSString*) description
{
return [NSString stringWithFormat: @"Handle (%d) to %s:%d",
desc, inet_ntoa(sockAddr.sin_addr), ntohs(sockAddr.sin_port)];
desc, GSPrivateSockaddrName(&sockAddr)];
}
- (int) descriptor
@ -1118,9 +1110,7 @@ static Class runLoopClass;
len = send(desc, [d bytes], [d length], 0);
if (len == (int)[d length])
{
RELEASE(defaultAddress);
defaultAddress = RETAIN([NSString stringWithUTF8String:
inet_ntoa(sockAddr.sin_addr)]);
ASSIGN(defaultAddress, GSPrivateSockaddrHost(&sockAddr));
NSDebugMLLog(@"GSTcpHandle",
@"wrote %d bytes on 0x%x", len, self);
state = GS_H_CONNECTED;
@ -1596,43 +1586,19 @@ static Class tcpPortClass;
#endif
SOCKET desc;
BOOL addrOk = YES;
struct sockaddr_in sockaddr;
struct sockaddr sockaddr;
/*
* Creating a new port on the local host - so we must create a
* listener socket to accept incoming connections.
*/
memset(&sockaddr, '\0', sizeof(sockaddr));
sockaddr.sin_family = AF_INET;
if (addr == nil)
{
sockaddr.sin_addr.s_addr = GSSwapHostI32ToBig(INADDR_ANY);
}
else
{
#ifndef HAVE_INET_ATON
sockaddr.sin_addr.s_addr = inet_addr([addr cString]);
if (sockaddr.sin_addr.s_addr == INADDR_NONE)
#else
if (inet_aton([addr cString], &sockaddr.sin_addr) == 0)
#endif
{
addrOk = NO;
}
}
sockaddr.sin_port = GSSwapHostI16ToBig(number);
/*
* Need size of buffer for getsockbyname() later.
*/
slen = sizeof(sockaddr);
if (addrOk == NO)
addrOk = GSPrivateSockaddrSetup(addr, number, nil, nil, &sockaddr);
if (NO == addrOk)
{
NSLog(@"Bad address (%@) specified for listening port", addr);
DESTROY(port);
}
else if ((desc = socket(AF_INET, SOCK_STREAM, PF_UNSPEC))
else if ((desc = socket(sockaddr.sa_family, SOCK_STREAM, PF_UNSPEC))
== INVALID_SOCKET)
{
NSLog(@"unable to create socket - %@", [NSError _last]);
@ -1654,11 +1620,11 @@ static Class tcpPortClass;
DESTROY(port);
}
#endif
else if (bind(desc, (struct sockaddr *)&sockaddr,
sizeof(sockaddr)) == SOCKET_ERROR)
else if (bind(desc, &sockaddr,
GSPrivateSockaddrLength(&sockaddr)) == SOCKET_ERROR)
{
NSLog(@"unable to bind to port %s:%d - %@",
inet_ntoa(sockaddr.sin_addr), number, [NSError _last]);
NSLog(@"unable to bind to port %@ - %@",
GSPrivateSockaddrName(&sockaddr), [NSError _last]);
(void) close(desc);
DESTROY(port);
}
@ -1686,7 +1652,7 @@ static Class tcpPortClass;
* we did the 'bind' call.
*/
port->listener = desc;
port->portNum = GSSwapBigI16ToHost(sockaddr.sin_port);
port->portNum = GSPrivateSockaddrPort(&sockaddr);
#if defined(__MINGW__)
port->eventListener = (WSAEVENT)CreateEvent(NULL,NO,NO,NULL);
if (port->eventListener == WSA_INVALID_EVENT)
@ -2147,7 +2113,7 @@ static Class tcpPortClass;
if (desc == listener)
#endif
{
struct sockaddr_in sockAddr;
struct sockaddr sockAddr;
socklen_t size = sizeof(sockAddr);
desc = accept(listener, (struct sockaddr*)&sockAddr, &size);
@ -2172,8 +2138,7 @@ static Class tcpPortClass;
*/
handle = [GSTcpHandle handleWithDescriptor: desc];
memcpy(&handle->sockAddr, &sockAddr, sizeof(sockAddr));
handle->defaultAddress = RETAIN([NSString stringWithUTF8String:
inet_ntoa(sockAddr.sin_addr)]);
ASSIGN(handle->defaultAddress, GSPrivateSockaddrHost(&sockAddr));
[handle setState: GS_H_ACCEPT];
[self addHandle: handle forSend: NO];

View file

@ -1,3 +1,6 @@
ObjectiveC2.framework implements the new Apple runtime APIs, introduced with OS X 10.5 on top of the GCC Objective-C runtime. Its use is now discouraged. This code has been merged into the GNUstep Objective-C runtime, which can act as a drop-in replacement for GCC libobjc. You can find the code here:
ObjectiveC2 framework implements the new Apple runtime APIs, introduced with
OS X 10.5 on top of the GCC Objective-C runtime. Its use is now discouraged.
This code has been merged into the GNUstep Objective-C-2.0 runtime, which can
act as a drop-in replacement for GCC libobjc. You can find the code here:
svn://svn.gna.org/svn/gnustep/libs/libobjc2/trunk

View file

@ -11,25 +11,28 @@ int main()
NSHost *tmp;
current = [NSHost currentHost];
PASS(current != nil && [current isKindOfClass:[NSHost class]],
PASS(current != nil && [current isKindOfClass: [NSHost class]],
"NSHost understands +currentHost");
#if defined(GNUSTEP_BASE_LIBRARY)
localh = [NSHost localHost];
PASS(localh != nil && [localh isKindOfClass:[NSHost class]],
PASS(localh != nil && [localh isKindOfClass: [NSHost class]],
"NSHost understands +localHost");
#else
localh = current;
#endif
tmp = [NSHost hostWithName:[current name]];
PASS([tmp isEqualToHost:current], "NSHost understands +hostWithName:");
tmp = [NSHost hostWithName: @"::1"];
PASS([[tmp address] isEqual: @"::1"], "+hostWithName: works for IPV6 addr");
tmp = [NSHost hostWithName: [current name]];
PASS([tmp isEqualToHost: current], "NSHost understands +hostWithName:");
tmp = [NSHost hostWithAddress:[current address]];
PASS([tmp isEqualToHost:current], "NSHost understands +hostWithAddress:");
tmp = [NSHost hostWithAddress: [current address]];
PASS([tmp isEqualToHost: current], "NSHost understands +hostWithAddress:");
tmp = [NSHost hostWithName:@"127.0.0.1"];
PASS(tmp != nil && [tmp isEqualToHost:localh],
tmp = [NSHost hostWithName: @"127.0.0.1"];
PASS(tmp != nil && [tmp isEqualToHost: localh],
"NSHost understands [+hostWithName: 127.0.0.1]");
[arp release]; arp = nil;