iUpdates for local private connections

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@17217 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-Macdonald 2003-07-15 05:21:34 +00:00
parent 874ab7af4f
commit 93fa4de6be
11 changed files with 5745 additions and 1399 deletions

View file

@ -2,6 +2,14 @@
* Source/NSConnection.m: When creating new connection with registered
name on host, ensure that send and receive ports are of same class.
* Source/NSMessagePort.m: New for private local connections.
* Source/NSMessagePortNameServer.m: New for private local connections.
* Source/NSPortNameServer.m: Made abstract
* Source/NSSocketPortNameServer.m: Concrete version based on original.
* Source/NSSocketPort.m: GSTcpPort.m renamed
Alexanders modifications added by RFM and altered slightly to use
NSSocketPort by default and to refrain from building new code under
windows, so this *shouldn't* break any existing code I hope.
2003-07-15 Richard Frith-Macdonald <rfm@gnu.org>

View file

@ -28,6 +28,7 @@
#define __NSPort_h_GNUSTEP_BASE_INCLUDE
#include <Foundation/NSObject.h>
#include <Foundation/NSMapTable.h>
#ifdef __MINGW__
#include <winsock2.h>
@ -42,6 +43,8 @@
@class NSDate;
@class NSRunLoop;
@class NSString;
@class NSPortMessage;
@class NSHost;
GS_EXPORT NSString * const NSPortTimeoutException; /* OPENSTEP */
@ -100,7 +103,35 @@ GS_EXPORT NSString* NSPortDidBecomeInvalidNotification;
typedef SOCKET NSSocketNativeHandle;
@interface NSSocketPort : NSPort <NSCoding, NSCopying>
@class GSTcpHandle;
@interface NSSocketPort : NSPort <GCFinalization>
{
NSRecursiveLock *myLock;
NSHost *host; /* OpenStep host for this port. */
NSString *address; /* Forced internet address. */
gsu16 portNum; /* TCP port in host byte order. */
SOCKET listener;
NSMapTable *handles; /* Handles indexed by socket. */
}
+ (NSSocketPort*) existingPortWithNumber: (gsu16)number
onHost: (NSHost*)host;
+ (NSSocketPort*) portWithNumber: (gsu16)number
onHost: (NSHost*)host
forceAddress: (NSString*)addr
listener: (BOOL)shouldListen;
- (void) addHandle: (GSTcpHandle*)handle forSend: (BOOL)send;
- (NSString*) address;
- (void) getFds: (SOCKET*)fds count: (int*)count;
- (GSTcpHandle*) handleForPort: (NSSocketPort*)recvPort
beforeDate: (NSDate*)when;
- (void) handlePortMessage: (NSPortMessage*)m;
- (NSHost*) host;
- (gsu16) portNumber;
- (void) removeHandle: (GSTcpHandle*)h;
/*
{
NSSocketNativeHandle _socket;
int _protocolFamily;
@ -108,7 +139,6 @@ typedef SOCKET NSSocketNativeHandle;
int _protocol;
NSData *_remoteAddrData;
}
- (id) init;
- (id) initWithTCPPort: (unsigned short)portNumber;
- (id) initWithProtocolFamily: (int)family
@ -131,8 +161,35 @@ typedef SOCKET NSSocketNativeHandle;
- (int) protocolFamily;
- (NSSocketNativeHandle) socket;
- (int) socketType;
*/
@end
@class GSMessageHandle;
@interface NSMessagePort : NSPort <GCFinalization>
{
NSData *name;
NSRecursiveLock *myLock;
NSMapTable *handles; /* Handles indexed by socket. */
int listener; /* Descriptor to listen on. */
}
- (int) _listener;
- (const unsigned char *) _name;
+ (NSMessagePort*) _portWithName: (const unsigned char *)name
listener: (BOOL)shouldListen;
- (void) addHandle: (GSMessageHandle*)handle forSend: (BOOL)send;
- (void) removeHandle: (GSMessageHandle*)handle;
- (void) handlePortMessage: (NSPortMessage*)m;
@end
#endif
#endif /* __NSPort_h_GNUSTEP_BASE_INCLUDE */

View file

