1998-10-29 12:50:23 +00:00
|
|
|
|
/* Implementation of NSPortNameServer class for Distributed Objects
|
2000-02-24 22:45:18 +00:00
|
|
|
|
Copyright (C) 1998,1999,2000 Free Software Foundation, Inc.
|
1998-10-29 12:50:23 +00:00
|
|
|
|
|
|
|
|
|
Written by: Richard Frith-Macdonald <richard@brainstorm.co.uk>
|
|
|
|
|
Created: October 1998
|
|
|
|
|
|
|
|
|
|
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
|
1999-09-09 02:56:20 +00:00
|
|
|
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
1998-10-29 12:50:23 +00:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
#include <Foundation/NSString.h>
|
|
|
|
|
#include <Foundation/NSByteOrder.h>
|
|
|
|
|
#include <Foundation/NSException.h>
|
|
|
|
|
#include <Foundation/NSAutoreleasePool.h>
|
|
|
|
|
#include <Foundation/NSLock.h>
|
|
|
|
|
#include <Foundation/NSFileHandle.h>
|
|
|
|
|
#include <Foundation/NSRunLoop.h>
|
|
|
|
|
#include <Foundation/NSNotificationQueue.h>
|
|
|
|
|
#include <Foundation/NSPort.h>
|
1998-10-30 08:40:03 +00:00
|
|
|
|
#include <Foundation/NSMapTable.h>
|
|
|
|
|
#include <Foundation/NSSet.h>
|
1998-11-27 20:20:16 +00:00
|
|
|
|
#include <Foundation/NSHost.h>
|
1999-04-14 10:34:56 +00:00
|
|
|
|
#include <Foundation/NSTask.h>
|
|
|
|
|
#include <Foundation/NSDate.h>
|
1999-04-16 20:06:25 +00:00
|
|
|
|
#include <Foundation/NSTimer.h>
|
1998-10-29 12:50:23 +00:00
|
|
|
|
#include <Foundation/NSPortNameServer.h>
|
1999-09-21 19:07:27 +00:00
|
|
|
|
#include <Foundation/NSDebug.h>
|
1998-12-20 21:27:47 +00:00
|
|
|
|
#include <base/TcpPort.h>
|
1999-06-24 19:30:29 +00:00
|
|
|
|
#include <arpa/inet.h>
|
1998-10-29 12:50:23 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Protocol definition stuff for talking to gdomap process.
|
|
|
|
|
*/
|
|
|
|
|
#include "../Tools/gdomap.h"
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Macros to build text to start name server and to give an error
|
|
|
|
|
* message about it - they include installation path information.
|
|
|
|
|
*/
|
|
|
|
|
#define stringify_it(X) #X
|
1999-04-14 14:13:20 +00:00
|
|
|
|
#define make_gdomap_cmd(X) stringify_it(X) "/Tools/gdomap"
|
|
|
|
|
#define make_gdomap_err(X) "check that " stringify_it(X) "/Tools/gdomap is running and owned by root."
|
1998-11-27 20:39:08 +00:00
|
|
|
|
#define make_gdomap_port(X) stringify_it(X)
|
1998-10-29 12:50:23 +00:00
|
|
|
|
|
1999-06-24 20:13:02 +00:00
|
|
|
|
/*
|
2000-02-24 22:45:18 +00:00
|
|
|
|
* to suppress warnings about using private methods.
|
1999-06-24 20:13:02 +00:00
|
|
|
|
*/
|
2000-02-24 22:45:18 +00:00
|
|
|
|
@class GSTcpPort;
|
|
|
|
|
@class TcpOutPort;
|
|
|
|
|
@interface NSPort (Hack)
|
1999-06-24 20:13:02 +00:00
|
|
|
|
+ newForSendingToSockaddr: (struct sockaddr_in*)sockaddr
|
|
|
|
|
withAcceptedSocket: (int)sock
|
|
|
|
|
pollingInPort: (id)ip;
|
2000-02-24 22:45:18 +00:00
|
|
|
|
|
|
|
|
|
+ (GSTcpPort*) portWithNumber: (gsu16)number
|
|
|
|
|
onHost: (NSHost*)host
|
2000-02-27 17:16:39 +00:00
|
|
|
|
forceAddress: (NSString*)addr
|
|
|
|
|
listener: (BOOL)shouldListen;
|
1999-06-24 20:13:02 +00:00
|
|
|
|
@end
|
|
|
|
|
|
1998-10-29 12:50:23 +00:00
|
|
|
|
/*
|
1999-09-21 19:07:27 +00:00
|
|
|
|
* class-wide variables.
|
1998-10-29 12:50:23 +00:00
|
|
|
|
*/
|
1999-09-21 19:07:27 +00:00
|
|
|
|
static unsigned maxHandles = 4;
|
|
|
|
|
static NSTimeInterval timeout = 20.0;
|
1998-10-29 12:50:23 +00:00
|
|
|
|
static NSString *serverPort = @"gdomap";
|
|
|
|
|
static NSString *mode = @"NSPortServerLookupMode";
|
|
|
|
|
static NSArray *modes = nil;
|
|
|
|
|
static NSRecursiveLock *serverLock = nil;
|
|
|
|
|
static NSPortNameServer *defaultServer = nil;
|
1999-09-21 19:07:27 +00:00
|
|
|
|
static NSString *launchCmd = nil;
|
2000-02-24 22:45:18 +00:00
|
|
|
|
static Class portClass = 0;
|
1999-09-21 19:07:27 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
|
GSPC_NONE,
|
|
|
|
|
GSPC_LOPEN,
|
|
|
|
|
GSPC_ROPEN,
|
|
|
|
|
GSPC_RETRY,
|
|
|
|
|
GSPC_WRITE,
|
|
|
|
|
GSPC_READ1,
|
|
|
|
|
GSPC_READ2,
|
|
|
|
|
GSPC_FAIL,
|
|
|
|
|
GSPC_DONE
|
|
|
|
|
} GSPortComState;
|
|
|
|
|
|
|
|
|
|
@interface GSPortCom : NSObject
|
|
|
|
|
{
|
|
|
|
|
gdo_req msg;
|
|
|
|
|
unsigned expecting;
|
|
|
|
|
NSMutableData *data;
|
|
|
|
|
NSFileHandle *handle;
|
|
|
|
|
GSPortComState state;
|
|
|
|
|
struct in_addr addr;
|
|
|
|
|
}
|
|
|
|
|
- (struct in_addr) addr;
|
|
|
|
|
- (void) close;
|
|
|
|
|
- (NSData*) data;
|
|
|
|
|
- (void) didConnect: (NSNotification*)notification;
|
|
|
|
|
- (void) didRead: (NSNotification*)notification;
|
|
|
|
|
- (void) didWrite: (NSNotification*)notification;
|
|
|
|
|
- (void) fail;
|
|
|
|
|
- (BOOL) isActive;
|
|
|
|
|
- (void) open: (NSString*)host;
|
|
|
|
|
- (void) setAddr: (struct in_addr)addr;
|
|
|
|
|
- (GSPortComState) state;
|
|
|
|
|
- (void) startListNameServers;
|
|
|
|
|
- (void) startPortLookup: (NSString*)name onHost: (NSString*)addr;
|
|
|
|
|
- (void) startPortRegistration: (gsu32)portNumber withName: (NSString*)name;
|
|
|
|
|
- (void) startPortUnregistration: (gsu32)portNumber withName: (NSString*)name;
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
@implementation GSPortCom
|
|
|
|
|
|
|
|
|
|
- (struct in_addr) addr
|
|
|
|
|
{
|
|
|
|
|
return addr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) close
|
|
|
|
|
{
|
|
|
|
|
if (handle != nil)
|
|
|
|
|
{
|
|
|
|
|
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
|
|
|
|
|
|
|
|
|
|
[nc removeObserver: self
|
|
|
|
|
name: GSFileHandleConnectCompletionNotification
|
|
|
|
|
object: handle];
|
|
|
|
|
[nc removeObserver: self
|
|
|
|
|
name: NSFileHandleReadCompletionNotification
|
|
|
|
|
object: handle];
|
|
|
|
|
[nc removeObserver: self
|
|
|
|
|
name: GSFileHandleWriteCompletionNotification
|
|
|
|
|
object: handle];
|
|
|
|
|
[handle closeFile];
|
|
|
|
|
DESTROY(handle);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (NSData*) data
|
|
|
|
|
{
|
|
|
|
|
return data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) dealloc
|
|
|
|
|
{
|
|
|
|
|
[self close];
|
|
|
|
|
TEST_RELEASE(data);
|
|
|
|
|
[super dealloc];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) didConnect: (NSNotification*)notification
|
|
|
|
|
{
|
|
|
|
|
NSDictionary *userInfo = [notification userInfo];
|
|
|
|
|
NSString *e;
|
|
|
|
|
|
|
|
|
|
e = [userInfo objectForKey: GSFileHandleNotificationError];
|
|
|
|
|
if (e != nil)
|
|
|
|
|
{
|
|
|
|
|
NSLog(@"NSPortNameServer failed connect to gdomap - %@", e);
|
|
|
|
|
/*
|
|
|
|
|
* Remove our file handle, then either retry or fail.
|
|
|
|
|
*/
|
|
|
|
|
[self close];
|
|
|
|
|
if (state == GSPC_LOPEN)
|
|
|
|
|
{
|
1999-10-01 09:37:40 +00:00
|
|
|
|
NSRunLoop *loop = [NSRunLoop currentRunLoop];
|
|
|
|
|
NSTimer *timer;
|
|
|
|
|
|
1999-09-21 19:07:27 +00:00
|
|
|
|
NSLog(@"NSPortNameServer attempting to start gdomap on local host");
|
|
|
|
|
[NSTask launchedTaskWithLaunchPath: launchCmd arguments: nil];
|
1999-10-01 09:37:40 +00:00
|
|
|
|
timer = [NSTimer timerWithTimeInterval: 5.0
|
|
|
|
|
invocation: nil
|
|
|
|
|
repeats: NO];
|
|
|
|
|
[loop addTimer: timer forMode: [loop currentMode]];
|
|
|
|
|
[loop runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 5.0]];
|
1999-09-21 19:07:27 +00:00
|
|
|
|
NSLog(@"NSPortNameServer retrying connection attempt to gdomap");
|
|
|
|
|
state = GSPC_RETRY;
|
|
|
|
|
[self open: nil];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
[self fail];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
[[NSNotificationCenter defaultCenter]
|
|
|
|
|
removeObserver: self
|
|
|
|
|
name: GSFileHandleConnectCompletionNotification
|
|
|
|
|
object: handle];
|
|
|
|
|
/*
|
|
|
|
|
* Now we have established a connection, we can write the request
|
|
|
|
|
* to the name server.
|
|
|
|
|
*/
|
|
|
|
|
state = GSPC_WRITE;
|
|
|
|
|
[handle writeInBackgroundAndNotify: data
|
|
|
|
|
forModes: modes];
|
|
|
|
|
DESTROY(data);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) didRead: (NSNotification*)notification
|
|
|
|
|
{
|
|
|
|
|
NSDictionary *userInfo = [notification userInfo];
|
|
|
|
|
NSData *d;
|
|
|
|
|
|
|
|
|
|
d = [userInfo objectForKey: NSFileHandleNotificationDataItem];
|
|
|
|
|
|
|
|
|
|
if (d == nil || [d length] == 0)
|
|
|
|
|
{
|
|
|
|
|
[self fail];
|
|
|
|
|
NSLog(@"NSPortNameServer lost connection to gdomap");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (data == nil)
|
|
|
|
|
{
|
|
|
|
|
data = [d mutableCopy];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
[data appendData: d];
|
|
|
|
|
}
|
|
|
|
|
if ([data length] < expecting)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Not enough data read yet - go read some more.
|
|
|
|
|
*/
|
|
|
|
|
[handle readInBackgroundAndNotifyForModes: modes];
|
|
|
|
|
}
|
|
|
|
|
else if (state == GSPC_READ1 && msg.rtype == GDO_SERVERS)
|
|
|
|
|
{
|
|
|
|
|
gsu32 numSvrs = GSSwapBigI32ToHost(*(gsu32*)[data bytes]);
|
|
|
|
|
|
|
|
|
|
if (numSvrs == 0)
|
|
|
|
|
{
|
|
|
|
|
[self fail];
|
|
|
|
|
NSLog(@"failed to get list of name servers on net");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Now read in the addresses of the servers.
|
|
|
|
|
*/
|
|
|
|
|
expecting += numSvrs * sizeof(struct in_addr);
|
|
|
|
|
if ([data length] < expecting)
|
|
|
|
|
{
|
|
|
|
|
state = GSPC_READ2;
|
|
|
|
|
[handle readInBackgroundAndNotifyForModes: modes];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
[[NSNotificationCenter defaultCenter]
|
|
|
|
|
removeObserver: self
|
|
|
|
|
name: NSFileHandleReadCompletionNotification
|
|
|
|
|
object: handle];
|
|
|
|
|
state = GSPC_DONE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
[[NSNotificationCenter defaultCenter]
|
|
|
|
|
removeObserver: self
|
|
|
|
|
name: NSFileHandleReadCompletionNotification
|
|
|
|
|
object: handle];
|
|
|
|
|
state = GSPC_DONE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) didWrite: (NSNotification*)notification
|
|
|
|
|
{
|
|
|
|
|
NSDictionary *userInfo = [notification userInfo];
|
|
|
|
|
NSString *e;
|
|
|
|
|
|
|
|
|
|
e = [userInfo objectForKey: GSFileHandleNotificationError];
|
|
|
|
|
if (e != nil)
|
|
|
|
|
{
|
|
|
|
|
[self fail];
|
|
|
|
|
NSLog(@"NSPortNameServer failed write to gdomap - %@", e);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
state = GSPC_READ1;
|
|
|
|
|
data = [NSMutableData new];
|
|
|
|
|
expecting = 4;
|
|
|
|
|
[handle readInBackgroundAndNotifyForModes: modes];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) fail
|
|
|
|
|
{
|
|
|
|
|
[self close];
|
|
|
|
|
if (data != nil)
|
|
|
|
|
{
|
|
|
|
|
DESTROY(data);
|
|
|
|
|
}
|
|
|
|
|
msg.rtype = 0;
|
|
|
|
|
state = GSPC_FAIL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (BOOL) isActive
|
|
|
|
|
{
|
|
|
|
|
if (handle == nil)
|
|
|
|
|
return NO;
|
|
|
|
|
if (state == GSPC_FAIL)
|
|
|
|
|
return NO;
|
|
|
|
|
if (state == GSPC_NONE)
|
|
|
|
|
return NO;
|
|
|
|
|
if (state == GSPC_DONE)
|
|
|
|
|
return NO;
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) open: (NSString*)hostname
|
|
|
|
|
{
|
|
|
|
|
NSNotificationCenter *nc;
|
|
|
|
|
|
|
|
|
|
NSAssert(state == GSPC_NONE || state == GSPC_RETRY, @"open in bad state");
|
|
|
|
|
|
|
|
|
|
if (state == GSPC_NONE)
|
|
|
|
|
{
|
|
|
|
|
state = GSPC_ROPEN; /* Assume we are connection to remote system */
|
|
|
|
|
if (hostname == nil || [hostname isEqual: @""])
|
|
|
|
|
{
|
|
|
|
|
hostname = @"localhost";
|
|
|
|
|
state = GSPC_LOPEN;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
NSHost *current = [NSHost currentHost];
|
|
|
|
|
NSHost *host = [NSHost hostWithName: hostname];
|
|
|
|
|
|
|
|
|
|
if (host == nil)
|
|
|
|
|
{
|
|
|
|
|
host = [NSHost hostWithAddress: hostname];
|
|
|
|
|
}
|
|
|
|
|
if ([current isEqual: host])
|
|
|
|
|
{
|
|
|
|
|
state = GSPC_LOPEN;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_DURING
|
|
|
|
|
{
|
|
|
|
|
handle = [NSFileHandle fileHandleAsClientInBackgroundAtAddress:
|
|
|
|
|
hostname service: serverPort protocol: @"tcp" forModes: modes];
|
|
|
|
|
}
|
|
|
|
|
NS_HANDLER
|
|
|
|
|
{
|
|
|
|
|
NSLog(@"Exception looking up port for gdomap - %@", localException);
|
|
|
|
|
if ([[localException name] isEqual: NSInvalidArgumentException])
|
|
|
|
|
{
|
|
|
|
|
handle = nil;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
[self fail];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
NS_ENDHANDLER
|
|
|
|
|
|
|
|
|
|
if (state == GSPC_FAIL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (handle == nil)
|
|
|
|
|
{
|
|
|
|
|
NSLog(@"Failed to find gdomap port with name '%@',\nperhaps your "
|
|
|
|
|
@"/etc/services file is not correctly set up?\n"
|
|
|
|
|
@"Retrying with default (IANA allocated) port number 538",
|
|
|
|
|
serverPort);
|
|
|
|
|
NS_DURING
|
|
|
|
|
{
|
|
|
|
|
handle = [NSFileHandle fileHandleAsClientInBackgroundAtAddress:
|
|
|
|
|
hostname service: @"538" protocol: @"tcp" forModes: modes];
|
|
|
|
|
}
|
|
|
|
|
NS_HANDLER
|
|
|
|
|
{
|
|
|
|
|
NSLog(@"Exception creating handle for gdomap - %@", localException);
|
|
|
|
|
[self fail];
|
|
|
|
|
}
|
|
|
|
|
NS_ENDHANDLER
|
|
|
|
|
if (handle)
|
|
|
|
|
{
|
|
|
|
|
RELEASE(serverPort);
|
|
|
|
|
serverPort = @"538";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (state == GSPC_FAIL)
|
|
|
|
|
return;
|
|
|
|
|
|
1999-09-28 19:35:09 +00:00
|
|
|
|
IF_NO_GC(RETAIN(handle));
|
1999-09-21 19:07:27 +00:00
|
|
|
|
nc = [NSNotificationCenter defaultCenter];
|
|
|
|
|
[nc addObserver: self
|
|
|
|
|
selector: @selector(didConnect:)
|
|
|
|
|
name: GSFileHandleConnectCompletionNotification
|
|
|
|
|
object: handle];
|
|
|
|
|
[nc addObserver: self
|
|
|
|
|
selector: @selector(didRead:)
|
|
|
|
|
name: NSFileHandleReadCompletionNotification
|
|
|
|
|
object: handle];
|
|
|
|
|
[nc addObserver: self
|
|
|
|
|
selector: @selector(didWrite:)
|
|
|
|
|
name: GSFileHandleWriteCompletionNotification
|
|
|
|
|
object: handle];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) setAddr: (struct in_addr)anAddr
|
|
|
|
|
{
|
|
|
|
|
addr = anAddr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (GSPortComState) state
|
|
|
|
|
{
|
|
|
|
|
return state;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) startListNameServers
|
|
|
|
|
{
|
|
|
|
|
msg.rtype = GDO_SERVERS; /* Get a list of name servers. */
|
|
|
|
|
msg.ptype = GDO_TCP_GDO; /* Port is TCP port for GNU DO */
|
|
|
|
|
msg.nsize = 0;
|
|
|
|
|
msg.port = 0;
|
|
|
|
|
TEST_RELEASE(data);
|
|
|
|
|
data = [NSMutableData dataWithBytes: (void*)&msg length: sizeof(msg)];
|
1999-09-28 19:35:09 +00:00
|
|
|
|
IF_NO_GC(RETAIN(data));
|
1999-09-21 19:07:27 +00:00
|
|
|
|
[self open: nil];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) startPortLookup: (NSString*)name onHost: (NSString*)host
|
|
|
|
|
{
|
|
|
|
|
msg.rtype = GDO_LOOKUP; /* Find the named port. */
|
|
|
|
|
msg.ptype = GDO_TCP_GDO; /* Port is TCP port for GNU DO */
|
|
|
|
|
msg.port = 0;
|
|
|
|
|
msg.nsize = [name cStringLength];
|
|
|
|
|
[name getCString: msg.name];
|
|
|
|
|
TEST_RELEASE(data);
|
|
|
|
|
data = [NSMutableData dataWithBytes: (void*)&msg length: sizeof(msg)];
|
1999-09-28 19:35:09 +00:00
|
|
|
|
IF_NO_GC(RETAIN(data));
|
1999-09-21 19:07:27 +00:00
|
|
|
|
[self open: host];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) startPortRegistration: (gsu32)portNumber withName: (NSString*)name
|
|
|
|
|
{
|
|
|
|
|
msg.rtype = GDO_REGISTER; /* Register a port. */
|
|
|
|
|
msg.ptype = GDO_TCP_GDO; /* Port is TCP port for GNU DO */
|
|
|
|
|
msg.nsize = [name cStringLength];
|
|
|
|
|
[name getCString: msg.name];
|
|
|
|
|
msg.port = GSSwapHostI32ToBig(portNumber);
|
|
|
|
|
TEST_RELEASE(data);
|
|
|
|
|
data = [NSMutableData dataWithBytes: (void*)&msg length: sizeof(msg)];
|
1999-09-28 19:35:09 +00:00
|
|
|
|
IF_NO_GC(RETAIN(data));
|
1999-09-21 19:07:27 +00:00
|
|
|
|
[self open: nil];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) startPortUnregistration: (gsu32)portNumber withName: (NSString*)name
|
|
|
|
|
{
|
|
|
|
|
msg.rtype = GDO_UNREG;
|
|
|
|
|
msg.ptype = GDO_TCP_GDO;
|
|
|
|
|
if (name == nil)
|
|
|
|
|
{
|
|
|
|
|
msg.nsize = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
msg.nsize = [name cStringLength];
|
|
|
|
|
[name getCString: msg.name];
|
|
|
|
|
}
|
|
|
|
|
msg.port = GSSwapHostI32ToBig(portNumber);
|
|
|
|
|
TEST_RELEASE(data);
|
|
|
|
|
data = [NSMutableData dataWithBytes: (void*)&msg length: sizeof(msg)];
|
1999-09-28 19:35:09 +00:00
|
|
|
|
IF_NO_GC(RETAIN(data));
|
1999-09-21 19:07:27 +00:00
|
|
|
|
[self open: nil];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@implementation NSPortNameServer
|
1998-10-29 12:50:23 +00:00
|
|
|
|
|
|
|
|
|
+ (id) allocWithZone: (NSZone*)aZone
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSGenericException
|
|
|
|
|
format: @"attempt to create extra port name server"];
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (void) initialize
|
|
|
|
|
{
|
|
|
|
|
if (self == [NSPortNameServer class])
|
|
|
|
|
{
|
1999-09-21 19:07:27 +00:00
|
|
|
|
serverLock = [NSRecursiveLock new];
|
|
|
|
|
modes = [[NSArray alloc] initWithObjects: &mode count: 1];
|
1998-11-27 20:39:08 +00:00
|
|
|
|
#ifdef GDOMAP_PORT_OVERRIDE
|
1999-09-21 19:07:27 +00:00
|
|
|
|
serverPort = RETAIN([NSString stringWithCString:
|
|
|
|
|
make_gdomap_port(GDOMAP_PORT_OVERRIDE)]);
|
1998-11-27 20:39:08 +00:00
|
|
|
|
#endif
|
1999-09-21 19:07:27 +00:00
|
|
|
|
launchCmd = [NSString stringWithCString:
|
|
|
|
|
make_gdomap_cmd(GNUSTEP_INSTALL_PREFIX)];
|
2000-07-04 11:05:46 +00:00
|
|
|
|
#if GS_NEW_DO
|
|
|
|
|
portClass = [GSTcpPort class];
|
|
|
|
|
#else
|
2000-02-24 22:45:18 +00:00
|
|
|
|
portClass = [TcpOutPort class];
|
2000-07-04 11:05:46 +00:00
|
|
|
|
#endif
|
1998-10-29 12:50:23 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2000-07-04 09:49:31 +00:00
|
|
|
|
+ (id) systemDefaultPortNameServer
|
1998-10-29 12:50:23 +00:00
|
|
|
|
{
|
|
|
|
|
if (defaultServer == nil)
|
|
|
|
|
{
|
|
|
|
|
NSPortNameServer *s;
|
|
|
|
|
|
|
|
|
|
[serverLock lock];
|
|
|
|
|
if (defaultServer)
|
|
|
|
|
{
|
|
|
|
|
[serverLock unlock];
|
|
|
|
|
return defaultServer;
|
|
|
|
|
}
|
|
|
|
|
s = (NSPortNameServer*)NSAllocateObject(self, 0, NSDefaultMallocZone());
|
1999-09-16 07:21:34 +00:00
|
|
|
|
s->_portMap = NSCreateMapTable(NSNonRetainedObjectMapKeyCallBacks,
|
1998-10-30 08:40:03 +00:00
|
|
|
|
NSObjectMapValueCallBacks, 0);
|
1999-09-16 07:21:34 +00:00
|
|
|
|
s->_nameMap = NSCreateMapTable(NSObjectMapKeyCallBacks,
|
1998-10-30 08:40:03 +00:00
|
|
|
|
NSNonOwnedPointerMapValueCallBacks, 0);
|
1998-10-29 12:50:23 +00:00
|
|
|
|
defaultServer = s;
|
|
|
|
|
[serverLock unlock];
|
|
|
|
|
}
|
|
|
|
|
return defaultServer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) dealloc
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSGenericException
|
|
|
|
|
format: @"attempt to deallocate default port name server"];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (NSPort*) portForName: (NSString*)name
|
|
|
|
|
{
|
|
|
|
|
return [self portForName: name onHost: nil];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (NSPort*) portForName: (NSString*)name
|
|
|
|
|
onHost: (NSString*)host
|
|
|
|
|
{
|
1999-09-21 19:07:27 +00:00
|
|
|
|
GSPortCom *com = nil;
|
1998-10-29 12:50:23 +00:00
|
|
|
|
NSRunLoop *loop = [NSRunLoop currentRunLoop];
|
|
|
|
|
struct in_addr singleServer;
|
|
|
|
|
struct in_addr *svrs = &singleServer;
|
|
|
|
|
unsigned numSvrs;
|
|
|
|
|
unsigned count;
|
|
|
|
|
unsigned portNum = 0;
|
1999-09-21 19:07:27 +00:00
|
|
|
|
unsigned len;
|
|
|
|
|
NSMutableArray *array;
|
2000-02-04 18:14:13 +00:00
|
|
|
|
NSDate *limit;
|
1998-10-29 12:50:23 +00:00
|
|
|
|
|
|
|
|
|
if (name == nil)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
1999-07-23 21:18:36 +00:00
|
|
|
|
format: @"attempt to lookup port with nil name"];
|
1998-10-29 12:50:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
len = [name cStringLength];
|
|
|
|
|
if (len == 0)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
1999-07-23 21:18:36 +00:00
|
|
|
|
format: @"attempt to lookup port with no name"];
|
1998-10-29 12:50:23 +00:00
|
|
|
|
}
|
|
|
|
|
if (len > GDO_NAME_MAX_LEN)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"name of port is too long (max %d) bytes",
|
|
|
|
|
GDO_NAME_MAX_LEN];
|
|
|
|
|
}
|
|
|
|
|
|
2000-02-04 18:14:13 +00:00
|
|
|
|
limit = [NSDate dateWithTimeIntervalSinceNow: timeout];
|
|
|
|
|
|
1999-09-21 19:07:27 +00:00
|
|
|
|
/*
|
|
|
|
|
* get one or more host addresses in network byte order.
|
|
|
|
|
*/
|
1999-07-23 21:18:36 +00:00
|
|
|
|
if (host == nil || [host isEqual: @""])
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Query a single nameserver - on the local host.
|
|
|
|
|
*/
|
|
|
|
|
numSvrs = 1;
|
|
|
|
|
#ifndef HAVE_INET_ATON
|
|
|
|
|
svrs->s_addr = inet_addr("127.0.0.1");
|
|
|
|
|
#else
|
|
|
|
|
inet_aton("127.0.0.1", (struct in_addr *)&svrs->s_addr);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
else if ([host isEqual: @"*"])
|
1998-10-29 12:50:23 +00:00
|
|
|
|
{
|
1999-09-21 19:07:27 +00:00
|
|
|
|
GSPortCom *com = [GSPortCom new];
|
1998-10-29 12:50:23 +00:00
|
|
|
|
|
|
|
|
|
[serverLock lock];
|
|
|
|
|
NS_DURING
|
|
|
|
|
{
|
1999-09-21 19:07:27 +00:00
|
|
|
|
GSPortCom *tmp;
|
|
|
|
|
NSData *dat;
|
|
|
|
|
|
|
|
|
|
[com startListNameServers];
|
|
|
|
|
while ([limit timeIntervalSinceNow] > 0 && [com isActive] == YES)
|
1998-10-29 12:50:23 +00:00
|
|
|
|
{
|
1999-09-21 19:07:27 +00:00
|
|
|
|
[loop runMode: mode
|
|
|
|
|
beforeDate: limit];
|
1998-10-29 12:50:23 +00:00
|
|
|
|
}
|
1999-09-21 19:07:27 +00:00
|
|
|
|
[com close];
|
|
|
|
|
if ([com state] != GSPC_DONE)
|
1998-10-29 12:50:23 +00:00
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSPortTimeoutException
|
1999-09-21 19:07:27 +00:00
|
|
|
|
format: @"timed out listing name servers"];
|
1998-10-29 12:50:23 +00:00
|
|
|
|
}
|
1999-09-21 19:07:27 +00:00
|
|
|
|
/*
|
|
|
|
|
* Retain and autorelease the data item so the buffer won't disappear
|
|
|
|
|
* when the 'com' object is destroyed.
|
|
|
|
|
*/
|
|
|
|
|
dat = AUTORELEASE(RETAIN([com data]));
|
|
|
|
|
svrs = (struct in_addr*)([dat bytes] + 4);
|
|
|
|
|
numSvrs = GSSwapBigI32ToHost(*(gsu32*)[dat bytes]);
|
1998-10-29 12:50:23 +00:00
|
|
|
|
if (numSvrs == 0)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
2000-02-04 18:14:13 +00:00
|
|
|
|
format: @"failed to get list of name servers"];
|
1998-10-29 12:50:23 +00:00
|
|
|
|
}
|
1999-09-21 19:07:27 +00:00
|
|
|
|
tmp = com;
|
|
|
|
|
com = nil;
|
|
|
|
|
RELEASE(tmp);
|
1998-10-29 12:50:23 +00:00
|
|
|
|
}
|
|
|
|
|
NS_HANDLER
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* If we had a problem - unlock before continueing.
|
|
|
|
|
*/
|
1999-09-21 19:07:27 +00:00
|
|
|
|
RELEASE(com);
|
1998-10-29 12:50:23 +00:00
|
|
|
|
[serverLock unlock];
|
|
|
|
|
[localException raise];
|
|
|
|
|
}
|
|
|
|
|
NS_ENDHANDLER
|
|
|
|
|
[serverLock unlock];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
1999-07-23 21:18:36 +00:00
|
|
|
|
NSHost *h;
|
|
|
|
|
|
1998-10-29 12:50:23 +00:00
|
|
|
|
/*
|
1999-07-23 21:18:36 +00:00
|
|
|
|
* Query a single nameserver - on the specified host.
|
1998-10-29 12:50:23 +00:00
|
|
|
|
*/
|
|
|
|
|
numSvrs = 1;
|
1999-07-23 21:18:36 +00:00
|
|
|
|
h = [NSHost hostWithName: host];
|
|
|
|
|
if (h)
|
|
|
|
|
host = [h address];
|
1998-10-29 12:50:23 +00:00
|
|
|
|
#ifndef HAVE_INET_ATON
|
1999-07-23 21:18:36 +00:00
|
|
|
|
svrs->s_addr = inet_addr([host cString]);
|
1998-10-29 12:50:23 +00:00
|
|
|
|
#else
|
1999-07-23 21:18:36 +00:00
|
|
|
|
inet_aton([host cString], (struct in_addr *)&svrs->s_addr);
|
1998-10-29 12:50:23 +00:00
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
1999-09-21 19:07:27 +00:00
|
|
|
|
/*
|
|
|
|
|
* Ok, 'svrs'now points to one or more internet addresses in network
|
|
|
|
|
* byte order, and numSvrs tells us how many there are.
|
|
|
|
|
*/
|
|
|
|
|
array = [NSMutableArray arrayWithCapacity: maxHandles];
|
1998-10-29 12:50:23 +00:00
|
|
|
|
[serverLock lock];
|
|
|
|
|
NS_DURING
|
|
|
|
|
{
|
1999-09-21 19:07:27 +00:00
|
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
|
|
portNum = 0;
|
|
|
|
|
count = 0;
|
|
|
|
|
do
|
1998-10-29 12:50:23 +00:00
|
|
|
|
{
|
1999-09-21 19:07:27 +00:00
|
|
|
|
/*
|
|
|
|
|
* Make sure that all the array slots are full if possible
|
|
|
|
|
*/
|
|
|
|
|
while (count < numSvrs && [array count] < maxHandles)
|
1998-10-29 12:50:23 +00:00
|
|
|
|
{
|
1999-09-21 19:07:27 +00:00
|
|
|
|
NSString *addr;
|
|
|
|
|
|
|
|
|
|
com = [GSPortCom new];
|
|
|
|
|
[array addObject: com];
|
|
|
|
|
RELEASE(com);
|
|
|
|
|
[com setAddr: svrs[count]];
|
|
|
|
|
addr = [NSString stringWithCString:
|
|
|
|
|
(char*)inet_ntoa(svrs[count])];
|
|
|
|
|
[com startPortLookup: name onHost: addr];
|
|
|
|
|
count++;
|
1998-10-29 12:50:23 +00:00
|
|
|
|
}
|
1999-09-21 19:07:27 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Handle I/O on the file handles.
|
|
|
|
|
*/
|
|
|
|
|
i = [array count];
|
|
|
|
|
if (i == 0)
|
1998-10-29 12:50:23 +00:00
|
|
|
|
{
|
1999-09-21 19:07:27 +00:00
|
|
|
|
break; /* No servers left to try! */
|
|
|
|
|
}
|
|
|
|
|
[loop runMode: mode
|
|
|
|
|
beforeDate: limit];
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Check for completed operations.
|
|
|
|
|
*/
|
|
|
|
|
while (portNum == 0 && i-- > 0)
|
|
|
|
|
{
|
|
|
|
|
com = [array objectAtIndex: i];
|
|
|
|
|
if ([com isActive] == NO)
|
1998-10-29 12:50:23 +00:00
|
|
|
|
{
|
1999-09-21 19:07:27 +00:00
|
|
|
|
[com close];
|
|
|
|
|
if ([com state] == GSPC_DONE)
|
1998-10-29 12:50:23 +00:00
|
|
|
|
{
|
2000-02-04 18:14:13 +00:00
|
|
|
|
portNum
|
|
|
|
|
= GSSwapBigI32ToHost(*(gsu32*)[[com data] bytes]);
|
1999-09-21 19:07:27 +00:00
|
|
|
|
if (portNum != 0)
|
|
|
|
|
{
|
|
|
|
|
singleServer = [com addr];
|
|
|
|
|
}
|
1998-10-29 12:50:23 +00:00
|
|
|
|
}
|
1999-09-21 19:07:27 +00:00
|
|
|
|
[array removeObjectAtIndex: i];
|
1998-10-29 12:50:23 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
1999-09-21 19:07:27 +00:00
|
|
|
|
while (portNum == 0 && [limit timeIntervalSinceNow] > 0);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Make sure that any outstanding lookups are cancelled.
|
|
|
|
|
*/
|
|
|
|
|
i = [array count];
|
|
|
|
|
while (i-- > 0)
|
|
|
|
|
{
|
|
|
|
|
[[array objectAtIndex: i] fail];
|
|
|
|
|
[array removeObjectAtIndex: i];
|
|
|
|
|
}
|
1998-10-29 12:50:23 +00:00
|
|
|
|
}
|
|
|
|
|
NS_HANDLER
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* If we had a problem - unlock before continueing.
|
|
|
|
|
*/
|
|
|
|
|
[serverLock unlock];
|
|
|
|
|
[localException raise];
|
|
|
|
|
}
|
|
|
|
|
NS_ENDHANDLER
|
|
|
|
|
[serverLock unlock];
|
|
|
|
|
|
|
|
|
|
if (portNum)
|
|
|
|
|
{
|
2000-02-24 22:45:18 +00:00
|
|
|
|
if (portClass == [TcpOutPort class])
|
|
|
|
|
{
|
|
|
|
|
struct sockaddr_in sin;
|
|
|
|
|
NSPort *p;
|
|
|
|
|
unsigned short n;
|
1998-10-29 12:50:23 +00:00
|
|
|
|
|
2000-02-24 22:45:18 +00:00
|
|
|
|
memset(&sin, '\0', sizeof(sin));
|
|
|
|
|
sin.sin_family = AF_INET;
|
1998-10-29 12:50:23 +00:00
|
|
|
|
|
2000-02-24 22:45:18 +00:00
|
|
|
|
/*
|
|
|
|
|
* The returned port is an unsigned int - so we have to
|
|
|
|
|
* convert to a short in network byte order (big endian).
|
|
|
|
|
*/
|
|
|
|
|
n = (unsigned short)portNum;
|
|
|
|
|
sin.sin_port = NSSwapHostShortToBig(n);
|
1998-10-29 12:50:23 +00:00
|
|
|
|
|
2000-02-24 22:45:18 +00:00
|
|
|
|
/*
|
|
|
|
|
* The host addresses are given to us in network byte order
|
|
|
|
|
* so we just copy the address into place.
|
|
|
|
|
*/
|
|
|
|
|
sin.sin_addr = singleServer;
|
1998-10-29 12:50:23 +00:00
|
|
|
|
|
2000-02-24 22:45:18 +00:00
|
|
|
|
p = [TcpOutPort newForSendingToSockaddr: &sin
|
|
|
|
|
withAcceptedSocket: 0
|
|
|
|
|
pollingInPort: nil];
|
|
|
|
|
return AUTORELEASE(p);
|
|
|
|
|
}
|
|
|
|
|
else if (portClass == [GSTcpPort class])
|
|
|
|
|
{
|
|
|
|
|
NSString *addr;
|
|
|
|
|
NSHost *host;
|
|
|
|
|
|
|
|
|
|
addr = [NSString stringWithCString: inet_ntoa(singleServer)];
|
|
|
|
|
host = [NSHost hostWithAddress: addr];
|
|
|
|
|
return (NSPort*)[GSTcpPort portWithNumber: portNum
|
|
|
|
|
onHost: host
|
2000-02-27 17:16:39 +00:00
|
|
|
|
forceAddress: addr
|
|
|
|
|
listener: NO];
|
2000-02-24 22:45:18 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
NSLog(@"Unknown port class (%@) set for new port!", portClass);
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
}
|
1998-10-29 12:50:23 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (BOOL) registerPort: (NSPort*)port
|
|
|
|
|
forName: (NSString*)name
|
|
|
|
|
{
|
|
|
|
|
NSRunLoop *loop = [NSRunLoop currentRunLoop];
|
1999-09-21 19:07:27 +00:00
|
|
|
|
GSPortCom *com;
|
|
|
|
|
unsigned len;
|
2000-02-04 18:14:13 +00:00
|
|
|
|
NSDate *limit;
|
1998-10-29 12:50:23 +00:00
|
|
|
|
|
|
|
|
|
if (name == nil)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"attempt to register port with nil name"];
|
|
|
|
|
}
|
|
|
|
|
if (port == nil)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"attempt to register nil port"];
|
|
|
|
|
}
|
|
|
|
|
len = [name cStringLength];
|
|
|
|
|
if (len == 0)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"attempt to register port with no name"];
|
|
|
|
|
}
|
|
|
|
|
if (len > GDO_NAME_MAX_LEN)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"name of port is too long (max %d) bytes",
|
|
|
|
|
GDO_NAME_MAX_LEN];
|
|
|
|
|
}
|
2000-02-04 18:14:13 +00:00
|
|
|
|
|
|
|
|
|
limit = [NSDate dateWithTimeIntervalSinceNow: timeout];
|
1998-10-29 12:50:23 +00:00
|
|
|
|
/*
|
|
|
|
|
* Lock out other threads while doing I/O to gdomap
|
|
|
|
|
*/
|
|
|
|
|
[serverLock lock];
|
|
|
|
|
|
|
|
|
|
NS_DURING
|
|
|
|
|
{
|
1999-09-16 07:21:34 +00:00
|
|
|
|
NSMutableSet *known = NSMapGet(_portMap, port);
|
1999-09-21 19:07:27 +00:00
|
|
|
|
GSPortCom *tmp;
|
1998-10-30 08:40:03 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If there is no set of names for this port - create one.
|
|
|
|
|
*/
|
|
|
|
|
if (known == nil)
|
|
|
|
|
{
|
|
|
|
|
known = [NSMutableSet new];
|
1999-09-16 07:21:34 +00:00
|
|
|
|
NSMapInsert(_portMap, port, known);
|
1999-07-03 19:59:44 +00:00
|
|
|
|
RELEASE(known);
|
1998-10-30 08:40:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If this port has never been registered under any name, first
|
|
|
|
|
* send an unregister message to gdomap to ensure that any old
|
|
|
|
|
* names for the port (perhaps from a server that crashed without
|
|
|
|
|
* unregistering its ports) are no longer around.
|
|
|
|
|
*/
|
|
|
|
|
if ([known count] == 0)
|
|
|
|
|
{
|
1999-09-21 19:07:27 +00:00
|
|
|
|
com = [GSPortCom new];
|
|
|
|
|
[com startPortUnregistration: [(TcpInPort*)port portNumber]
|
|
|
|
|
withName: nil];
|
|
|
|
|
while ([limit timeIntervalSinceNow] > 0 && [com isActive] == YES)
|
1998-10-30 08:40:03 +00:00
|
|
|
|
{
|
1999-09-21 19:07:27 +00:00
|
|
|
|
[loop runMode: mode
|
|
|
|
|
beforeDate: limit];
|
1998-10-30 08:40:03 +00:00
|
|
|
|
}
|
1999-09-21 19:07:27 +00:00
|
|
|
|
[com close];
|
|
|
|
|
if ([com state] != GSPC_DONE)
|
1998-10-30 08:40:03 +00:00
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSPortTimeoutException
|
1999-09-21 19:07:27 +00:00
|
|
|
|
format: @"timed out unregistering port"];
|
1998-10-30 08:40:03 +00:00
|
|
|
|
}
|
1999-09-21 19:07:27 +00:00
|
|
|
|
tmp = com;
|
|
|
|
|
com = nil;
|
|
|
|
|
RELEASE(tmp);
|
1998-10-30 08:40:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
1999-09-21 19:07:27 +00:00
|
|
|
|
com = [GSPortCom new];
|
|
|
|
|
[com startPortRegistration: [(TcpInPort*)port portNumber]
|
|
|
|
|
withName: name];
|
|
|
|
|
while ([limit timeIntervalSinceNow] > 0 && [com isActive] == YES)
|
1998-10-29 12:50:23 +00:00
|
|
|
|
{
|
1999-09-21 19:07:27 +00:00
|
|
|
|
[loop runMode: mode
|
|
|
|
|
beforeDate: limit];
|
1998-10-29 12:50:23 +00:00
|
|
|
|
}
|
1999-09-21 19:07:27 +00:00
|
|
|
|
[com close];
|
|
|
|
|
if ([com state] != GSPC_DONE)
|
1998-10-29 12:50:23 +00:00
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSPortTimeoutException
|
1999-09-21 19:07:27 +00:00
|
|
|
|
format: @"timed out registering port %@", name];
|
1998-10-29 12:50:23 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
1999-09-21 19:07:27 +00:00
|
|
|
|
unsigned result;
|
1998-10-29 12:50:23 +00:00
|
|
|
|
|
1999-09-21 19:07:27 +00:00
|
|
|
|
result = GSSwapBigI32ToHost(*(gsu32*)[[com data] bytes]);
|
1998-10-29 12:50:23 +00:00
|
|
|
|
if (result == 0)
|
|
|
|
|
{
|
1999-01-09 06:49:06 +00:00
|
|
|
|
[NSException raise: NSGenericException
|
|
|
|
|
format: @"unable to register %@", name];
|
1998-10-29 12:50:23 +00:00
|
|
|
|
}
|
1998-10-30 08:40:03 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Add this name to the set of names that the port
|
|
|
|
|
* is known by and to the name map.
|
|
|
|
|
*/
|
|
|
|
|
[known addObject: name];
|
1999-09-16 07:21:34 +00:00
|
|
|
|
NSMapInsert(_nameMap, name, port);
|
1998-10-30 08:40:03 +00:00
|
|
|
|
}
|
1998-10-29 12:50:23 +00:00
|
|
|
|
}
|
1999-09-21 19:07:27 +00:00
|
|
|
|
tmp = com;
|
|
|
|
|
com = nil;
|
|
|
|
|
RELEASE(tmp);
|
1998-10-29 12:50:23 +00:00
|
|
|
|
}
|
|
|
|
|
NS_HANDLER
|
|
|
|
|
{
|
|
|
|
|
/*
|
1998-10-30 08:40:03 +00:00
|
|
|
|
* If we had a problem - close and unlock before continueing.
|
1998-10-29 12:50:23 +00:00
|
|
|
|
*/
|
1999-09-21 19:07:27 +00:00
|
|
|
|
RELEASE(com);
|
1998-10-29 12:50:23 +00:00
|
|
|
|
[serverLock unlock];
|
|
|
|
|
[localException raise];
|
|
|
|
|
}
|
|
|
|
|
NS_ENDHANDLER
|
|
|
|
|
[serverLock unlock];
|
1999-06-24 19:30:29 +00:00
|
|
|
|
return YES;
|
1998-10-29 12:50:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) removePortForName: (NSString*)name
|
|
|
|
|
{
|
|
|
|
|
NSRunLoop *loop = [NSRunLoop currentRunLoop];
|
1999-09-21 19:07:27 +00:00
|
|
|
|
GSPortCom *com;
|
|
|
|
|
unsigned len;
|
|
|
|
|
NSDate *limit = [NSDate dateWithTimeIntervalSinceNow: timeout];
|
1998-10-29 12:50:23 +00:00
|
|
|
|
|
|
|
|
|
if (name == nil)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"attempt to remove port with nil name"];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
len = [name cStringLength];
|
|
|
|
|
if (len == 0)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"attempt to remove port with no name"];
|
|
|
|
|
}
|
|
|
|
|
if (len > GDO_NAME_MAX_LEN)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"name of port is too long (max %d) bytes",
|
|
|
|
|
GDO_NAME_MAX_LEN];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Lock out other threads while doing I/O to gdomap
|
|
|
|
|
*/
|
|
|
|
|
[serverLock lock];
|
|
|
|
|
|
|
|
|
|
NS_DURING
|
|
|
|
|
{
|
1999-09-21 19:07:27 +00:00
|
|
|
|
GSPortCom *tmp;
|
1998-10-29 12:50:23 +00:00
|
|
|
|
|
1999-09-21 19:07:27 +00:00
|
|
|
|
com = [GSPortCom new];
|
|
|
|
|
[com startPortUnregistration: 0 withName: name];
|
|
|
|
|
while ([limit timeIntervalSinceNow] > 0 && [com isActive] == YES)
|
1998-10-29 12:50:23 +00:00
|
|
|
|
{
|
1999-09-21 19:07:27 +00:00
|
|
|
|
[loop runMode: mode
|
|
|
|
|
beforeDate: limit];
|
1998-10-29 12:50:23 +00:00
|
|
|
|
}
|
1999-09-21 19:07:27 +00:00
|
|
|
|
[com close];
|
|
|
|
|
if ([com state] != GSPC_DONE)
|
1998-10-29 12:50:23 +00:00
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSPortTimeoutException
|
1999-09-21 19:07:27 +00:00
|
|
|
|
format: @"timed out unregistering port"];
|
1998-10-29 12:50:23 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
1999-09-21 19:07:27 +00:00
|
|
|
|
unsigned result;
|
1998-10-29 12:50:23 +00:00
|
|
|
|
|
1999-09-21 19:07:27 +00:00
|
|
|
|
result = GSSwapBigI32ToHost(*(gsu32*)[[com data] bytes]);
|
1998-10-29 12:50:23 +00:00
|
|
|
|
if (result == 0)
|
|
|
|
|
{
|
1999-09-21 19:07:27 +00:00
|
|
|
|
NSLog(@"NSPortNameServer unable to unregister '%@'", name);
|
1998-10-29 12:50:23 +00:00
|
|
|
|
}
|
1998-10-30 08:40:03 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
NSPort *port;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Find the port that was registered for this name and
|
|
|
|
|
* remove the mapping table entries.
|
|
|
|
|
*/
|
1999-09-16 07:21:34 +00:00
|
|
|
|
port = NSMapGet(_nameMap, name);
|
1998-10-30 08:40:03 +00:00
|
|
|
|
if (port)
|
|
|
|
|
{
|
|
|
|
|
NSMutableSet *known;
|
|
|
|
|
|
1999-09-16 07:21:34 +00:00
|
|
|
|
NSMapRemove(_nameMap, name);
|
|
|
|
|
known = NSMapGet(_portMap, port);
|
1998-10-30 08:40:03 +00:00
|
|
|
|
if (known)
|
|
|
|
|
{
|
|
|
|
|
[known removeObject: name];
|
|
|
|
|
if ([known count] == 0)
|
|
|
|
|
{
|
1999-09-16 07:21:34 +00:00
|
|
|
|
NSMapRemove(_portMap, port);
|
1998-10-30 08:40:03 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
1998-10-29 12:50:23 +00:00
|
|
|
|
}
|
1999-09-21 19:07:27 +00:00
|
|
|
|
tmp = com;
|
|
|
|
|
com = nil;
|
|
|
|
|
RELEASE(tmp);
|
1998-10-29 12:50:23 +00:00
|
|
|
|
}
|
|
|
|
|
NS_HANDLER
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* If we had a problem - unlock before continueing.
|
|
|
|
|
*/
|
1999-09-21 19:07:27 +00:00
|
|
|
|
RELEASE(com);
|
1998-10-29 12:50:23 +00:00
|
|
|
|
[serverLock unlock];
|
|
|
|
|
[localException raise];
|
|
|
|
|
}
|
|
|
|
|
NS_ENDHANDLER
|
|
|
|
|
[serverLock unlock];
|
|
|
|
|
}
|
|
|
|
|
@end
|
|
|
|
|
|
1998-10-30 08:40:03 +00:00
|
|
|
|
@implementation NSPortNameServer (GNUstep)
|
|
|
|
|
|
2000-02-24 22:45:18 +00:00
|
|
|
|
+ (Class) setPortClass: (Class)c
|
|
|
|
|
{
|
|
|
|
|
Class old = portClass;
|
|
|
|
|
|
|
|
|
|
portClass = c;
|
|
|
|
|
return old;
|
|
|
|
|
}
|
|
|
|
|
|
2000-02-04 18:14:13 +00:00
|
|
|
|
/*
|
|
|
|
|
* Return the names under which the port is currently registered.
|
|
|
|
|
*/
|
|
|
|
|
- (NSArray*) namesForPort: (NSPort*)port
|
|
|
|
|
{
|
|
|
|
|
NSArray *names;
|
|
|
|
|
|
|
|
|
|
if (port == nil)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"attempt to get names for nil port"];
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
* Lock out other threads while grabbing port names.
|
|
|
|
|
*/
|
|
|
|
|
[serverLock lock];
|
|
|
|
|
names = [(NSSet*)NSMapGet(_portMap, port) allObjects];
|
|
|
|
|
[serverLock unlock];
|
|
|
|
|
return names;
|
|
|
|
|
}
|
|
|
|
|
|
1998-10-30 08:40:03 +00:00
|
|
|
|
/*
|
|
|
|
|
* Remove all names for a particular port - used when a port is
|
|
|
|
|
* invalidated.
|
|
|
|
|
*/
|
|
|
|
|
- (void) removePort: (NSPort*)port
|
|
|
|
|
{
|
|
|
|
|
[serverLock lock];
|
|
|
|
|
NS_DURING
|
|
|
|
|
{
|
1999-09-16 07:21:34 +00:00
|
|
|
|
NSMutableSet *known = (NSMutableSet*)NSMapGet(_portMap, port);
|
2000-02-04 18:14:13 +00:00
|
|
|
|
NSString *name;
|
1998-10-30 08:40:03 +00:00
|
|
|
|
|
|
|
|
|
while ((name = [known anyObject]) != nil)
|
|
|
|
|
{
|
|
|
|
|
[self removePortForName: name];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
NS_HANDLER
|
|
|
|
|
{
|
|
|
|
|
[serverLock unlock];
|
|
|
|
|
[localException raise];
|
|
|
|
|
}
|
|
|
|
|
NS_ENDHANDLER
|
2000-02-04 18:14:13 +00:00
|
|
|
|
[serverLock unlock];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Remove name for port iff it is registered.
|
|
|
|
|
*/
|
|
|
|
|
- (void) removePort: (NSPort*)port forName: (NSString*)name
|
|
|
|
|
{
|
1998-10-30 08:40:03 +00:00
|
|
|
|
[serverLock lock];
|
2000-02-04 18:14:13 +00:00
|
|
|
|
NS_DURING
|
|
|
|
|
{
|
|
|
|
|
NSMutableSet *known = (NSMutableSet*)NSMapGet(_portMap, port);
|
|
|
|
|
|
|
|
|
|
if ([known member: name] != nil)
|
|
|
|
|
{
|
|
|
|
|
[self removePortForName: name];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
NS_HANDLER
|
|
|
|
|
{
|
|
|
|
|
[serverLock unlock];
|
|
|
|
|
[localException raise];
|
|
|
|
|
}
|
|
|
|
|
NS_ENDHANDLER
|
|
|
|
|
[serverLock unlock];
|
1998-10-30 08:40:03 +00:00
|
|
|
|
}
|
|
|
|
|
@end
|
1999-09-21 19:07:27 +00:00
|
|
|
|
|
|
|
|
|
|