Apply modified patch to support windows native event handling

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20785 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-Macdonald 2005-02-23 16:05:09 +00:00
parent 0e7313bb94
commit 2a9f4ec7c0
24 changed files with 2735 additions and 1640 deletions

View file

@ -109,6 +109,11 @@ static GSFileHandle* fh_stderr = nil;
// Key to info dictionary for operation mode.
static NSString* NotificationKey = @"NSFileHandleNotificationKey";
@interface GSFileHandle(private)
- (void) receivedEventRead;
- (void) receivedEventWrite;
@end
@implementation GSFileHandle
/**
@ -299,6 +304,8 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin)
if (isSocket)
{
closesocket((SOCKET)_get_osfhandle(descriptor));
WSACloseEvent(event);
event = WSA_INVALID_EVENT;
}
#endif
close(descriptor);
@ -1221,6 +1228,22 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
writeOK = YES;
acceptOK = YES;
connectOK = YES;
#ifdef __MINGW32__
if (isSocket)
{
event = CreateEvent(NULL, NO, NO, NULL);
if (event == WSA_INVALID_EVENT)
{
NSLog(@"Invalid Event - '%d'", WSAGetLastError());
return nil;
}
WSAEventSelect(_get_osfhandle(descriptor), event, FD_ALL_EVENTS);
}
else
{
event = WSA_INVALID_EVENT;
}
#endif
}
return self;
}
@ -1492,7 +1515,12 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
rval = [self write: (char*)ptr+pos length: toWrite];
if (rval < 0)
{
#ifdef __MINGW32__
if (WSAGetLastError()== WSAEINTR ||
WSAGetLastError()== WSAEWOULDBLOCK)
#else
if (errno == EAGAIN || errno == EINTR)
#endif
{
rval = 0;
}
@ -1702,6 +1730,8 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
if (isSocket)
{
(void)closesocket((SOCKET)_get_osfhandle(descriptor));
WSACloseEvent(event);
event = WSA_INVALID_EVENT;
}
#endif
(void)close(descriptor);
@ -1796,6 +1826,10 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
modes = (NSArray*)[info objectForKey: NSFileHandleNotificationMonitorModes];
name = (NSString*)[info objectForKey: NotificationKey];
if (name == nil)
{
return;
}
n = [NSNotification notificationWithName: name object: self userInfo: info];
RELEASE(info); /* Retained by the notification. */
@ -1877,9 +1911,9 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
for (i = 0; i < [modes count]; i++)
{
#if defined(__MINGW__)
[l removeEvent: (void*)(gsaddr)(SOCKET)_get_osfhandle(descriptor)
type: ET_RDESC
#ifdef __MINGW32__
[l removeEvent: (void*)(gsaddr)event
type: ET_HANDLE
forMode: [modes objectAtIndex: i]
all: YES];
#else
@ -1892,11 +1926,11 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
}
else
{
#if defined(__MINGW__)
[l removeEvent: (void*)(gsaddr)(SOCKET)_get_osfhandle(descriptor)
type: ET_RDESC
#ifdef __MINGW32__
[l removeEvent: (void*)(gsaddr)event
type: ET_HANDLE
forMode: NSDefaultRunLoopMode
all: YES];
all: YES];
#else
[l removeEvent: (void*)(gsaddr)descriptor
type: ET_RDESC
@ -1931,11 +1965,11 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
for (i = 0; i < [modes count]; i++)
{
#if defined(__MINGW__)
[l removeEvent: (void*)(gsaddr)(SOCKET)_get_osfhandle(descriptor)
type: ET_WDESC
forMode: [modes objectAtIndex: i]
all: YES];
#ifdef __MINGW32__
[l removeEvent: (void*)(gsaddr)event
type: ET_HANDLE
forMode: [modes objectAtIndex: i]
all: YES];
#else
[l removeEvent: (void*)(gsaddr)descriptor
type: ET_WDESC
@ -1946,11 +1980,11 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
}
else
{
#if defined(__MINGW__)
[l removeEvent: (void*)(gsaddr)(SOCKET)_get_osfhandle(descriptor)
type: ET_WDESC
#ifdef __MINGW32__
[l removeEvent: (void*)(gsaddr)event
type: ET_HANDLE
forMode: NSDefaultRunLoopMode
all: YES];
all: YES];
#else
[l removeEvent: (void*)(gsaddr)descriptor
type: ET_WDESC
@ -1968,6 +2002,7 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
{
return;
}
l = [NSRunLoop currentRunLoop];
[self setNonBlocking: YES];
if (modes && [modes count])
@ -1976,9 +2011,9 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
for (i = 0; i < [modes count]; i++)
{
#if defined(__MINGW__)
[l addEvent: (void*)(gsaddr)(SOCKET)_get_osfhandle(descriptor)
type: ET_RDESC
#ifdef __MINGW32__
[l addEvent: (void*)(gsaddr)event
type: ET_HANDLE
watcher: self
forMode: [modes objectAtIndex: i]];
#else
@ -1992,9 +2027,9 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
}
else
{
#if defined(__MINGW__)
[l addEvent: (void*)(gsaddr)(SOCKET)_get_osfhandle(descriptor)
type: ET_RDESC
#ifdef __MINGW32__
[l addEvent: (void*)(gsaddr)event
type: ET_HANDLE
watcher: self
forMode: NSDefaultRunLoopMode];
#else
@ -2027,9 +2062,9 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
for (i = 0; i < [modes count]; i++)
{
#if defined(__MINGW__)
[l addEvent: (void*)(gsaddr)(SOCKET)_get_osfhandle(descriptor)
type: ET_WDESC
#ifdef __MINGW32__
[l addEvent: (void*)(gsaddr)event
type: ET_HANDLE
watcher: self
forMode: [modes objectAtIndex: i]];
#else
@ -2042,9 +2077,9 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
}
else
{
#if defined(__MINGW__)
[l addEvent: (void*)(gsaddr)(SOCKET)_get_osfhandle(descriptor)
type: ET_WDESC
#ifdef __MINGW32__
[l addEvent: (void*)(gsaddr)event
type: ET_HANDLE
watcher: self
forMode: NSDefaultRunLoopMode];
#else
@ -2057,12 +2092,205 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
}
}
- (void) receivedEventRead
{
NSString *operation;
operation = [readInfo objectForKey: NotificationKey];
if (operation == NSFileHandleConnectionAcceptedNotification)
{
struct sockaddr_in buf;
#if defined(__MINGW__)
SOCKET desc;
#else
int desc;
#endif
int blen = sizeof(buf);
#if defined(__MINGW__)
desc = accept((SOCKET)_get_osfhandle(descriptor), (struct sockaddr*)&buf, &blen);
#else
desc = accept(descriptor, (struct sockaddr*)&buf, &blen);
#endif
if (desc == INVALID_SOCKET)
{
NSString *s;
s = [NSString stringWithFormat: @"Accept attempt failed - %s",
GSLastErrorStr(errno)];
[readInfo setObject: s forKey: GSFileHandleNotificationError];
}
else
{ // Accept attempt completed.
GSFileHandle *h;
struct sockaddr_in sin;
int size = sizeof(sin);
#if defined(__MINGW__)
h = [[[self class] alloc] initWithNativeHandle: (void*)desc
closeOnDealloc: YES];
#else
h = [[[self class] alloc] initWithFileDescriptor: desc
closeOnDealloc: YES];
#endif
h->isSocket = YES;
getpeername(desc, (struct sockaddr*)&sin, &size);
[h setAddr: &sin];
[readInfo setObject: h
forKey: NSFileHandleNotificationFileHandleItem];
RELEASE(h);
}
[self postReadNotification];
}
else if (operation == NSFileHandleDataAvailableNotification)
{
[self postReadNotification];
}
else
{
NSMutableData *item;
int length;
int received = 0;
char buf[NETBUF_SIZE];
item = [readInfo objectForKey: NSFileHandleNotificationDataItem];
/*
* We may have a maximum data size set...
*/
if (readMax > 0)
{
length = (unsigned int)readMax - [item length];
if (length > (int)sizeof(buf))
{
length = sizeof(buf);
}
}
else
{
length = sizeof(buf);
}
received = [self read: buf length: length];
if (received == 0)
{ // Read up to end of file.
[self postReadNotification];
}
else if (received < 0)
{
#ifdef __MINGW32__
if (WSAGetLastError() != WSAEINTR
&& WSAGetLastError() != WSAEWOULDBLOCK)
#else
if (errno != EAGAIN && errno != EINTR)
#endif
{
NSString *s;
s = [NSString stringWithFormat: @"Read attempt failed - %s",
GSLastErrorStr(errno)];
[readInfo setObject: s forKey: GSFileHandleNotificationError];
[self postReadNotification];
}
}
else
{
[item appendBytes: buf length: received];
if (readMax < 0 || (readMax > 0 && (int)[item length] == readMax))
{
// Read a single chunk of data
[self postReadNotification];
}
}
}
}
- (void) receivedEventWrite
{
NSString *operation;
NSMutableDictionary *info;
info = [writeInfo objectAtIndex: 0];
operation = [info objectForKey: NotificationKey];
if (operation == GSFileHandleConnectCompletionNotification
|| operation == GSSOCKSConnect)
{ // Connection attempt completed.
int result;
int len = sizeof(result);
#if defined(__MINGW__)
if (getsockopt((SOCKET)_get_osfhandle(descriptor), SOL_SOCKET, SO_ERROR,
(char*)&result, &len) == 0 && result != 0)
#else
if (getsockopt(descriptor, SOL_SOCKET, SO_ERROR,
(char*)&result, &len) == 0 && result != 0)
#endif
{
NSString *s;
s = [NSString stringWithFormat: @"Connect attempt failed - %s",
GSLastErrorStr(result)];
[info setObject: s forKey: GSFileHandleNotificationError];
}
else
{
readOK = YES;
writeOK = YES;
}
connectOK = NO;
[self postWriteNotification];
}
else
{
NSData *item;
int length;
const void *ptr;
item = [info objectForKey: NSFileHandleNotificationDataItem];
length = [item length];
ptr = [item bytes];
if (writePos < length)
{
int written;
written = [self write: (char*)ptr+writePos
length: length-writePos];
if (written <= 0)
{
#ifdef __MINGW32__
if (written < 0 && WSAGetLastError()!= WSAEINTR
&& WSAGetLastError()!= WSAEWOULDBLOCK)
#else
if (written < 0 && errno != EAGAIN && errno != EINTR)
#endif
{
NSString *s;
s = [NSString stringWithFormat:
@"Write attempt failed - %s", GSLastErrorStr(errno)];
[info setObject: s forKey: GSFileHandleNotificationError];
[self postWriteNotification];
}
}
else
{
writePos += written;
}
}
if (writePos >= length)
{ // Write operation completed.
[self postWriteNotification];
}
}
}
- (void) receivedEvent: (void*)data
type: (RunLoopEventType)type
extra: (void*)extra
forMode: (NSString*)mode
{
NSString *operation;
#ifdef __MINGW32__
WSANETWORKEVENTS ocurredEvents;
#endif
NSDebugMLLog(@"NSFileHandle", @"%@ event: %d", self, type);
@ -2070,183 +2298,77 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
{
[self setNonBlocking: YES];
}
if (type == ET_RDESC)
#ifdef __MINGW32__
if (WSAEnumNetworkEvents((SOCKET)_get_osfhandle(descriptor),
event, &ocurredEvents) == SOCKET_ERROR)
{
operation = [readInfo objectForKey: NotificationKey];
if (operation == NSFileHandleConnectionAcceptedNotification)
NSLog(@"Error getting event type %d", WSAGetLastError());
abort();
}
if (ocurredEvents.lNetworkEvents & FD_CONNECT)
{
NSDebugMLLog(@"NSFileHandle", @"Connect on %x", extra);
ocurredEvents.lNetworkEvents ^= FD_CONNECT;
[self receivedEventWrite];
GSNotifyASAP();
}
if (ocurredEvents.lNetworkEvents & FD_ACCEPT)
{
NSDebugMLLog(@"NSFileHandle", @"Accept on %x", extra);
ocurredEvents.lNetworkEvents ^= FD_ACCEPT;
[self receivedEventRead];
GSNotifyASAP();
}
if (ocurredEvents.lNetworkEvents & FD_WRITE)
{
NSDebugMLLog(@"NSFileHandle", @"Write on %x", extra);
ocurredEvents.lNetworkEvents ^= FD_WRITE;
[self receivedEventWrite];
GSNotifyASAP();
}
if (ocurredEvents.lNetworkEvents & FD_READ)
{
NSDebugMLLog(@"NSFileHandle", @"Read on %x", extra);
ocurredEvents.lNetworkEvents ^= FD_READ;
[self receivedEventRead];
GSNotifyASAP();
}
if (ocurredEvents.lNetworkEvents & FD_OOB)
{
NSDebugMLLog(@"NSFileHandle", @"OOB on %x", extra);
ocurredEvents.lNetworkEvents ^= FD_OOB;
[self receivedEventRead];
GSNotifyASAP();
}
if (ocurredEvents.lNetworkEvents & FD_CLOSE)
{
NSDebugMLLog(@"NSFileHandle", @"Close on %x", extra);
ocurredEvents.lNetworkEvents ^= FD_CLOSE;
if ([writeInfo count] > 0)
{
struct sockaddr_in buf;
#if defined(__MINGW__)
SOCKET desc;
#else
int desc;
#endif
int blen = sizeof(buf);
#if defined(__MINGW__)
desc = accept((SOCKET)_get_osfhandle(descriptor), (struct sockaddr*)&buf, &blen);
#else
desc = accept(descriptor, (struct sockaddr*)&buf, &blen);
#endif
if (desc == INVALID_SOCKET)
{
NSString *s;
s = [NSString stringWithFormat: @"Accept attempt failed - %s",
GSLastErrorStr(errno)];
[readInfo setObject: s forKey: GSFileHandleNotificationError];
}
else
{ // Accept attempt completed.
GSFileHandle *h;
struct sockaddr_in sin;
int size = sizeof(sin);
#if defined(__MINGW__)
h = [[[self class] alloc] initWithNativeHandle: (void*)desc
closeOnDealloc: YES];
#else
h = [[[self class] alloc] initWithFileDescriptor: desc
closeOnDealloc: YES];
#endif
h->isSocket = YES;
getpeername(desc, (struct sockaddr*)&sin, &size);
[h setAddr: &sin];
[readInfo setObject: h
forKey: NSFileHandleNotificationFileHandleItem];
RELEASE(h);
}
[self postReadNotification];
}
else if (operation == NSFileHandleDataAvailableNotification)
{
[self postReadNotification];
[self receivedEventWrite];
}
else
{
NSMutableData *item;
int length;
int received = 0;
char buf[NETBUF_SIZE];
item = [readInfo objectForKey: NSFileHandleNotificationDataItem];
/*
* We may have a maximum data size set...
*/
if (readMax > 0)
{
length = (unsigned int)readMax - [item length];
if (length > (int)sizeof(buf))
{
length = sizeof(buf);
}
}
else
{
length = sizeof(buf);
}
received = [self read: buf length: length];
if (received == 0)
{ // Read up to end of file.
[self postReadNotification];
}
else if (received < 0)
{
if (errno != EAGAIN && errno != EINTR)
{
NSString *s;
s = [NSString stringWithFormat: @"Read attempt failed - %s",
GSLastErrorStr(errno)];
[readInfo setObject: s forKey: GSFileHandleNotificationError];
[self postReadNotification];
}
}
else
{
[item appendBytes: buf length: received];
if (readMax < 0 || (readMax > 0 && (int)[item length] == readMax))
{
// Read a single chunk of data
[self postReadNotification];
}
}
[self receivedEventRead];
}
GSNotifyASAP();
}
if (ocurredEvents.lNetworkEvents)
{
NSLog(@"Event not get %d", ocurredEvents.lNetworkEvents);
abort();
}
#else
if (type == ET_RDESC)
{
[self receivedEventRead];
}
else
{
NSMutableDictionary *info;
info = [writeInfo objectAtIndex: 0];
operation = [info objectForKey: NotificationKey];
if (operation == GSFileHandleConnectCompletionNotification
|| operation == GSSOCKSConnect)
{ // Connection attempt completed.
int result;
int len = sizeof(result);
#if defined(__MINGW__)
if (getsockopt((SOCKET)_get_osfhandle(descriptor), SOL_SOCKET, SO_ERROR,
(char*)&result, &len) == 0 && result != 0)
#else
if (getsockopt(descriptor, SOL_SOCKET, SO_ERROR,
(char*)&result, &len) == 0 && result != 0)
#endif
{
NSString *s;
s = [NSString stringWithFormat: @"Connect attempt failed - %s",
GSLastErrorStr(result)];
[info setObject: s forKey: GSFileHandleNotificationError];
}
else
{
readOK = YES;
writeOK = YES;
}
connectOK = NO;
[self postWriteNotification];
}
else
{
NSData *item;
int length;
const void *ptr;
item = [info objectForKey: NSFileHandleNotificationDataItem];
length = [item length];
ptr = [item bytes];
if (writePos < length)
{
int written;
written = [self write: (char*)ptr+writePos
length: length-writePos];
if (written <= 0)
{
if (written < 0 && errno != EAGAIN && errno != EINTR)
{
NSString *s;
s = [NSString stringWithFormat:
@"Write attempt failed - %s", GSLastErrorStr(errno)];
[info setObject: s forKey: GSFileHandleNotificationError];
[self postWriteNotification];
}
}
else
{
writePos += written;
}
}
if (writePos >= length)
{ // Write operation completed.
[self postWriteNotification];
}
}
[self receivedEventWrite];
}
#endif
}
- (NSDate*) timedOutEvent: (void*)data