@ -24,14 +24,13 @@
#ifndef __NSPortNameServer_h_GNUSTEP_BASE_INCLUDE
#define __NSPortNameServer_h_GNUSTEP_BASE_INCLUDE
#include <Foundation/NSObject.h>
#include <Foundation/NSObject.h>
#include <Foundation/NSMapTable.h>
@class NSPort, NSString, NSMutableArray;
@interface NSPortNameServer : NSObject
{
NSMapTable *_portMap; /* Registered ports information. */
NSMapTable *_nameMap; /* Registered names information. */
}
+ (id) systemDefaultPortNameServer;
- (NSPort*) portForName: (NSString*)name;
@ -46,9 +45,25 @@
@interface NSPortNameServer (GNUstep)
- (NSArray*) namesForPort: (NSPort*)port; /* return all names for port */
- (BOOL) removePort: (NSPort*)port; /* remove all names for port */
/* Remove the name if and only if it is registered by the given port. */
- (BOOL) removePort: (NSPort*)port forName: (NSString*)name;
@end
#endif
@interface NSSocketPortNameServer : NSPortNameServer
{
NSMapTable *_portMap; /* Registered ports information. */
NSMapTable *_nameMap; /* Registered names information. */
}
+ (id) sharedInstance;
@end
@interface NSMessagePortNameServer : NSPortNameServer
+ (id) sharedInstance;
@end
#endif

View file

@ -194,7 +194,6 @@ NSObject.m \
NSPage.m \
NSPipe.m \
NSPort.m \
GSTcpPort.m \
NSPortCoder.m \
NSPortMessage.m \
NSPortNameServer.m \
@ -206,6 +205,8 @@ NSRunLoop.m \
NSScanner.m \
NSSerializer.m \
NSSet.m \
NSSocketPort.m \
NSSocketPortNameServer.m \
NSString.m \
NSTask.m \
NSThread.m \
@ -222,6 +223,12 @@ NSZone.m \
externs.m \
objc-load.m
ifneq ($(GNUSTEP_TARGET_OS), mingw32)
BASE_MFILES += \
NSMessagePort.m \
NSMessagePortNameServer.m
endif
ifeq ($(WITH_FFI),libffi)
GNU_MFILES += cifframe.m
BASE_MFILES += GSFFIInvocation.m

