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:
CaS 2003-07-15 05:21:34 +00:00
parent 1561800b3b
commit 30146f8f24
11 changed files with 5745 additions and 1399 deletions

View file

@ -2,6 +2,14 @@
* Source/NSConnection.m: When creating new connection with registered * Source/NSConnection.m: When creating new connection with registered
name on host, ensure that send and receive ports are of same class. 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> 2003-07-15 Richard Frith-Macdonald <rfm@gnu.org>

View file

@ -28,6 +28,7 @@
#define __NSPort_h_GNUSTEP_BASE_INCLUDE #define __NSPort_h_GNUSTEP_BASE_INCLUDE
#include <Foundation/NSObject.h> #include <Foundation/NSObject.h>
#include <Foundation/NSMapTable.h>
#ifdef __MINGW__ #ifdef __MINGW__
#include <winsock2.h> #include <winsock2.h>
@ -42,6 +43,8 @@
@class NSDate; @class NSDate;
@class NSRunLoop; @class NSRunLoop;
@class NSString; @class NSString;
@class NSPortMessage;
@class NSHost;
GS_EXPORT NSString * const NSPortTimeoutException; /* OPENSTEP */ GS_EXPORT NSString * const NSPortTimeoutException; /* OPENSTEP */
@ -100,7 +103,35 @@ GS_EXPORT NSString* NSPortDidBecomeInvalidNotification;
typedef SOCKET NSSocketNativeHandle; 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; NSSocketNativeHandle _socket;
int _protocolFamily; int _protocolFamily;
@ -108,7 +139,6 @@ typedef SOCKET NSSocketNativeHandle;
int _protocol; int _protocol;
NSData *_remoteAddrData; NSData *_remoteAddrData;
} }
- (id) init; - (id) init;
- (id) initWithTCPPort: (unsigned short)portNumber; - (id) initWithTCPPort: (unsigned short)portNumber;
- (id) initWithProtocolFamily: (int)family - (id) initWithProtocolFamily: (int)family
@ -131,8 +161,35 @@ typedef SOCKET NSSocketNativeHandle;
- (int) protocolFamily; - (int) protocolFamily;
- (NSSocketNativeHandle) socket; - (NSSocketNativeHandle) socket;
- (int) socketType; - (int) socketType;
*/
@end @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
#endif /* __NSPort_h_GNUSTEP_BASE_INCLUDE */ #endif /* __NSPort_h_GNUSTEP_BASE_INCLUDE */

View file

@ -24,14 +24,13 @@
#ifndef __NSPortNameServer_h_GNUSTEP_BASE_INCLUDE #ifndef __NSPortNameServer_h_GNUSTEP_BASE_INCLUDE
#define __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; @class NSPort, NSString, NSMutableArray;
@interface NSPortNameServer : NSObject @interface NSPortNameServer : NSObject
{ {
NSMapTable *_portMap; /* Registered ports information. */
NSMapTable *_nameMap; /* Registered names information. */
} }
+ (id) systemDefaultPortNameServer; + (id) systemDefaultPortNameServer;
- (NSPort*) portForName: (NSString*)name; - (NSPort*) portForName: (NSString*)name;
@ -46,9 +45,25 @@
@interface NSPortNameServer (GNUstep) @interface NSPortNameServer (GNUstep)
- (NSArray*) namesForPort: (NSPort*)port; /* return all names for port */ - (NSArray*) namesForPort: (NSPort*)port; /* return all names for port */
- (BOOL) removePort: (NSPort*)port; /* remove 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; - (BOOL) removePort: (NSPort*)port forName: (NSString*)name;
@end @end
#endif #endif
@interface NSSocketPortNameServer : NSPortNameServer
{
NSMapTable *_portMap; /* Registered ports information. */
NSMapTable *_nameMap; /* Registered names information. */
}
+ (id) sharedInstance;
@end
@interface NSMessagePortNameServer : NSPortNameServer
+ (id) sharedInstance;
@end
#endif #endif

View file

@ -194,7 +194,6 @@ NSObject.m \
NSPage.m \ NSPage.m \
NSPipe.m \ NSPipe.m \
NSPort.m \ NSPort.m \
GSTcpPort.m \
NSPortCoder.m \ NSPortCoder.m \
NSPortMessage.m \ NSPortMessage.m \
NSPortNameServer.m \ NSPortNameServer.m \
@ -206,6 +205,8 @@ NSRunLoop.m \
NSScanner.m \ NSScanner.m \
NSSerializer.m \ NSSerializer.m \
NSSet.m \ NSSet.m \
NSSocketPort.m \
NSSocketPortNameServer.m \
NSString.m \ NSString.m \
NSTask.m \ NSTask.m \
NSThread.m \ NSThread.m \
@ -222,6 +223,12 @@ NSZone.m \
externs.m \ externs.m \
objc-load.m objc-load.m
ifneq ($(GNUSTEP_TARGET_OS), mingw32)
BASE_MFILES += \
NSMessagePort.m \
NSMessagePortNameServer.m
endif
ifeq ($(WITH_FFI),libffi) ifeq ($(WITH_FFI),libffi)
GNU_MFILES += cifframe.m GNU_MFILES += cifframe.m
BASE_MFILES += GSFFIInvocation.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/NSRunLoop.h"
#include "Foundation/NSAutoreleasePool.h" #include "Foundation/NSAutoreleasePool.h"
@class GSTcpPort;
@class NSMessagePort;
@implementation NSPort @implementation NSPort
@ -60,13 +61,17 @@ Class NSPort_concrete_class;
if (self == [NSPort class]) if (self == [NSPort class])
{ {
NSPort_abstract_class = self; NSPort_abstract_class = self;
NSPort_concrete_class = [GSTcpPort class]; NSPort_concrete_class = [NSSocketPort class];
// NSPort_concrete_class = [NSMessagePort class];
} }
} }
+ (NSPort*) port + (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 + (NSPort*) portWithMachPort: (int)machPort
@ -119,20 +124,13 @@ Class NSPort_concrete_class;
*/ */
- (void) invalidate - (void) invalidate
{ {
NSAutoreleasePool *arp; CREATE_AUTORELEASE_POOL(arp);
[[NSPortNameServer systemDefaultPortNameServer] removePort: self];
_is_valid = NO; _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] [[NSNotificationCenter defaultCenter]
postNotificationName: NSPortDidBecomeInvalidNotification postNotificationName: NSPortDidBecomeInvalidNotification
object: self]; object: self];
[arp release]; RELEASE(arp);
} }
- (BOOL) isValid - (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_NSGString
__objc_class_name_NSImmutableString __objc_class_name_NSImmutableString
__objc_class_name_GSTcpHandle __objc_class_name_GSTcpHandle
__objc_class_name_GSTcpPort __objc_class_name_NSSocketPort
__objc_class_name_GSValue __objc_class_name_GSValue
__objc_class_name_GSNonretainedObjectValue __objc_class_name_GSNonretainedObjectValue
__objc_class_name_GSPointValue __objc_class_name_GSPointValue
@ -171,6 +171,7 @@ __objc_class_name_NSPortCoder
__objc_class_name_NSPortMessage __objc_class_name_NSPortMessage
__objc_class_name_GSPortCom __objc_class_name_GSPortCom
__objc_class_name_NSPortNameServer __objc_class_name_NSPortNameServer
__objc_class_name_NSSocketPortNameServer
__objc_class_name__NSConcreteProcessInfo __objc_class_name__NSConcreteProcessInfo
__objc_class_name_NSProcessInfo __objc_class_name_NSProcessInfo
__objc_class_name_NSProtocolChecker __objc_class_name_NSProtocolChecker