macosx compatibility fixes

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@23215 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
rfm 2006-08-08 13:31:50 +00:00
parent 71148081f7
commit 85ada8322a
5 changed files with 261 additions and 198 deletions

View file

@ -1,9 +1,13 @@
2006-08-07 Richard Frith-Macdonald <rfm@gnu.org> 2006-08-08 Richard Frith-Macdonald <rfm@gnu.org>
* Source/GSStream.h:
* Source/GSStream.m:
* Source/win32/NSStreamWin32.m: * Source/win32/NSStreamWin32.m:
* Source/unix/NSStream.m: * Source/unix/NSStream.m:
If a connection attampt fails, propogate error to sibling stream so If a connection attempt fails, propagate error to sibling stream so
both streams in the pair get a failure. both streams in the pair get a failure.
Try to make behavior of socket streams MacOs-X like, avoiding repeated
notifications of events.
2006-08-07 00:13-EDT Gregory John Casamento <greg_casamento@yahoo.com> 2006-08-07 00:13-EDT Gregory John Casamento <greg_casamento@yahoo.com>

View file

@ -68,6 +68,7 @@
id _delegate; /* Delegate controls operation. */\ id _delegate; /* Delegate controls operation. */\
NSMutableDictionary *_properties; /* storage for properties */\ NSMutableDictionary *_properties; /* storage for properties */\
BOOL _delegateValid;/* whether the delegate responds*/\ BOOL _delegateValid;/* whether the delegate responds*/\
BOOL _unhandledData; /* no read/write since event */\
NSError *_lastError; /* last error occured */\ NSError *_lastError; /* last error occured */\
NSStreamStatus _currentStatus;/* current status */\ NSStreamStatus _currentStatus;/* current status */\
NSMutableArray *_modes; /* currently scheduled modes. */\ NSMutableArray *_modes; /* currently scheduled modes. */\
@ -121,6 +122,11 @@ IVARS
* record an error based on errno * record an error based on errno
*/ */
- (void) _recordError; - (void) _recordError;
/**
* say whether there is unahdnled data for the stream.
*/
- (BOOL) _unhandledData;
@end @end
@interface GSInputStream : NSInputStream @interface GSInputStream : NSInputStream

View file