1943
Source/NSMessagePort.m Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,361 @@
#include "Foundation/NSPortNameServer.h"
#include "Foundation/NSAutoreleasePool.h"
#include "Foundation/NSDebug.h"
#include "Foundation/NSException.h"
#include "Foundation/NSLock.h"
#include "Foundation/NSMapTable.h"
#include "Foundation/NSPathUtilities.h"
#include "Foundation/NSPort.h"
#include <sys/stat.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <string.h>
#include <sys/un.h>
static NSRecursiveLock *serverLock = nil;
static NSMessagePortNameServer *defaultServer = nil;
/*
Maps NSMessagePort objects to NSMutableArray:s of NSString:s. The array
is an array of names the port has been registered under by _us_.
Note that this map holds the names the port has been registered under at
some time. If the name is been unregistered by some other program, we can't
update the table, so we have to deal with the case where the array contains
names that the port isn't registered under.
Since we _have_to_ deal with this anyway, we handle it in -removePort: and
-removePort:forName:, and we don't bother removing entries in the map when
unregistering a name not for a specific port.
*/
static NSMapTable portToNamesMap;
@interface NSMessagePortNameServer (private)
+(NSString *) _pathForName: (NSString *)name;
@end
static void clean_up_names(void)
{
CREATE_AUTORELEASE_POOL(arp);
NSMapEnumerator mEnum;
NSMessagePort *port;
NSString *name;
mEnum = NSEnumerateMapTable(portToNamesMap);
while (NSNextMapEnumeratorPair(&mEnum, (void *)&port, (void *)&name))
{
[defaultServer removePort: port];
}
NSEndMapTableEnumeration(&mEnum);
DESTROY(arp);
}
@implementation NSMessagePortNameServer
+ (void) initialize
{
if (self == [NSMessagePortNameServer class])
{
serverLock = [NSRecursiveLock new];
portToNamesMap = NSCreateMapTable(NSNonRetainedObjectMapKeyCallBacks,
NSObjectMapValueCallBacks, 0);
atexit(clean_up_names);
}
}
+ (id) sharedInstance
{
if (defaultServer == nil)
{
NSMessagePortNameServer *s;
[serverLock lock];
if (defaultServer)
{
[serverLock unlock];
return defaultServer;
}
s = (NSMessagePortNameServer *)NSAllocateObject(self, 0, NSDefaultMallocZone());
defaultServer = s;
[serverLock unlock];
}
return defaultServer;
}
+(NSString *) _pathForName: (NSString *)name
{
NSString *path;
static NSString *base_path = nil;
[serverLock lock];
if (!base_path)
{
path=NSTemporaryDirectory();
path = [path stringByAppendingPathComponent: @"NSMessagePort"];
mkdir([path fileSystemRepresentation], 0700);
path = [path stringByAppendingPathComponent: @"names"];
mkdir([path fileSystemRepresentation], 0700);
base_path = RETAIN(path);
}
else
{
path = base_path;
}
[serverLock unlock];
path = [path stringByAppendingPathComponent: name];
return path;
}
+(BOOL) _livePort: (NSString *)path
{
FILE *f;
char socket_path[512];
int pid;
struct stat sb;
NSDebugLLog(@"NSMessagePort", @"_livePort: %@", path);
f = fopen([path fileSystemRepresentation], "rt");
if (!f)
{
NSDebugLLog(@"NSMessagePort", @"not live, couldn't open file (%m)");
return NO;
}
fgets(socket_path, sizeof(socket_path), f);
if (strlen(socket_path) > 0) socket_path[strlen(socket_path) - 1] = 0;
fscanf(f, "%i", &pid);
fclose(f);
if (stat(socket_path,&sb)<0)
{
unlink([path fileSystemRepresentation]);
NSDebugLLog(@"NSMessagePort", @"not live, couldn't stat socket (%m)");
return NO;
}
if (kill(pid,0)<0)
{
unlink([path fileSystemRepresentation]);
unlink(socket_path);
NSDebugLLog(@"NSMessagePort", @"not live, no such process (%m)");
return NO;
}
{
struct sockaddr_un sockAddr;
int desc;
memset(&sockAddr, '\0', sizeof(sockAddr));
sockAddr.sun_family = AF_LOCAL;
strncpy(sockAddr.sun_path, socket_path, sizeof(sockAddr.sun_path));
if ((desc = socket(PF_LOCAL, SOCK_STREAM, PF_UNSPEC)) < 0)
{
unlink([path fileSystemRepresentation]);
unlink(socket_path);
NSDebugLLog(@"NSMessagePort", @"couldn't create socket, assuming not live (%m)");
return NO;
}
if (connect(desc, (struct sockaddr*)&sockAddr, SUN_LEN(&sockAddr)) < 0)
{
unlink([path fileSystemRepresentation]);
unlink(socket_path);
NSDebugLLog(@"NSMessagePort", @"not live, can't connect (%m)");
return NO;
}
close(desc);
}
NSDebugLLog(@"NSMessagePort", @"port is live");
return YES;
}
- (NSPort *) portForName: (NSString *)name
onHost: (NSString *)host
{
NSString *path;
FILE *f;
char socket_path[512];
NSDebugLLog(@"NSMessagePort", @"portForName: %@ host: %@", name, host);
if ([host length] && ![host isEqual: @"*"])
{
NSDebugLLog(@"NSMessagePort", @"non-local host");
return nil;
}
path = [isa _pathForName: name];
if (![isa _livePort: path])
{
NSDebugLLog(@"NSMessagePort", @"not a live port");
return nil;
}
f = fopen([path fileSystemRepresentation], "rt");
if (!f)
{
NSDebugLLog(@"NSMessagePort", @"can't open file (%m)");
return nil;
}
fgets(socket_path, sizeof(socket_path), f);
if (strlen(socket_path) > 0) socket_path[strlen(socket_path) - 1] = 0;
fclose(f);
NSDebugLLog(@"NSMessagePort", @"got %s", socket_path);
return [NSMessagePort _portWithName: socket_path
listener: NO];
}
- (BOOL) registerPort: (NSPort *)port
forName: (NSString *)name
{
int fd;
unsigned char buf[32];
NSString *path;
const unsigned char *socket_name;
NSDebugLLog(@"NSMessagePort", @"register %@ as %@\n", port, name);
if (![port isKindOfClass: [NSMessagePort class]])
{
[NSException raise: NSInvalidArgumentException
format: @"Attempted to register a non-NSMessagePort with NSMessagePortNameServer"];
return NO;
}
path=[isa _pathForName: name];
if ([isa _livePort: path])
{
NSDebugLLog(@"NSMessagePort", @"fail, is a live port");
return NO;
}
fd = open([path fileSystemRepresentation], O_CREAT|O_EXCL|O_WRONLY, 0600);
if (fd < 0)
{
NSDebugLLog(@"NSMessagePort", @"fail, can't open file (%m)");
return NO;
}
socket_name = [(NSMessagePort *)port _name];
write(fd, socket_name, strlen(socket_name));
write(fd, "\n", 1);
sprintf(buf, "%i\n", getpid());
write(fd, buf, strlen(buf));
close(fd);
{
NSMutableArray *a;
[serverLock lock];
a = NSMapGet(portToNamesMap, port);
if (!a)
{
a = [[NSMutableArray alloc] init];
NSMapInsert(portToNamesMap, port, a);
RELEASE(a);
}
[a addObject: [name copy]];
[serverLock unlock];
}
return YES;
}
- (BOOL) removePortForName: (NSString *)name
{
NSString *path;
NSDebugLLog(@"NSMessagePort", @"removePortForName: %@", name);
path=[isa _pathForName: name];
unlink([path fileSystemRepresentation]);
return YES;
}
- (NSArray *) namesForPort: (NSPort *)port
{
NSMutableArray *a;
[serverLock lock];
a = NSMapGet(portToNamesMap, port);
a = [a copy];
[serverLock unlock];
return a;
}
- (BOOL) removePort: (NSPort *)port
{
NSMutableArray *a;
int i;
NSDebugLLog(@"NSMessagePort", @"removePort: %@", port);
[serverLock lock];
a = NSMapGet(portToNamesMap, port);
for (i = 0; i < [a count]; i++)
{
[self removePort: port forName: [a objectAtIndex: i]];
}
NSMapRemove(portToNamesMap, port);
[serverLock unlock];
return YES;
}
- (BOOL) removePort: (NSPort*)port forName: (NSString*)name
{
FILE *f;
char socket_path[512];
NSString *path;
const unsigned char *port_path;
NSDebugLLog(@"NSMessagePort", @"removePort: %@ forName: %@", port, name);
path = [isa _pathForName: name];
f = fopen([path fileSystemRepresentation], "rt");
if (!f)
return YES;
fgets(socket_path, sizeof(socket_path), f);
if (strlen(socket_path) > 0) socket_path[strlen(socket_path) - 1] = 0;
fclose(f);
port_path = [(NSMessagePort *)port _name];
if (!strcmp(socket_path, port_path))
{
unlink([path fileSystemRepresentation]);
}
return YES;
}
@end

