mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
more mingw32 updates
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@21951 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
574ac81e17
commit
32990455b2
10 changed files with 955 additions and 297 deletions
12
ChangeLog
12
ChangeLog
|
@ -1,3 +1,15 @@
|
|||
2005-11-05 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/GSCompatibility.m: don't generate macos-x (xml) property
|
||||
lists if we can't parse them.
|
||||
* Source/GSHTTPURLHandle.m: debug fix for mingw32
|
||||
* Headers/Foundation/NSFileManager.h: add mingw32 conditionals.
|
||||
* Headers/Foundation/NSString.h: add mingw32 conditionals.
|
||||
* Source/NSMessagePort.m: remove mingw32 stuff
|
||||
* Source/win32/NSMessagePort.m: added partial implementation
|
||||
* Source/win32/NSMessagePortNewServer.m: added skeleton
|
||||
* Source/win32/GNUmakefile: build message port classes
|
||||
|
||||
2005-11-04 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* configure.ac: Cope with backslashes in values from GNUstep.conf
|
||||
|
|
|
@ -226,7 +226,11 @@
|
|||
* with unicode strings.<br />
|
||||
* Raises an exception if the character conversion is not possible.
|
||||
*/
|
||||
#if defined(__MINGW32__)
|
||||
- (const unichar*) fileSystemRepresentationWithPath: (NSString*)path;
|
||||
#else
|
||||
- (const char*) fileSystemRepresentationWithPath: (NSString*)path;
|
||||
#endif
|
||||
|
||||
- (BOOL) isExecutableFileAtPath: (NSString*)path;
|
||||
- (BOOL) isDeletableFileAtPath: (NSString*)path;
|
||||
|
@ -241,8 +245,23 @@
|
|||
- (NSString*) pathContentOfSymbolicLinkAtPath: (NSString*)path;
|
||||
- (BOOL) removeFileAtPath: (NSString*)path
|
||||
handler: (id)handler;
|
||||
|
||||
/**
|
||||
* Convert to OpenStep internal string format from a string in
|
||||
* the local filesystem format, as returned by system functions.<br />
|
||||
* This representation may vary between filesystems.<br />
|
||||
* On windows, the filesystem representation is 16-bit unicode and is expected
|
||||
* to have come from the variant of a system call which works
|
||||
* with unicode strings.
|
||||
*/
|
||||
#if defined(__MINGW32__)
|
||||
- (NSString*) stringWithFileSystemRepresentation: (const unichar*)string
|
||||
length: (unsigned int)len;
|
||||
#else
|
||||
- (NSString*) stringWithFileSystemRepresentation: (const char*)string
|
||||
length: (unsigned int)len;
|
||||
#endif
|
||||
|
||||
- (NSArray*) subpathsAtPath: (NSString*)path;
|
||||
|
||||
@end /* NSFileManager */
|
||||
|
|
|
@ -339,10 +339,14 @@ enum {
|
|||
* automatically freed soon after it is returned, so copy it if you need it
|
||||
* for long.<br />
|
||||
* NB. On ms-windows the filesystem representation of a path is a 16-bit
|
||||
* unicode character string, so you should only path the value returned by
|
||||
* unicode character string, so you should only pass the value returned by
|
||||
* this method to functions expecting wide characters.
|
||||
*/
|
||||
#if defined(__MINGW32__)
|
||||
- (const unichar*) fileSystemRepresentation;
|
||||
#else
|
||||
- (const char*) fileSystemRepresentation;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Converts the receiver to a C string path using the character encoding
|
||||
|
@ -350,10 +354,15 @@ enum {
|
|||
* into buffer if it is shorter than size, otherwise NO is returned.<br />
|
||||
* NB. On ms-windows the filesystem representation of a path is a 16-bit
|
||||
* unicode character string, so the buffer you pass to this method must be
|
||||
* twice as long as the number of characters you expect to receive.
|
||||
* twice as many bytes as the size (number of characters) you expect to receive.
|
||||
*/
|
||||
#if defined(__MINGW32__)
|
||||
- (BOOL) getFileSystemRepresentation: (unichar*)buffer
|
||||
maxLength: (unsigned int)size;
|
||||
#else
|
||||
- (BOOL) getFileSystemRepresentation: (char*)buffer
|
||||
maxLength: (unsigned int)size;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns a string containing the last path component of the receiver.<br />
|
||||
|
|
|
@ -223,6 +223,7 @@ NSZone.m \
|
|||
externs.m \
|
||||
objc-load.m
|
||||
|
||||
|
||||
ifneq ($(GNUSTEP_TARGET_OS), mingw32)
|
||||
BASE_MFILES += \
|
||||
NSMessagePort.m \
|
||||
|
|
|
@ -50,8 +50,12 @@ BOOL GSMacOSXCompatibleGeometry(void)
|
|||
|
||||
BOOL GSMacOSXCompatiblePropertyLists(void)
|
||||
{
|
||||
#if defined(HAVE_LIBXML)
|
||||
if (GSUserDefaultsFlag(NSWriteOldStylePropertyLists) == YES)
|
||||
return NO;
|
||||
return GSUserDefaultsFlag(GSMacOSXCompatible);
|
||||
#else
|
||||
return NO;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -221,8 +221,13 @@ static void debugRead(GSHTTPURLHandle *handle, NSData *data)
|
|||
int d;
|
||||
|
||||
[debugLock lock];
|
||||
#if defined(__MINGW__)
|
||||
d = _wopen((const unichar*)[debugFile fileSystemRepresentation],
|
||||
O_WRONLY|O_CREAT|O_APPEND, 0644);
|
||||
#else
|
||||
d = open([debugFile fileSystemRepresentation],
|
||||
O_WRONLY|O_CREAT|O_APPEND, 0644);
|
||||
O_WRONLY|O_CREAT|O_APPEND, 0644);
|
||||
#endif
|
||||
if (d >= 0)
|
||||
{
|
||||
s = [NSString stringWithFormat: @"\nRead for %x at %@ %u bytes - '",
|
||||
|
@ -240,8 +245,13 @@ static void debugWrite(GSHTTPURLHandle *handle, NSData *data)
|
|||
int d;
|
||||
|
||||
[debugLock lock];
|
||||
#if defined(__MINGW__)
|
||||
d = _wopen((const unichar*)[debugFile fileSystemRepresentation],
|
||||
O_WRONLY|O_CREAT|O_APPEND, 0644);
|
||||
#else
|
||||
d = open([debugFile fileSystemRepresentation],
|
||||
O_WRONLY|O_CREAT|O_APPEND, 0644);
|
||||
O_WRONLY|O_CREAT|O_APPEND, 0644);
|
||||
#endif
|
||||
if (d >= 0)
|
||||
{
|
||||
s = [NSString stringWithFormat: @"\nWrite for %x at %@ %u bytes - '",
|
||||
|
|
|
@ -49,7 +49,6 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if !defined(__MINGW32__)
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h> /* for gethostname() */
|
||||
#endif
|
||||
|
@ -90,7 +89,6 @@
|
|||
#if defined(__svr4__)
|
||||
#include <sys/stropts.h>
|
||||
#endif
|
||||
#endif /* !__MINGW32__ */
|
||||
|
||||
/*
|
||||
* Largest chunk of data possible in DO
|
||||
|
@ -192,9 +190,6 @@ newDataWithEncodedPort(NSMessagePort *port)
|
|||
return data;
|
||||
}
|
||||
|
||||
|
||||
#if !defined(__MINGW32__)
|
||||
|
||||
/* Older systems (Solaris) compatibility */
|
||||
#ifndef AF_LOCAL
|
||||
#define AF_LOCAL AF_UNIX
|
||||
|
@ -1962,290 +1957,3 @@ static unsigned wordAlign;
|
|||
|
||||
@end
|
||||
|
||||
#else
|
||||
|
||||
@implementation NSMessagePort
|
||||
|
||||
static NSRecursiveLock *messagePortLock = nil;
|
||||
|
||||
/*
|
||||
* Maps port name to NSMessagePort objects.
|
||||
*/
|
||||
static NSMapTable *messagePortMap = 0;
|
||||
static Class messagePortClass;
|
||||
|
||||
typedef struct {
|
||||
NSString *_name;
|
||||
NSRecursiveLock *_lock;
|
||||
HANDLE *_handle;
|
||||
} internal;
|
||||
#define myName(P) ((internal*)(P)->_internal)->_name
|
||||
#define myLock(P) ((internal*)(P)->_internal)->_lock
|
||||
#define myHandle(P) ((internal*)(P)->_internal)->_handle
|
||||
|
||||
#if NEED_WORD_ALIGNMENT
|
||||
static unsigned wordAlign;
|
||||
#endif
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [NSMessagePort class])
|
||||
{
|
||||
#if NEED_WORD_ALIGNMENT
|
||||
wordAlign = objc_alignof_type(@encode(gsu32));
|
||||
#endif
|
||||
messagePortClass = self;
|
||||
messagePortMap = NSCreateMapTable(NSNonRetainedObjectMapKeyCallBacks,
|
||||
NSNonOwnedPointerMapValueCallBacks, 0);
|
||||
|
||||
messagePortLock = [GSLazyRecursiveLock new];
|
||||
}
|
||||
}
|
||||
|
||||
+ (id) new
|
||||
{
|
||||
static int unique_index = 0;
|
||||
unsigned char path[BUFSIZ];
|
||||
|
||||
M_LOCK(messagePortLock);
|
||||
sprintf(path, "\\\\.\\mailslot\\NSMessagePort\\%i.%i",
|
||||
[[NSProcessInfo processInfo] processIdentifier], unique_index++);
|
||||
M_UNLOCK(messagePortLock);
|
||||
|
||||
return RETAIN([self _portWithName: path listener: YES]);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the preferred initialisation method for NSMessagePort
|
||||
*
|
||||
* 'mailslotName' is the name of the mailslot to use.
|
||||
*/
|
||||
+ (NSMessagePort*) _portWithName: (const unsigned char*)mailslotName
|
||||
listener: (BOOL)shouldListen
|
||||
{
|
||||
NSMessagePort *port = nil;
|
||||
|
||||
M_LOCK(messagePortLock);
|
||||
|
||||
/*
|
||||
* First try to find a pre-existing port.
|
||||
*/
|
||||
port = (NSMessagePort*)NSMapGet(messagePortMap, mailslotName);
|
||||
|
||||
if (port == nil)
|
||||
{
|
||||
port = (NSMessagePort*)NSAllocateObject(self, 0, NSDefaultMallocZone());
|
||||
myName(port) = [[NSString alloc] initWithUTF8String: mailslotName];
|
||||
myHandle(port) = INVALID_HANDLE_VALUE;
|
||||
myLock(port) = [GSLazyRecursiveLock new];
|
||||
port->_is_valid = YES;
|
||||
|
||||
if (shouldListen == YES)
|
||||
{
|
||||
myHandle(port) = CreateMailslot([myName(port) UTF8String], 0, 0, 0);
|
||||
if (myHandle(port) == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
NSLog(@"unable to create mailslot - %s", GSLastErrorStr(errno));
|
||||
DESTROY(port);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Make sure we have the map table for this port.
|
||||
*/
|
||||
NSMapInsert(messagePortMap, (void*)myName(port), (void*)port);
|
||||
NSDebugMLLog(@"NSMessagePort", @"Created listening port: %@",
|
||||
port);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Make sure we have the map table for this port.
|
||||
*/
|
||||
NSMapInsert(messagePortMap, (void*)myName(port), (void*)port);
|
||||
NSDebugMLLog(@"NSMessagePort", @"Created speaking port: %@", port);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RETAIN(port);
|
||||
NSDebugMLLog(@"NSMessagePort", @"Using pre-existing port: %@", port);
|
||||
}
|
||||
IF_NO_GC(AUTORELEASE(port));
|
||||
|
||||
M_UNLOCK(messagePortLock);
|
||||
return port;
|
||||
}
|
||||
|
||||
- (id) copyWithZone: (NSZone*)zone
|
||||
{
|
||||
return RETAIN(self);
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[self gcFinalize];
|
||||
DESTROY(myName(self));
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSString*) description
|
||||
{
|
||||
NSString *desc;
|
||||
|
||||
desc = [NSString stringWithFormat: @"<NSMessagePort %p with name %@>",
|
||||
self, myName(self)];
|
||||
return desc;
|
||||
}
|
||||
|
||||
- (void) gcFinalize
|
||||
{
|
||||
NSDebugMLLog(@"NSMessagePort", @"NSMessagePort 0x%x finalized", self);
|
||||
[self invalidate];
|
||||
}
|
||||
|
||||
- (id) conversation: (NSPort*)recvPort
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void) handlePortMessage: (NSPortMessage*)m
|
||||
{
|
||||
id d = [self delegate];
|
||||
|
||||
if (d == nil)
|
||||
{
|
||||
NSDebugMLLog(@"NSMessagePort",
|
||||
@"No delegate to handle incoming message", 0);
|
||||
return;
|
||||
}
|
||||
if ([d respondsToSelector: @selector(handlePortMessage:)] == NO)
|
||||
{
|
||||
NSDebugMLLog(@"NSMessagePort", @"delegate doesn't handle messages", 0);
|
||||
return;
|
||||
}
|
||||
[d handlePortMessage: m];
|
||||
}
|
||||
|
||||
- (unsigned) hash
|
||||
{
|
||||
return [myName(self) hash];
|
||||
}
|
||||
|
||||
- (id) init
|
||||
{
|
||||
RELEASE(self);
|
||||
self = [messagePortClass new];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) invalidate
|
||||
{
|
||||
if ([self isValid] == YES)
|
||||
{
|
||||
M_LOCK(myLock(self));
|
||||
if ([self isValid] == YES)
|
||||
{
|
||||
M_LOCK(messagePortLock);
|
||||
if (myHandle(self) != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
(void) CloseHandle(myHandle(self));
|
||||
myHandle(self) = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
NSMapRemove(messagePortMap, (void*)myName(self));
|
||||
M_UNLOCK(messagePortLock);
|
||||
|
||||
[[NSMessagePortNameServer sharedInstance] removePort: self];
|
||||
[super invalidate];
|
||||
}
|
||||
M_UNLOCK(myLock(self));
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL) isEqual: (id)anObject
|
||||
{
|
||||
if (anObject == self)
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
if ([anObject class] == [self class])
|
||||
{
|
||||
NSMessagePort *o = (NSMessagePort*)anObject;
|
||||
|
||||
return [myName(o) isEqual: myName(self)];
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void) receivedEvent: (void*)data
|
||||
type: (RunLoopEventType)type
|
||||
extra: (void*)extra
|
||||
forMode: (NSString*)mode
|
||||
{
|
||||
HANDLE h = (HANDLE)(gsaddr)extra;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* This returns the amount of space that a port coder should reserve at the
|
||||
* start of its encoded data so that the NSMessagePort can insert header info
|
||||
* into the data.
|
||||
* The idea is that a message consisting of a single data item with space at
|
||||
* the start can be written directly without having to copy data to another
|
||||
* buffer etc.
|
||||
*/
|
||||
- (unsigned int) reservedSpaceLength
|
||||
{
|
||||
return sizeof(GSPortItemHeader) + sizeof(GSPortMsgHeader);
|
||||
}
|
||||
|
||||
- (BOOL) sendBeforeDate: (NSDate*)when
|
||||
msgid: (int)msgId
|
||||
components: (NSMutableArray*)components
|
||||
from: (NSPort*)receivingPort
|
||||
reserved: (unsigned)length
|
||||
{
|
||||
BOOL sent = NO;
|
||||
unsigned rl;
|
||||
|
||||
if ([self isValid] == NO)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
if ([components count] == 0)
|
||||
{
|
||||
NSLog(@"empty components sent");
|
||||
return NO;
|
||||
}
|
||||
/*
|
||||
* If the reserved length in the first data object is wrong - we have to
|
||||
* fail, unless it's zero, in which case we can insert a data object for
|
||||
* the header.
|
||||
*/
|
||||
rl = [self reservedSpaceLength];
|
||||
if (length != 0 && length != rl)
|
||||
{
|
||||
NSLog(@"bad reserved length - %u", length);
|
||||
return NO;
|
||||
}
|
||||
if ([receivingPort isKindOfClass: messagePortClass] == NO)
|
||||
{
|
||||
NSLog(@"woah there - receiving port is not the correct type");
|
||||
return NO;
|
||||
}
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
- (NSDate*) timedOutEvent: (void*)data
|
||||
type: (RunLoopEventType)type
|
||||
forMode: (NSString*)mode
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __MINGW32__ */
|
||||
|
||||
|
|
|
@ -32,9 +32,11 @@ SUBPROJECT_NAME = win32
|
|||
win32_OBJC_FILES =\
|
||||
GSRunLoopCtxt.m \
|
||||
GSRunLoopWatcher.m \
|
||||
NSMessagePortWin32.m \
|
||||
NSRunLoopWin32.m \
|
||||
NSUserDefaultsWin32.m \
|
||||
Win32Support.m \
|
||||
Win32_Utilities.m NSUserDefaultsWin32.m
|
||||
Win32_Utilities.m
|
||||
|
||||
-include Makefile.preamble
|
||||
|
||||
|
|
404
Source/win32/NSMessagePortNameServerWin32.m
Normal file
404
Source/win32/NSMessagePortNameServerWin32.m
Normal file
|
@ -0,0 +1,404 @@
|
|||
/* Implementation of message port subclass of NSPortNameServer
|
||||
|
||||
Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA.
|
||||
|
||||
<title>NSMessagePortNameServer class reference</title>
|
||||
$Date$ $Revision$
|
||||
*/
|
||||
|
||||
#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 "Foundation/NSFileManager.h"
|
||||
#include "Foundation/NSValue.h"
|
||||
#include "Foundation/NSThread.h"
|
||||
|
||||
#include "GSPortPrivate.h"
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
|
||||
#else /* __MINGW32__ */
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
NSMapEnumerator mEnum;
|
||||
NSMessagePort *port;
|
||||
NSString *name;
|
||||
BOOL unknownThread = GSRegisterCurrentThread();
|
||||
CREATE_AUTORELEASE_POOL(arp);
|
||||
|
||||
mEnum = NSEnumerateMapTable(portToNamesMap);
|
||||
while (NSNextMapEnumeratorPair(&mEnum, (void *)&port, (void *)&name))
|
||||
{
|
||||
[defaultServer removePort: port];
|
||||
}
|
||||
NSEndMapTableEnumeration(&mEnum);
|
||||
DESTROY(arp);
|
||||
if (unknownThread == YES)
|
||||
{
|
||||
GSUnregisterCurrentThread();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclass of [NSPortNameServer] taking/returning instances of [NSMessagePort].
|
||||
* Port removal functionality is not supported; if you want to cancel a service,
|
||||
* you have to destroy the port (invalidate the [NSMessagePort] given to
|
||||
* [NSPortNameServer-registerPort:forName:]).
|
||||
*/
|
||||
@implementation NSMessagePortNameServer
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [NSMessagePortNameServer class])
|
||||
{
|
||||
serverLock = [NSRecursiveLock new];
|
||||
portToNamesMap = NSCreateMapTable(NSNonRetainedObjectMapKeyCallBacks,
|
||||
NSObjectMapValueCallBacks, 0);
|
||||
atexit(clean_up_names);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain single instance for this host.
|
||||
*/
|
||||
+ (id) sharedInstance
|
||||
{
|
||||
if (defaultServer == nil)
|
||||
{
|
||||
[serverLock lock];
|
||||
if (defaultServer == nil)
|
||||
{
|
||||
defaultServer = (NSMessagePortNameServer *)NSAllocateObject(self,
|
||||
0, NSDefaultMallocZone());
|
||||
}
|
||||
[serverLock unlock];
|
||||
}
|
||||
return defaultServer;
|
||||
}
|
||||
|
||||
|
||||
+ (NSString *) _pathForName: (NSString *)name
|
||||
{
|
||||
static NSString *base_path = nil;
|
||||
NSString *path;
|
||||
|
||||
[serverLock lock];
|
||||
if (!base_path)
|
||||
{
|
||||
NSNumber *p = [NSNumber numberWithInt: 0700];
|
||||
NSDictionary *attr;
|
||||
|
||||
path = NSTemporaryDirectory();
|
||||
attr = [NSDictionary dictionaryWithObject: p
|
||||
forKey: NSFilePosixPermissions];
|
||||
|
||||
path = [path stringByAppendingPathComponent: @"NSMessagePort"];
|
||||
[[NSFileManager defaultManager] createDirectoryAtPath: path
|
||||
attributes: attr];
|
||||
|
||||
path = [path stringByAppendingPathComponent: @"names"];
|
||||
[[NSFileManager defaultManager] createDirectoryAtPath: path
|
||||
attributes: attr];
|
||||
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
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 = [[self class] _pathForName: name];
|
||||
if (![[self class] _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: (unsigned char*)socket_path
|
||||
listener: NO];
|
||||
}
|
||||
|
||||
- (BOOL) registerPort: (NSPort *)port
|
||||
forName: (NSString *)name
|
||||
{
|
||||
int fd;
|
||||
unsigned char buf[32];
|
||||
NSString *path;
|
||||
const unsigned char *socket_name;
|
||||
NSMutableArray *a;
|
||||
|
||||
NSDebugLLog(@"NSMessagePort", @"register %@ as %@\n", port, name);
|
||||
if ([port isKindOfClass: [NSMessagePort class]] == NO)
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Attempted to register a non-NSMessagePort (%@)",
|
||||
port];
|
||||
return NO;
|
||||
}
|
||||
|
||||
path = [[self class] _pathForName: name];
|
||||
|
||||
if ([[self class] _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, (char*)socket_name, strlen((char*)socket_name));
|
||||
write(fd, "\n", 1);
|
||||
sprintf((char*)buf, "%i\n", getpid());
|
||||
write(fd, (char*)buf, strlen((char*)buf));
|
||||
|
||||
close(fd);
|
||||
|
||||
[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 = [[self class] _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 = [[self class] _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((char*)socket_path, (char*)port_path))
|
||||
{
|
||||
unlink([path fileSystemRepresentation]);
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __MINGW32__ */
|
||||
|
489
Source/win32/NSMessagePortWin32.m
Normal file
489
Source/win32/NSMessagePortWin32.m
Normal file
|
@ -0,0 +1,489 @@
|
|||
/** Implementation of network port object based on unix domain sockets
|
||||
Copyright (C) 2000 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Richard Frith-Macdonald <richard@brainstorm.co.uk>
|
||||
Based on code by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
|
||||
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.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "GNUstepBase/preface.h"
|
||||
#include "GNUstepBase/GSLock.h"
|
||||
#include "Foundation/NSArray.h"
|
||||
#include "Foundation/NSNotification.h"
|
||||
#include "Foundation/NSException.h"
|
||||
#include "Foundation/NSRunLoop.h"
|
||||
#include "Foundation/NSByteOrder.h"
|
||||
#include "Foundation/NSData.h"
|
||||
#include "Foundation/NSDate.h"
|
||||
#include "Foundation/NSMapTable.h"
|
||||
#include "Foundation/NSPortMessage.h"
|
||||
#include "Foundation/NSPortNameServer.h"
|
||||
#include "Foundation/NSLock.h"
|
||||
#include "Foundation/NSThread.h"
|
||||
#include "Foundation/NSConnection.h"
|
||||
#include "Foundation/NSDebug.h"
|
||||
#include "Foundation/NSPathUtilities.h"
|
||||
#include "Foundation/NSValue.h"
|
||||
#include "Foundation/NSFileManager.h"
|
||||
#include "Foundation/NSProcessInfo.h"
|
||||
|
||||
#include "GSPortPrivate.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
* Largest chunk of data possible in DO
|
||||
*/
|
||||
static gsu32 maxDataLength = 10 * 1024 * 1024;
|
||||
|
||||
#if 0
|
||||
#define M_LOCK(X) {NSDebugMLLog(@"NSMessagePort",@"lock %@",X); [X lock];}
|
||||
#define M_UNLOCK(X) {NSDebugMLLog(@"NSMessagePort",@"unlock %@",X); [X unlock];}
|
||||
#else
|
||||
#define M_LOCK(X) {[X lock];}
|
||||
#define M_UNLOCK(X) {[X unlock];}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* The GSPortItemType constant is used to identify the type of data in
|
||||
* each packet read. All data transmitted is in a packet, each packet
|
||||
* has an initial packet type and packet length.
|
||||
*/
|
||||
typedef enum {
|
||||
GSP_NONE,
|
||||
GSP_PORT, /* Simple port item. */
|
||||
GSP_DATA, /* Simple data item. */
|
||||
GSP_HEAD /* Port message header + initial data. */
|
||||
} GSPortItemType;
|
||||
|
||||
/*
|
||||
* The GSPortItemHeader structure defines the header for each item transmitted.
|
||||
* Its contents are transmitted in network byte order.
|
||||
*/
|
||||
typedef struct {
|
||||
gsu32 type; /* A GSPortItemType as a 4-byte number. */
|
||||
gsu32 length; /* The length of the item (excluding header). */
|
||||
} GSPortItemHeader;
|
||||
|
||||
/*
|
||||
* The GSPortMsgHeader structure is at the start of any item of type GSP_HEAD.
|
||||
* Its contents are transmitted in network byte order.
|
||||
* Any additional data in the item is an NSData object.
|
||||
* NB. additional data counts as part of the same item.
|
||||
*/
|
||||
typedef struct {
|
||||
gsu32 mId; /* The ID for the message starting with this. */
|
||||
gsu32 nItems; /* Number of items (including this one). */
|
||||
} GSPortMsgHeader;
|
||||
|
||||
typedef struct {
|
||||
unsigned char version;
|
||||
unsigned char addr[0]; /* name of the port on the local host */
|
||||
} GSPortInfo;
|
||||
|
||||
/*
|
||||
* Utility functions for encoding and decoding ports.
|
||||
*/
|
||||
static NSMessagePort*
|
||||
decodePort(NSData *data)
|
||||
{
|
||||
GSPortItemHeader *pih;
|
||||
GSPortInfo *pi;
|
||||
|
||||
pih = (GSPortItemHeader*)[data bytes];
|
||||
NSCAssert(GSSwapBigI32ToHost(pih->type) == GSP_PORT,
|
||||
NSInternalInconsistencyException);
|
||||
pi = (GSPortInfo*)&pih[1];
|
||||
if (pi->version != 0)
|
||||
{
|
||||
NSLog(@"Remote version of GNUstep is more recent than this one (%i)",
|
||||
pi->version);
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSDebugFLLog(@"NSMessagePort", @"Decoded port as '%s'", pi->addr);
|
||||
|
||||
return [NSMessagePort _portWithName: pi->addr
|
||||
listener: NO];
|
||||
}
|
||||
|
||||
static NSData*
|
||||
newDataWithEncodedPort(NSMessagePort *port)
|
||||
{
|
||||
GSPortItemHeader *pih;
|
||||
GSPortInfo *pi;
|
||||
NSMutableData *data;
|
||||
unsigned plen;
|
||||
const unsigned char *name = [port _name];
|
||||
|
||||
plen = 2 + strlen((char*)name);
|
||||
|
||||
data = [[NSMutableData alloc] initWithLength: sizeof(GSPortItemHeader)+plen];
|
||||
pih = (GSPortItemHeader*)[data mutableBytes];
|
||||
pih->type = GSSwapHostI32ToBig(GSP_PORT);
|
||||
pih->length = GSSwapHostI32ToBig(plen);
|
||||
pi = (GSPortInfo*)&pih[1];
|
||||
strcpy((char*)pi->addr, (char*)name);
|
||||
|
||||
NSDebugFLLog(@"NSMessagePort", @"Encoded port as '%s'", pi->addr);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
@implementation NSMessagePort
|
||||
|
||||
static NSRecursiveLock *messagePortLock = nil;
|
||||
|
||||
/*
|
||||
* Maps port name to NSMessagePort objects.
|
||||
*/
|
||||
static NSMapTable *messagePortMap = 0;
|
||||
static Class messagePortClass;
|
||||
|
||||
#define HDR (sizeof(GSPortItemHeader) + sizeof(GSPortMsgHeader))
|
||||
|
||||
typedef struct {
|
||||
NSString *_name;
|
||||
NSRecursiveLock *_lock;
|
||||
HANDLE _handle;
|
||||
HANDLE _event;
|
||||
OVERLAPPED _ov;
|
||||
DWORD _size;
|
||||
BOOL _listen;
|
||||
NSMutableData *_data;
|
||||
unsigned _offset;
|
||||
unsigned _target;
|
||||
} internal;
|
||||
#define myName(P) ((internal*)(P)->_internal)->_name
|
||||
#define myLock(P) ((internal*)(P)->_internal)->_lock
|
||||
#define myHandle(P) ((internal*)(P)->_internal)->_handle
|
||||
#define myEvent(P) ((internal*)(P)->_internal)->_event
|
||||
#define myOv(P) ((internal*)(P)->_internal)->_ov
|
||||
#define myListen(P) ((internal*)(P)->_internal)->_listen
|
||||
#define mySize(P) ((internal*)(P)->_internal)->_size
|
||||
#define myData(P) ((internal*)(P)->_internal)->_data
|
||||
#define myOffset(P) ((internal*)(P)->_internal)->_offset
|
||||
#define myTarget(P) ((internal*)(P)->_internal)->_target
|
||||
|
||||
#if NEED_WORD_ALIGNMENT
|
||||
static unsigned wordAlign;
|
||||
#endif
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [NSMessagePort class])
|
||||
{
|
||||
#if NEED_WORD_ALIGNMENT
|
||||
wordAlign = objc_alignof_type(@encode(gsu32));
|
||||
#endif
|
||||
messagePortClass = self;
|
||||
messagePortMap = NSCreateMapTable(NSNonRetainedObjectMapKeyCallBacks,
|
||||
NSNonOwnedPointerMapValueCallBacks, 0);
|
||||
|
||||
messagePortLock = [GSLazyRecursiveLock new];
|
||||
}
|
||||
}
|
||||
|
||||
+ (id) new
|
||||
{
|
||||
static int unique_index = 0;
|
||||
unsigned char path[BUFSIZ];
|
||||
|
||||
M_LOCK(messagePortLock);
|
||||
sprintf(path, "\\\\.\\mailslot\\NSMessagePort\\%i.%i",
|
||||
[[NSProcessInfo processInfo] processIdentifier], unique_index++);
|
||||
M_UNLOCK(messagePortLock);
|
||||
|
||||
return RETAIN([self _portWithName: path listener: YES]);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the preferred initialisation method for NSMessagePort
|
||||
*
|
||||
* 'mailslotName' is the name of the mailslot to use.
|
||||
*/
|
||||
+ (NSMessagePort*) _portWithName: (const unsigned char*)mailslotName
|
||||
listener: (BOOL)shouldListen
|
||||
{
|
||||
NSMessagePort *port = nil;
|
||||
|
||||
M_LOCK(messagePortLock);
|
||||
|
||||
/*
|
||||
* First try to find a pre-existing port.
|
||||
*/
|
||||
port = (NSMessagePort*)NSMapGet(messagePortMap, mailslotName);
|
||||
|
||||
if (port == nil)
|
||||
{
|
||||
port = (NSMessagePort*)NSAllocateObject(self, 0, NSDefaultMallocZone());
|
||||
myName(port) = [[NSString alloc] initWithUTF8String: mailslotName];
|
||||
myEvent(port) = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
myOv(port).Offset = 0;
|
||||
myOv(port).OffsetHigh = 0;
|
||||
myOv(port).hEvent = myEvent(port);
|
||||
myHandle(port) = INVALID_HANDLE_VALUE;
|
||||
myLock(port) = [GSLazyRecursiveLock new];
|
||||
port->_is_valid = YES;
|
||||
|
||||
if (shouldListen == YES)
|
||||
{
|
||||
myHandle(port) = CreateMailslot([myName(port) UTF8String],
|
||||
0, /* No max message size. */
|
||||
MAILSLOT_WAIT_FOREVER, /* No read/write timeout. */
|
||||
(LPSECURITY_ATTRIBUTES)0);
|
||||
|
||||
if (myHandle(port) == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
NSLog(@"unable to create mailslot - %s", GSLastErrorStr(errno));
|
||||
DESTROY(port);
|
||||
}
|
||||
else
|
||||
{
|
||||
myListen(port) = YES;
|
||||
NSMapInsert(messagePortMap, (void*)myName(port), (void*)port);
|
||||
NSDebugMLLog(@"NSMessagePort", @"Created listening port: %@",
|
||||
port);
|
||||
|
||||
/* Set off an asynchronous read operation to get the header
|
||||
* of an incoming message.
|
||||
*/
|
||||
myOffset(port) = 0;
|
||||
myTarget(port) = HDR;
|
||||
[myData(port) setLength: HDR];
|
||||
ReadFile(myHandle(port),
|
||||
[myData(port) mutableBytes], // Store results here
|
||||
myTarget(port), // Read a header size.
|
||||
&mySize(port), // Store number of bytes read
|
||||
&myOv(port));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
myHandle(port) = CreateFile([myName(port) UTF8String],
|
||||
GENERIC_WRITE,
|
||||
FILE_SHARE_READ,
|
||||
(LPSECURITY_ATTRIBUTES)0,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
(HANDLE)0);
|
||||
if (myHandle(port) == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
NSLog(@"unable to access mailslot - %s", GSLastErrorStr(errno));
|
||||
DESTROY(port);
|
||||
}
|
||||
else
|
||||
{
|
||||
myListen(port) = NO;
|
||||
NSMapInsert(messagePortMap, (void*)myName(port), (void*)port);
|
||||
NSDebugMLLog(@"NSMessagePort", @"Created speaking port: %@",
|
||||
port);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RETAIN(port);
|
||||
NSDebugMLLog(@"NSMessagePort", @"Using pre-existing port: %@", port);
|
||||
}
|
||||
IF_NO_GC(AUTORELEASE(port));
|
||||
|
||||
M_UNLOCK(messagePortLock);
|
||||
return port;
|
||||
}
|
||||
|
||||
- (id) copyWithZone: (NSZone*)zone
|
||||
{
|
||||
return RETAIN(self);
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[self gcFinalize];
|
||||
DESTROY(myName(self));
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSString*) description
|
||||
{
|
||||
NSString *desc;
|
||||
|
||||
desc = [NSString stringWithFormat: @"<NSMessagePort %p with name %@>",
|
||||
self, myName(self)];
|
||||
return desc;
|
||||
}
|
||||
|
||||
- (void) gcFinalize
|
||||
{
|
||||
NSDebugMLLog(@"NSMessagePort", @"NSMessagePort 0x%x finalized", self);
|
||||
[self invalidate];
|
||||
}
|
||||
|
||||
- (id) conversation: (NSPort*)recvPort
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void) handlePortMessage: (NSPortMessage*)m
|
||||
{
|
||||
id d = [self delegate];
|
||||
|
||||
if (d == nil)
|
||||
{
|
||||
NSDebugMLLog(@"NSMessagePort",
|
||||
@"No delegate to handle incoming message", 0);
|
||||
return;
|
||||
}
|
||||
if ([d respondsToSelector: @selector(handlePortMessage:)] == NO)
|
||||
{
|
||||
NSDebugMLLog(@"NSMessagePort", @"delegate doesn't handle messages", 0);
|
||||
return;
|
||||
}
|
||||
[d handlePortMessage: m];
|
||||
}
|
||||
|
||||
- (unsigned) hash
|
||||
{
|
||||
return [myName(self) hash];
|
||||
}
|
||||
|
||||
- (id) init
|
||||
{
|
||||
RELEASE(self);
|
||||
self = [messagePortClass new];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) invalidate
|
||||
{
|
||||
if ([self isValid] == YES)
|
||||
{
|
||||
M_LOCK(myLock(self));
|
||||
if ([self isValid] == YES)
|
||||
{
|
||||
M_LOCK(messagePortLock);
|
||||
if (myEvent(self) != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
(void) CloseHandle(myEvent(self));
|
||||
myEvent(self) = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
if (myHandle(self) != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
(void) CloseHandle(myHandle(self));
|
||||
myHandle(self) = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
NSMapRemove(messagePortMap, (void*)myName(self));
|
||||
M_UNLOCK(messagePortLock);
|
||||
|
||||
// FIXME [[NSMessagePortNameServer sharedInstance] removePort: self];
|
||||
[super invalidate];
|
||||
}
|
||||
M_UNLOCK(myLock(self));
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL) isEqual: (id)anObject
|
||||
{
|
||||
if (anObject == self)
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
if ([anObject class] == [self class])
|
||||
{
|
||||
NSMessagePort *o = (NSMessagePort*)anObject;
|
||||
|
||||
return [myName(o) isEqual: myName(self)];
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void) receivedEvent: (void*)data
|
||||
type: (RunLoopEventType)type
|
||||
extra: (void*)extra
|
||||
forMode: (NSString*)mode
|
||||
{
|
||||
HANDLE h = (HANDLE)(gsaddr)extra;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* This returns the amount of space that a port coder should reserve at the
|
||||
* start of its encoded data so that the NSMessagePort can insert header info
|
||||
* into the data.
|
||||
* The idea is that a message consisting of a single data item with space at
|
||||
* the start can be written directly without having to copy data to another
|
||||
* buffer etc.
|
||||
*/
|
||||
- (unsigned int) reservedSpaceLength
|
||||
{
|
||||
return sizeof(GSPortItemHeader) + sizeof(GSPortMsgHeader);
|
||||
}
|
||||
|
||||
- (BOOL) sendBeforeDate: (NSDate*)when
|
||||
msgid: (int)msgId
|
||||
components: (NSMutableArray*)components
|
||||
from: (NSPort*)receivingPort
|
||||
reserved: (unsigned)length
|
||||
{
|
||||
BOOL sent = NO;
|
||||
unsigned rl;
|
||||
|
||||
if ([self isValid] == NO)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
if ([components count] == 0)
|
||||
{
|
||||
NSLog(@"empty components sent");
|
||||
return NO;
|
||||
}
|
||||
/*
|
||||
* If the reserved length in the first data object is wrong - we have to
|
||||
* fail, unless it's zero, in which case we can insert a data object for
|
||||
* the header.
|
||||
*/
|
||||
rl = [self reservedSpaceLength];
|
||||
if (length != 0 && length != rl)
|
||||
{
|
||||
NSLog(@"bad reserved length - %u", length);
|
||||
return NO;
|
||||
}
|
||||
if ([receivingPort isKindOfClass: messagePortClass] == NO)
|
||||
{
|
||||
NSLog(@"woah there - receiving port is not the correct type");
|
||||
return NO;
|
||||
}
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
- (NSDate*) timedOutEvent: (void*)data
|
||||
type: (RunLoopEventType)type
|
||||
forMode: (NSString*)mode
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
Loading…
Reference in a new issue