@ -318,6 +318,10 @@ static RunLoopEventType typeForStream(NSStream *aStream)
{ {
} }
- (BOOL) _unhandledData
{
return NO;
}
@end @end
@implementation GSStream (Private) @implementation GSStream (Private)
@ -351,7 +355,17 @@ static RunLoopEventType typeForStream(NSStream *aStream)
- (void) _sendEvent: (NSStreamEvent)event - (void) _sendEvent: (NSStreamEvent)event
{ {
if (_delegateValid) if (event == NSStreamEventHasSpaceAvailable
|| event == NSStreamEventHasBytesAvailable)
{
/* If we have a data event, we mark the stream as having unhandled
* data (so we can refrain from triggering again) until a read or
* write operation (as approriate) has been performed.
*/
_unhandledData = YES;
_unhandledData = YES;
}
if (_delegateValid == YES)
{ {
[(id <GSStreamListener>)_delegate stream: self handleEvent: event]; [(id <GSStreamListener>)_delegate stream: self handleEvent: event];
} }
@ -372,6 +386,38 @@ static RunLoopEventType typeForStream(NSStream *aStream)
} }
} }
- (BOOL) _unhandledData
{
return _unhandledData;
}
- (BOOL) runLoopShouldBlock: (BOOL*)trigger
{
if (_unhandledData == YES
|| _currentStatus == NSStreamStatusError)
{
/* If we have an unhandled data event, we should not watch for more
* or trigger until the appropriate rad or write has been done.
* If an error has occurred, we should not watch for any events at all.
*/
*trigger = NO;
return NO;
}
else if (_loopID == (void*)self)
{
/* If _loopID is the receiver, the stream is not receiving external
* input, so it must trigger an event when the loop runs and must not
* block the loop from running.
*/
*trigger = YES;
return NO;
}
else
{
*trigger = YES;
return YES;
}
}
@end @end
@implementation GSInputStream @implementation GSInputStream
@ -432,6 +478,7 @@ static RunLoopEventType typeForStream(NSStream *aStream)
unsigned long dataSize = [_data length]; unsigned long dataSize = [_data length];
unsigned long copySize; unsigned long copySize;
_unhandledData = NO;
NSAssert(dataSize >= _pointer, @"Buffer overflow!"); NSAssert(dataSize >= _pointer, @"Buffer overflow!");
if (len + _pointer > dataSize) if (len + _pointer > dataSize)
{ {
@ -482,8 +529,7 @@ static RunLoopEventType typeForStream(NSStream *aStream)
BOOL av = [self hasBytesAvailable]; BOOL av = [self hasBytesAvailable];
NSStreamEvent myEvent = av ? NSStreamEventHasBytesAvailable : NSStreamEvent myEvent = av ? NSStreamEventHasBytesAvailable :
NSStreamEventEndEncountered; NSStreamEventEndEncountered;
NSStreamStatus myStatus = av ? NSStreamStatusReading : NSStreamStatus myStatus = av ? NSStreamStatusOpen : NSStreamStatusAtEnd;
NSStreamStatusAtEnd;
[self _setStatus: myStatus]; [self _setStatus: myStatus];
[self _sendEvent: myEvent]; [self _sendEvent: myEvent];
@ -523,6 +569,7 @@ static RunLoopEventType typeForStream(NSStream *aStream)
- (int) write: (const uint8_t *)buffer maxLength: (unsigned int)len - (int) write: (const uint8_t *)buffer maxLength: (unsigned int)len
{ {
_unhandledData = NO;
if (_fixedSize) if (_fixedSize)
{ {
unsigned long dataLen = [_data length]; unsigned long dataLen = [_data length];

View file

@ -297,6 +297,7 @@ static void setNonblocking(int fd)
{ {
int readLen; int readLen;
_unhandledData = NO;
readLen = read((intptr_t)_loopID, buffer, len); readLen = read((intptr_t)_loopID, buffer, len);
if (readLen < 0 && errno != EAGAIN && errno != EINTR) if (readLen < 0 && errno != EAGAIN && errno != EINTR)
[self _recordError]; [self _recordError];
@ -353,15 +354,6 @@ static void setNonblocking(int fd)
[super close]; [super close];
} }
- (void) _dispatch
{
NSStreamEvent myEvent;
[self _setStatus: NSStreamStatusReading];
myEvent = NSStreamEventHasBytesAvailable;
[self _sendEvent: myEvent];
}
@end @end
@implementation GSSocketInputStream @implementation GSSocketInputStream
@ -472,6 +464,7 @@ static void setNonblocking(int fd)
{ {
int readLen; int readLen;
_unhandledData = NO;
readLen = read((intptr_t)_loopID, buffer, len); readLen = read((intptr_t)_loopID, buffer, len);
if (readLen < 0 && errno != EAGAIN && errno != EINTR) if (readLen < 0 && errno != EAGAIN && errno != EINTR)
[self _recordError]; [self _recordError];
@ -507,7 +500,8 @@ static void setNonblocking(int fd)
{ {
[_runloop removeStream: self mode: [_modes objectAtIndex: i]]; [_runloop removeStream: self mode: [_modes objectAtIndex: i]];
} }
result = getsockopt((intptr_t)_loopID, SOL_SOCKET, SO_ERROR, &error, &len); result
= getsockopt((intptr_t)_loopID, SOL_SOCKET, SO_ERROR, &error, &len);
if (result >= 0 && !error) if (result >= 0 && !error)
{ // finish up the opening { // finish up the opening
@ -530,7 +524,7 @@ static void setNonblocking(int fd)
} }
else else
{ {
[self _setStatus: NSStreamStatusReading]; [self _setStatus: NSStreamStatusOpen];
myEvent = NSStreamEventHasBytesAvailable; myEvent = NSStreamEventHasBytesAvailable;
} }
[self _sendEvent: myEvent]; [self _sendEvent: myEvent];
@ -666,6 +660,8 @@ static void setNonblocking(int fd)
- (int) write: (const uint8_t *)buffer maxLength: (unsigned int)len - (int) write: (const uint8_t *)buffer maxLength: (unsigned int)len
{ {
int writeLen; int writeLen;
_unhandledData = NO;
writeLen = write((intptr_t)_loopID, buffer, len); writeLen = write((intptr_t)_loopID, buffer, len);
if (writeLen < 0 && errno != EAGAIN && errno != EINTR) if (writeLen < 0 && errno != EAGAIN && errno != EINTR)
[self _recordError]; [self _recordError];
@ -720,15 +716,6 @@ static void setNonblocking(int fd)
return [super propertyForKey: key]; return [super propertyForKey: key];
} }
- (void) _dispatch
{
NSStreamEvent myEvent;
[self _setStatus: NSStreamStatusWriting];
myEvent = NSStreamEventHasSpaceAvailable;
[self _sendEvent: myEvent];
}
@end @end
@implementation GSSocketOutputStream @implementation GSSocketOutputStream
@ -776,6 +763,8 @@ static void setNonblocking(int fd)
- (int) write: (const uint8_t *)buffer maxLength: (unsigned int)len - (int) write: (const uint8_t *)buffer maxLength: (unsigned int)len
{ {
int writeLen; int writeLen;
_unhandledData = NO;
writeLen = write((intptr_t)_loopID, buffer, len); writeLen = write((intptr_t)_loopID, buffer, len);
if (writeLen < 0 && errno != EAGAIN && errno != EINTR) if (writeLen < 0 && errno != EAGAIN && errno != EINTR)
[self _recordError]; [self _recordError];
@ -868,7 +857,8 @@ static void setNonblocking(int fd)
{ {
[_runloop removeStream: self mode: [_modes objectAtIndex: i]]; [_runloop removeStream: self mode: [_modes objectAtIndex: i]];
} }
result = getsockopt((intptr_t)_loopID, SOL_SOCKET, SO_ERROR, &error, &len); result
= getsockopt((intptr_t)_loopID, SOL_SOCKET, SO_ERROR, &error, &len);
if (result >= 0 && !error) if (result >= 0 && !error)
{ // finish up the opening { // finish up the opening
myEvent = NSStreamEventOpenCompleted; myEvent = NSStreamEventOpenCompleted;
@ -890,7 +880,7 @@ static void setNonblocking(int fd)
} }
else else
{ {
[self _setStatus: NSStreamStatusWriting]; [self _setStatus: NSStreamStatusOpen];
myEvent = NSStreamEventHasSpaceAvailable; myEvent = NSStreamEventHasSpaceAvailable;
} }
[self _sendEvent: myEvent]; [self _sendEvent: myEvent];
@ -1411,7 +1401,7 @@ static void setNonblocking(int fd)
{ {
NSStreamEvent myEvent; NSStreamEvent myEvent;
[self _setStatus: NSStreamStatusReading]; [self _setStatus: NSStreamStatusOpen];
myEvent = NSStreamEventHasBytesAvailable; myEvent = NSStreamEventHasBytesAvailable;
[self _sendEvent: myEvent]; [self _sendEvent: myEvent];
} }

View file

@ -324,6 +324,7 @@ static void setNonblocking(SOCKET fd)
{ {
DWORD readLen; DWORD readLen;
_unhandledData = NO;
if (ReadFile((HANDLE)_loopID, buffer, len, &readLen, NULL) == 0) if (ReadFile((HANDLE)_loopID, buffer, len, &readLen, NULL) == 0)
{ {
[self _recordError]; [self _recordError];
@ -342,7 +343,7 @@ static void setNonblocking(SOCKET fd)
BOOL av = [self hasBytesAvailable]; BOOL av = [self hasBytesAvailable];
NSStreamEvent myEvent = av ? NSStreamEventHasBytesAvailable : NSStreamEvent myEvent = av ? NSStreamEventHasBytesAvailable :
NSStreamEventEndEncountered; NSStreamEventEndEncountered;
NSStreamStatus myStatus = av ? NSStreamStatusReading : NSStreamStatus myStatus = av ? NSStreamStatusOpen :
NSStreamStatusAtEnd; NSStreamStatusAtEnd;
[self _setStatus: myStatus]; [self _setStatus: myStatus];
@ -502,6 +503,7 @@ static void setNonblocking(SOCKET fd)
{ {
NSStreamStatus myStatus = [self streamStatus]; NSStreamStatus myStatus = [self streamStatus];
_unhandledData = NO;
if (myStatus == NSStreamStatusReading) if (myStatus == NSStreamStatusReading)
{ {
myStatus = [self _check]; myStatus = [self _check];
@ -587,6 +589,11 @@ static void setNonblocking(SOCKET fd)
{ {
NSStreamStatus myStatus = [self streamStatus]; NSStreamStatus myStatus = [self streamStatus];
if (_unhandledData == YES || myStatus == NSStreamStatusError)
{
*trigger = NO;
return NO;
}
*trigger = YES; *trigger = YES;
if (myStatus == NSStreamStatusReading) if (myStatus == NSStreamStatusReading)
{ {
@ -712,19 +719,28 @@ static void setNonblocking(SOCKET fd)
{ {
int readLen; int readLen;
_unhandledData = NO;
readLen = recv(_sock, buffer, len, 0); readLen = recv(_sock, buffer, len, 0);
if (readLen == SOCKET_ERROR) if (readLen == SOCKET_ERROR)
{ {
errno = WSAGetLastError(); errno = WSAGetLastError();
if (errno == WSAEINPROGRESS || errno == WSAEWOULDBLOCK) if (errno == WSAEINPROGRESS || errno == WSAEWOULDBLOCK)
{
[self _setStatus: NSStreamStatusReading]; [self _setStatus: NSStreamStatusReading];
}
else if (errno != WSAEINTR) else if (errno != WSAEINTR)
{
[self _recordError]; [self _recordError];
} }
}
else if (readLen == 0) else if (readLen == 0)
{
[self _setStatus: NSStreamStatusAtEnd]; [self _setStatus: NSStreamStatusAtEnd];
}
else else
{
[self _setStatus: NSStreamStatusOpen]; [self _setStatus: NSStreamStatusOpen];
}
return readLen; return readLen;
} }
@ -742,29 +758,29 @@ static void setNonblocking(SOCKET fd)
- (void) _dispatch - (void) _dispatch
{ {
NSStreamStatus myStatus;
WSANETWORKEVENTS ocurredEvents;
int error, getReturn;
unsigned len = sizeof(error);
/*
* it is possible the stream is closed yet recieving event because
* of not closed sibling
*/
if ([self streamStatus] == NSStreamStatusClosed) if ([self streamStatus] == NSStreamStatusClosed)
{ {
/*
* It is possible the stream is closed yet recieving event because
* of not closed sibling
*/
NSAssert([_sibling streamStatus] != NSStreamStatusClosed, NSAssert([_sibling streamStatus] != NSStreamStatusClosed,
@"Received event for closed stream"); @"Received event for closed stream");
[_sibling _dispatch]; [_sibling _dispatch];
return;
} }
else
if (WSAEnumNetworkEvents(_sock, _loopID, &ocurredEvents) == SOCKET_ERROR)
{ {
errno = WSAGetLastError(); WSANETWORKEVENTS events;
[self _recordError]; int error = 0;
int getReturn = -1;
if (WSAEnumNetworkEvents(_sock, _loopID, &events) == SOCKET_ERROR)
{
error = WSAGetLastError();
} }
else if ([self streamStatus] == NSStreamStatusOpening) else NSLog(@"EVENTS:%x", events.lNetworkEvents);
if ([self streamStatus] == NSStreamStatusOpening)
{ {
unsigned i = [_modes count]; unsigned i = [_modes count];
@ -772,68 +788,65 @@ static void setNonblocking(SOCKET fd)
{ {
[_runloop removeStream: self mode: [_modes objectAtIndex: i]]; [_runloop removeStream: self mode: [_modes objectAtIndex: i]];
} }
if (error == 0)
{
unsigned len = sizeof(error);
getReturn = getsockopt(_sock, SOL_SOCKET, SO_ERROR, getReturn = getsockopt(_sock, SOL_SOCKET, SO_ERROR,
(char*)&error, &len); (char*)&error, &len);
}
if (getReturn >= 0 && !error if (getReturn >= 0 && error == 0
&& (ocurredEvents.lNetworkEvents & FD_CONNECT)) && (events.lNetworkEvents & FD_CONNECT))
{ // finish up the opening { // finish up the opening
ocurredEvents.lNetworkEvents ^= FD_CONNECT;
_passive = YES; _passive = YES;
[self open]; [self open];
[self _sendEvent: NSStreamEventOpenCompleted];
// notify sibling // notify sibling
if (_sibling) if (_sibling)
{ {
[_sibling open]; [_sibling open];
[_sibling _sendEvent: NSStreamEventOpenCompleted]; [_sibling _sendEvent: NSStreamEventOpenCompleted];
} }
} [self _sendEvent: NSStreamEventOpenCompleted];
else // must be an error
{
if (error)
errno = error;
[self _recordError];
if (_sibling)
{
[_sibling _recordError];
[_sibling _sendEvent: NSStreamEventOpenCompleted];
}
}
}
else
{
if (ocurredEvents.lNetworkEvents & FD_READ)
{
ocurredEvents.lNetworkEvents ^= FD_READ;
[self _setStatus: NSStreamStatusOpen];
}
if ((ocurredEvents.lNetworkEvents & FD_WRITE)
&& (_sibling && [_sibling _isOpened]))
{
ocurredEvents.lNetworkEvents ^= FD_WRITE;
[_sibling _setStatus: NSStreamStatusOpen];
} }
} }
myStatus = [self streamStatus]; if (error != 0)
switch (myStatus)
{
case NSStreamStatusError:
{ {
errno = error;
[self _recordError];
[_sibling _recordError];
[self _sendEvent: NSStreamEventErrorOccurred]; [self _sendEvent: NSStreamEventErrorOccurred];
break; [_sibling _sendEvent: NSStreamEventErrorOccurred];
} }
case NSStreamStatusOpen: else
{
if (events.lNetworkEvents & FD_WRITE)
{
[_sibling _setStatus: NSStreamStatusOpen];
[_sibling _sendEvent: NSStreamEventHasSpaceAvailable];
}
if (events.lNetworkEvents & FD_READ)
{
[self _setStatus: NSStreamStatusOpen];
[self _sendEvent: NSStreamEventHasBytesAvailable];
}
if (events.lNetworkEvents & FD_CLOSE)
{
[_sibling _setStatus: NSStreamStatusAtEnd];
[_sibling _sendEvent: NSStreamEventEndEncountered];
while ([self streamStatus] == NSStreamStatusOpen
&& _unhandledData == NO)
{ {
[self _sendEvent: NSStreamEventHasBytesAvailable]; [self _sendEvent: NSStreamEventHasBytesAvailable];
break;
} }
default: if ([self streamStatus] == NSStreamStatusAtEnd)
break; {
[self _sendEvent: NSStreamEventEndEncountered];
}
}
}
} }
if (_sibling && [_sibling _isOpened])
[_sibling _dispatch];
} }
@end @end
@ -871,12 +884,6 @@ static void setNonblocking(SOCKET fd)
@implementation GSFileOutputStream @implementation GSFileOutputStream
- (void) close
{
if (CloseHandle((HANDLE)_loopID) == 0)
[self _recordError];
[super close];
}
- (void) dealloc - (void) dealloc
{ {
@ -947,6 +954,7 @@ static void setNonblocking(SOCKET fd)
{ {
DWORD writeLen; DWORD writeLen;
_unhandledData = NO;
if (_shouldAppend == YES) if (_shouldAppend == YES)
{ {
SetFilePointer((HANDLE)_loopID, 0, 0, FILE_END); SetFilePointer((HANDLE)_loopID, 0, 0, FILE_END);
@ -1061,6 +1069,7 @@ static void setNonblocking(SOCKET fd)
{ {
NSStreamStatus myStatus = [self streamStatus]; NSStreamStatus myStatus = [self streamStatus];
_unhandledData = NO;
if (len < 0) if (len < 0)
{ {
return -1; return -1;
@ -1152,6 +1161,11 @@ static void setNonblocking(SOCKET fd)
{ {
NSStreamStatus myStatus = [self streamStatus]; NSStreamStatus myStatus = [self streamStatus];
if (_unhandledData == YES || myStatus == NSStreamStatusError)
{
*trigger = NO;
return NO;
}
*trigger = YES; *trigger = YES;
if (myStatus == NSStreamStatusWriting) if (myStatus == NSStreamStatusWriting)
{ {
@ -1218,6 +1232,7 @@ static void setNonblocking(SOCKET fd)
{ {
int writeLen; int writeLen;
_unhandledData = NO;
writeLen = send(_sock, buffer, len, 0); writeLen = send(_sock, buffer, len, 0);
if (writeLen == SOCKET_ERROR) if (writeLen == SOCKET_ERROR)
{ {
@ -1304,29 +1319,29 @@ static void setNonblocking(SOCKET fd)
- (void) _dispatch - (void) _dispatch
{ {
NSStreamStatus myStatus;
WSANETWORKEVENTS ocurredEvents;
int error, getReturn;
unsigned len = sizeof(error);
/*
* it is possible the stream is closed yet recieving event
* because of not closed sibling
*/
if ([self streamStatus] == NSStreamStatusClosed) if ([self streamStatus] == NSStreamStatusClosed)
{ {
/*
* It is possible the stream is closed yet recieving event because
* of not closed sibling
*/
NSAssert([_sibling streamStatus] != NSStreamStatusClosed, NSAssert([_sibling streamStatus] != NSStreamStatusClosed,
@"Received event for closed stream"); @"Received event for closed stream");
[_sibling _dispatch]; [_sibling _dispatch];
return;
} }
else
if (WSAEnumNetworkEvents(_sock, _loopID, &ocurredEvents) == SOCKET_ERROR)
{ {
errno = WSAGetLastError(); WSANETWORKEVENTS events;
[self _recordError]; int error = 0;
int getReturn = -1;
if (WSAEnumNetworkEvents(_sock, _loopID, &events) == SOCKET_ERROR)
{
error = WSAGetLastError();
} }
else if ([self streamStatus] == NSStreamStatusOpening) else NSLog(@"EVENTS:%x", events.lNetworkEvents);
if ([self streamStatus] == NSStreamStatusOpening)
{ {
unsigned i = [_modes count]; unsigned i = [_modes count];
@ -1334,13 +1349,19 @@ static void setNonblocking(SOCKET fd)
{ {
[_runloop removeStream: self mode: [_modes objectAtIndex: i]]; [_runloop removeStream: self mode: [_modes objectAtIndex: i]];
} }
if (error == 0)
{
unsigned len = sizeof(error);
getReturn = getsockopt(_sock, SOL_SOCKET, SO_ERROR, getReturn = getsockopt(_sock, SOL_SOCKET, SO_ERROR,
(char*)&error, &len); (char*)&error, &len);
}
if (getReturn >= 0 && !error if (getReturn >= 0 && error == 0
&& (ocurredEvents.lNetworkEvents & FD_CONNECT)) && (events.lNetworkEvents & FD_CONNECT))
{ // finish up the opening { // finish up the opening
ocurredEvents.lNetworkEvents ^= FD_CONNECT; events.lNetworkEvents ^= FD_CONNECT;
_passive = YES; _passive = YES;
[self open]; [self open];
// notify sibling // notify sibling
@ -1349,51 +1370,46 @@ static void setNonblocking(SOCKET fd)
[_sibling open]; [_sibling open];
[_sibling _sendEvent: NSStreamEventOpenCompleted]; [_sibling _sendEvent: NSStreamEventOpenCompleted];
} }
[self _sendEvent: NSStreamEventOpenCompleted];
} }
else // must be an error }
if (error != 0)
{ {
if (error)
errno = error; errno = error;
[self _recordError]; [self _recordError];
if (_sibling)
{
[_sibling _recordError]; [_sibling _recordError];
[_sibling _sendEvent: NSStreamEventOpenCompleted]; [self _sendEvent: NSStreamEventErrorOccurred];
} [_sibling _sendEvent: NSStreamEventErrorOccurred];
}
} }
else else
{ {
if ((ocurredEvents.lNetworkEvents & FD_READ) && if (events.lNetworkEvents & FD_WRITE)
(_sibling && [_sibling _isOpened]))
{ {
ocurredEvents.lNetworkEvents ^= FD_READ;
[_sibling _setStatus: NSStreamStatusOpen];
}
if (ocurredEvents.lNetworkEvents & FD_WRITE)
{
ocurredEvents.lNetworkEvents ^= FD_WRITE;
[self _setStatus: NSStreamStatusOpen]; [self _setStatus: NSStreamStatusOpen];
}
}
myStatus = [self streamStatus];
switch (myStatus)
{
case NSStreamStatusError:
{
[self _sendEvent: NSStreamEventErrorOccurred];
break;
}
case NSStreamStatusOpen:
{
[self _sendEvent: NSStreamEventHasSpaceAvailable]; [self _sendEvent: NSStreamEventHasSpaceAvailable];
break;
} }
default: if (events.lNetworkEvents & FD_READ)
break; {
[_sibling _setStatus: NSStreamStatusOpen];
[_sibling _sendEvent: NSStreamEventHasBytesAvailable];
}
if (events.lNetworkEvents & FD_CLOSE)
{
[self _setStatus: NSStreamStatusAtEnd];
[self _sendEvent: NSStreamEventEndEncountered];
while ([_sibling streamStatus] == NSStreamStatusOpen
&& [_sibling _unhandledData] == NO)
{
[_sibling _sendEvent: NSStreamEventHasBytesAvailable];
}
if ([_sibling streamStatus] == NSStreamStatusAtEnd)
{
[_sibling _sendEvent: NSStreamEventEndEncountered];
}
}
}
} }
if (_sibling && [_sibling _isOpened])
[_sibling _dispatch];
} }
@end @end
@ -1788,7 +1804,7 @@ static void setNonblocking(SOCKET fd)
return 0; return 0;
} }
#define SOCKET_BACKLOG 5 #define SOCKET_BACKLOG 255
- (void) open - (void) open
{ {
@ -1860,17 +1876,17 @@ static void setNonblocking(SOCKET fd)
- (void) _dispatch - (void) _dispatch
{ {
WSANETWORKEVENTS ocurredEvents; WSANETWORKEVENTS events;
if (WSAEnumNetworkEvents(_sock, _loopID, &ocurredEvents) == SOCKET_ERROR) if (WSAEnumNetworkEvents(_sock, _loopID, &events) == SOCKET_ERROR)
{ {
errno = WSAGetLastError(); errno = WSAGetLastError();
[self _recordError]; [self _recordError];
[self _sendEvent: NSStreamEventErrorOccurred]; [self _sendEvent: NSStreamEventErrorOccurred];
} }
else if (ocurredEvents.lNetworkEvents & FD_ACCEPT) else if (events.lNetworkEvents & FD_ACCEPT)
{ {
ocurredEvents.lNetworkEvents ^= FD_ACCEPT; events.lNetworkEvents ^= FD_ACCEPT;
[self _setStatus: NSStreamStatusReading]; [self _setStatus: NSStreamStatusReading];
[self _sendEvent: NSStreamEventHasBytesAvailable]; [self _sendEvent: NSStreamEventHasBytesAvailable];
} }