View file

@ -34,7 +34,8 @@
#include "Foundation/NSRunLoop.h"
#include "Foundation/NSAutoreleasePool.h"
@class GSTcpPort;
@class NSMessagePort;
@implementation NSPort
@ -60,13 +61,17 @@ Class NSPort_concrete_class;
if (self == [NSPort class])
{
NSPort_abstract_class = self;
NSPort_concrete_class = [GSTcpPort class];
NSPort_concrete_class = [NSSocketPort class];
// NSPort_concrete_class = [NSMessagePort class];
}
}
+ (NSPort*) port
{
return AUTORELEASE([NSPort_concrete_class new]);
if (self == NSPort_abstract_class)
return AUTORELEASE([NSPort_concrete_class new]);
else
return AUTORELEASE([self new]);
}
+ (NSPort*) portWithMachPort: (int)machPort
@ -119,20 +124,13 @@ Class NSPort_concrete_class;
*/
- (void) invalidate
{
NSAutoreleasePool *arp;
CREATE_AUTORELEASE_POOL(arp);
[[NSPortNameServer systemDefaultPortNameServer] removePort: self];
_is_valid = NO;
/*
* Use a local autorelease pool when invalidating so that we know that
* anything refering to this port during the invalidation process is
* released immediately.
*/
arp = [NSAutoreleasePool new];
[[NSNotificationCenter defaultCenter]
postNotificationName: NSPortDidBecomeInvalidNotification
object: self];
[arp release];
RELEASE(arp);
}
- (BOOL) isValid

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -75,7 +75,7 @@ __objc_class_name_NSGMutableString
__objc_class_name_NSGString
__objc_class_name_NSImmutableString
__objc_class_name_GSTcpHandle
__objc_class_name_GSTcpPort
__objc_class_name_NSSocketPort
__objc_class_name_GSValue
__objc_class_name_GSNonretainedObjectValue
__objc_class_name_GSPointValue
@ -171,6 +171,7 @@ __objc_class_name_NSPortCoder
__objc_class_name_NSPortMessage
__objc_class_name_GSPortCom
__objc_class_name_NSPortNameServer
__objc_class_name_NSSocketPortNameServer
__objc_class_name__NSConcreteProcessInfo
__objc_class_name_NSProcessInfo
__objc_class_name_NSProtocolChecker