libs-base/Source/NSHost.m
fedor 6a75fb2858 subprojects, testing fiex
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@3762 72102866-910b-0410-8b05-ffd578937521
1999-02-19 21:47:15 +00:00

351 lines
7.4 KiB
Objective-C

/* Implementation of host class
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
Written by: Luke Howard <lukeh@xedoc.com.au>
Date: 1996
This file is part of the GNUstep Base Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <config.h>
#include <base/preface.h>
#include <Foundation/NSLock.h>
#include <Foundation/NSHost.h>
#include <Foundation/NSArray.h>
#include <Foundation/NSDictionary.h>
#include <Foundation/NSString.h>
#include <Foundation/NSCoder.h>
#include <netdb.h>
/* #include <libc.h> */
#ifdef WIN32
#include <Windows32/Sockets.h>
#else
#include <unistd.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#endif /* WIN32 */
static NSLock *_hostCacheLock = nil;
static BOOL _hostCacheEnabled = NO;
static NSMutableDictionary *_hostCache = nil;
@interface NSHost (Private)
+ (NSHost *)_hostWithHostEntry:(struct hostent *)entry;
+ (NSHost *)_hostWithHostEntry:(struct hostent *)entry name:name;
- _initWithHostEntry:(struct hostent *)entry name:name;
@end
@implementation NSHost (Private)
+ (NSHost *)_hostWithHostEntry:(struct hostent *)entry
{
if (!entry)
return nil;
return [[self class] _hostWithHostEntry:entry
name:[NSString stringWithCString:entry->h_name]];
}
+ (NSHost *)_hostWithHostEntry:(struct hostent *)entry name:name
{
NSHost *res = nil;
[_hostCacheLock lock];
if (_hostCacheEnabled == YES)
{
res = [_hostCache objectForKey:name];
}
[_hostCacheLock unlock];
return (res != nil) ? res : [[[[self class] alloc]
_initWithHostEntry:entry name:name] autorelease];
}
- _initWithHostEntry:(struct hostent *)entry name:name
{
int i;
char *ptr;
struct in_addr in;
NSString *h_name;
[super init];
if (entry == (struct hostent *)NULL)
{
return nil;
}
names = [[NSMutableArray array] retain];
addresses = [[NSMutableArray array] retain];
[names addObject:name];
h_name = [NSString stringWithCString:entry->h_name];
if (![h_name isEqual:name])
{
[names addObject:h_name];
}
for (i = 0, ptr = entry->h_aliases[0]; ptr != NULL; i++,
ptr = entry->h_aliases[i])
{
[names addObject:[NSString stringWithCString:ptr]];
}
for (i = 0, ptr = entry->h_addr_list[0]; ptr != NULL; i++,
ptr = entry->h_addr_list[i])
{
memcpy((void *)&in.s_addr, (const void *)ptr,
entry->h_length);
[addresses addObject:[NSString
stringWithCString:(char*)inet_ntoa(in)]];
}
[_hostCacheLock lock];
if (_hostCacheEnabled == YES)
{
[_hostCache setObject:self forKey:name];
}
[_hostCacheLock unlock];
return self;
}
@end
@implementation NSHost
- init
{
return nil;
}
+ (void)initialize
{
_hostCacheLock = [[NSConditionLock alloc] init];
_hostCache = [NSMutableDictionary new];
}
+ (NSHost *)currentHost
{
char name[MAXHOSTNAMELEN];
int res;
struct hostent *h;
res = gethostname(name, sizeof(name));
if (res < 0)
{
return nil;
}
h = gethostbyname(name);
if (h == NULL)
{
NSLog(@"Unable to determine current host");
return nil;
}
return [self _hostWithHostEntry:h name:[NSString
stringWithCString:name]];
}
+ (NSHost *)hostWithName:(NSString *)name
{
struct hostent *h;
if (name == nil)
{
NSLog(@"Nil host name sent to +[NSHost hostWithName]");
return nil;
}
h = gethostbyname((char *)[name cString]);
return [self _hostWithHostEntry:h name:name];
}
+ (NSHost *)hostWithAddress:(NSString *)address
{
struct hostent *h;
struct in_addr hostaddr;
if (address == nil)
{
NSLog(@"Nil address sent to +[NSHost hostWithAddress]");
return nil;
}
hostaddr.s_addr = inet_addr((char *)[address cString]);
if (hostaddr.s_addr == -1)
{
return nil;
}
h = gethostbyaddr((char *)&hostaddr, sizeof(hostaddr), AF_INET);
return [self _hostWithHostEntry:h];
}
+ (void)setHostCacheEnabled:(BOOL)flag
{
[_hostCacheLock lock];
_hostCacheEnabled = flag;
[_hostCacheLock unlock];
}
+ (BOOL)isHostCacheEnabled;
{
BOOL res;
[_hostCacheLock lock];
res = _hostCacheEnabled;
[_hostCacheLock unlock];
return res;
}
+ (void)flushHostCache
{
[_hostCacheLock lock];
[_hostCache removeAllObjects];
[_hostCacheLock unlock];
}
/* Methods for encoding/decoding */
- (Class) classForPortCoder
{
return [self class];
}
- replacementObjectForPortCoder:(NSPortCoder*)aCoder
{
return self;
}
- (void) encodeWithCoder: (NSCoder*)aCoder
{
[super encodeWithCoder: aCoder];
[aCoder encodeObject: [self address]];
}
#if 1
/* GNUstep specific method for more efficient decoding. */
+ (id) newWithCoder: (NSCoder*)aCoder
{
NSString *address = [aCoder decodeObject];
return [NSHost hostWithAddress: address];
}
#else
/* OpenStep methods for decoding (not used) */
- (id) awakeAfterUsingCoder: (NSCoder*)aCoder
{
return [NSHost hostWithAddress: [addresses objectAtIndex: 0]];
}
- (id) initWithCoder: (NSCoder*)aCoder
{
NSString *address;
[super initWithCoder: aCoder];
address = [aCoder decodeObject];
addresses = [NSArray arrayWithObject: address];
return self;
}
#endif
/*
* The OpenStep spec says that [-hash] must be the same for any two
* objects that [-isEqual:] returns YES for. We have a problem in
* that [-isEqualToHost:] is specified to return YES if any name or
* address part of two hosts is the same. That means we can't
* reasonably calculate a hash since two hosts with radically
* different ivar contents may be 'equal'. The best I can think of
* is for all hosts to hash to the same value - which makes it very
* inefficient to store them in a set, dictionary, map or hash table.
*/
- (unsigned) hash
{
return 1;
}
- (BOOL) isEqual: (id)other
{
if (other == self)
return YES;
if ([other isKindOfClass: [NSHost class]])
return [self isEqualToHost: (NSHost*)other];
return NO;
}
- (BOOL)isEqualToHost:(NSHost *)aHost
{
NSArray* a;
int i;
if (aHost == self)
return YES;
a = [aHost addresses];
for (i = 0; i < [a count]; i++)
if ([addresses containsObject:[a objectAtIndex:i]])
return YES;
a = [aHost names];
for (i = 0; i < [a count]; i++)
if ([addresses containsObject:[a objectAtIndex:i]])
return YES;
return NO;
}
- (NSString *)name
{
return [names objectAtIndex:0];
}
- (NSArray *)names
{
return names;
}
- (NSString *)address
{
return [addresses objectAtIndex:0];
}
- (NSArray *)addresses
{
return addresses;
}
- (NSString *)description
{
return [NSString stringWithFormat:@"Host %@ (%@ %@)", [self
name],
[[self names] description], [[self addresses]
description]];
}
- (void)dealloc
{
[names autorelease];
[addresses autorelease];
[super dealloc];
}
@end