mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 09:04:13 +00:00
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:
parent
aa1ecf7e6e
commit
3156b070fe
5 changed files with 261 additions and 198 deletions
|
@ -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/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.
|
||||
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>
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@
|
|||
id _delegate; /* Delegate controls operation. */\
|
||||
NSMutableDictionary *_properties; /* storage for properties */\
|
||||
BOOL _delegateValid;/* whether the delegate responds*/\
|
||||
BOOL _unhandledData; /* no read/write since event */\
|
||||
NSError *_lastError; /* last error occured */\
|
||||
NSStreamStatus _currentStatus;/* current status */\
|
||||
NSMutableArray *_modes; /* currently scheduled modes. */\
|
||||
|
@ -121,6 +122,11 @@ IVARS
|
|||
* record an error based on errno
|
||||
*/
|
||||
- (void) _recordError;
|
||||
|
||||
/**
|
||||
* say whether there is unahdnled data for the stream.
|
||||
*/
|
||||
- (BOOL) _unhandledData;
|
||||
@end
|
||||
|
||||
@interface GSInputStream : NSInputStream
|
||||
|
|
|
@ -318,6 +318,10 @@ static RunLoopEventType typeForStream(NSStream *aStream)
|
|||
{
|
||||
}
|
||||
|
||||
- (BOOL) _unhandledData
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation GSStream (Private)
|
||||
|
@ -351,7 +355,17 @@ static RunLoopEventType typeForStream(NSStream *aStream)
|
|||
|
||||
- (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];
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
@implementation GSInputStream
|
||||
|
@ -432,6 +478,7 @@ static RunLoopEventType typeForStream(NSStream *aStream)
|
|||
unsigned long dataSize = [_data length];
|
||||
unsigned long copySize;
|
||||
|
||||
_unhandledData = NO;
|
||||
NSAssert(dataSize >= _pointer, @"Buffer overflow!");
|
||||
if (len + _pointer > dataSize)
|
||||
{
|
||||
|
@ -482,8 +529,7 @@ static RunLoopEventType typeForStream(NSStream *aStream)
|
|||
BOOL av = [self hasBytesAvailable];
|
||||
NSStreamEvent myEvent = av ? NSStreamEventHasBytesAvailable :
|
||||
NSStreamEventEndEncountered;
|
||||
NSStreamStatus myStatus = av ? NSStreamStatusReading :
|
||||
NSStreamStatusAtEnd;
|
||||
NSStreamStatus myStatus = av ? NSStreamStatusOpen : NSStreamStatusAtEnd;
|
||||
|
||||
[self _setStatus: myStatus];
|
||||
[self _sendEvent: myEvent];
|
||||
|
@ -523,6 +569,7 @@ static RunLoopEventType typeForStream(NSStream *aStream)
|
|||
|
||||
- (int) write: (const uint8_t *)buffer maxLength: (unsigned int)len
|
||||
{
|
||||
_unhandledData = NO;
|
||||
if (_fixedSize)
|
||||
{
|
||||
unsigned long dataLen = [_data length];
|
||||
|
|
|
@ -297,6 +297,7 @@ static void setNonblocking(int fd)
|
|||
{
|
||||
int readLen;
|
||||
|
||||
_unhandledData = NO;
|
||||
readLen = read((intptr_t)_loopID, buffer, len);
|
||||
if (readLen < 0 && errno != EAGAIN && errno != EINTR)
|
||||
[self _recordError];
|
||||
|
@ -353,15 +354,6 @@ static void setNonblocking(int fd)
|
|||
[super close];
|
||||
}
|
||||
|
||||
- (void) _dispatch
|
||||
{
|
||||
NSStreamEvent myEvent;
|
||||
|
||||
[self _setStatus: NSStreamStatusReading];
|
||||
myEvent = NSStreamEventHasBytesAvailable;
|
||||
[self _sendEvent: myEvent];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation GSSocketInputStream
|
||||
|
@ -472,6 +464,7 @@ static void setNonblocking(int fd)
|
|||
{
|
||||
int readLen;
|
||||
|
||||
_unhandledData = NO;
|
||||
readLen = read((intptr_t)_loopID, buffer, len);
|
||||
if (readLen < 0 && errno != EAGAIN && errno != EINTR)
|
||||
[self _recordError];
|
||||
|
@ -507,7 +500,8 @@ static void setNonblocking(int fd)
|
|||
{
|
||||
[_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)
|
||||
{ // finish up the opening
|
||||
|
@ -530,7 +524,7 @@ static void setNonblocking(int fd)
|
|||
}
|
||||
else
|
||||
{
|
||||
[self _setStatus: NSStreamStatusReading];
|
||||
[self _setStatus: NSStreamStatusOpen];
|
||||
myEvent = NSStreamEventHasBytesAvailable;
|
||||
}
|
||||
[self _sendEvent: myEvent];
|
||||
|
@ -666,6 +660,8 @@ static void setNonblocking(int fd)
|
|||
- (int) write: (const uint8_t *)buffer maxLength: (unsigned int)len
|
||||
{
|
||||
int writeLen;
|
||||
|
||||
_unhandledData = NO;
|
||||
writeLen = write((intptr_t)_loopID, buffer, len);
|
||||
if (writeLen < 0 && errno != EAGAIN && errno != EINTR)
|
||||
[self _recordError];
|
||||
|
@ -720,15 +716,6 @@ static void setNonblocking(int fd)
|
|||
return [super propertyForKey: key];
|
||||
}
|
||||
|
||||
- (void) _dispatch
|
||||
{
|
||||
NSStreamEvent myEvent;
|
||||
|
||||
[self _setStatus: NSStreamStatusWriting];
|
||||
myEvent = NSStreamEventHasSpaceAvailable;
|
||||
[self _sendEvent: myEvent];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation GSSocketOutputStream
|
||||
|
@ -776,6 +763,8 @@ static void setNonblocking(int fd)
|
|||
- (int) write: (const uint8_t *)buffer maxLength: (unsigned int)len
|
||||
{
|
||||
int writeLen;
|
||||
|
||||
_unhandledData = NO;
|
||||
writeLen = write((intptr_t)_loopID, buffer, len);
|
||||
if (writeLen < 0 && errno != EAGAIN && errno != EINTR)
|
||||
[self _recordError];
|
||||
|
@ -868,7 +857,8 @@ static void setNonblocking(int fd)
|
|||
{
|
||||
[_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)
|
||||
{ // finish up the opening
|
||||
myEvent = NSStreamEventOpenCompleted;
|
||||
|
@ -890,7 +880,7 @@ static void setNonblocking(int fd)
|
|||
}
|
||||
else
|
||||
{
|
||||
[self _setStatus: NSStreamStatusWriting];
|
||||
[self _setStatus: NSStreamStatusOpen];
|
||||
myEvent = NSStreamEventHasSpaceAvailable;
|
||||
}
|
||||
[self _sendEvent: myEvent];
|
||||
|
@ -1411,7 +1401,7 @@ static void setNonblocking(int fd)
|
|||
{
|
||||
NSStreamEvent myEvent;
|
||||
|
||||
[self _setStatus: NSStreamStatusReading];
|
||||
[self _setStatus: NSStreamStatusOpen];
|
||||
myEvent = NSStreamEventHasBytesAvailable;
|
||||
[self _sendEvent: myEvent];
|
||||
}
|
||||
|
|
|
@ -324,6 +324,7 @@ static void setNonblocking(SOCKET fd)
|
|||
{
|
||||
DWORD readLen;
|
||||
|
||||
_unhandledData = NO;
|
||||
if (ReadFile((HANDLE)_loopID, buffer, len, &readLen, NULL) == 0)
|
||||
{
|
||||
[self _recordError];
|
||||
|
@ -342,7 +343,7 @@ static void setNonblocking(SOCKET fd)
|
|||
BOOL av = [self hasBytesAvailable];
|
||||
NSStreamEvent myEvent = av ? NSStreamEventHasBytesAvailable :
|
||||
NSStreamEventEndEncountered;
|
||||
NSStreamStatus myStatus = av ? NSStreamStatusReading :
|
||||
NSStreamStatus myStatus = av ? NSStreamStatusOpen :
|
||||
NSStreamStatusAtEnd;
|
||||
|
||||
[self _setStatus: myStatus];
|
||||
|
@ -502,6 +503,7 @@ static void setNonblocking(SOCKET fd)
|
|||
{
|
||||
NSStreamStatus myStatus = [self streamStatus];
|
||||
|
||||
_unhandledData = NO;
|
||||
if (myStatus == NSStreamStatusReading)
|
||||
{
|
||||
myStatus = [self _check];
|
||||
|
@ -587,6 +589,11 @@ static void setNonblocking(SOCKET fd)
|
|||
{
|
||||
NSStreamStatus myStatus = [self streamStatus];
|
||||
|
||||
if (_unhandledData == YES || myStatus == NSStreamStatusError)
|
||||
{
|
||||
*trigger = NO;
|
||||
return NO;
|
||||
}
|
||||
*trigger = YES;
|
||||
if (myStatus == NSStreamStatusReading)
|
||||
{
|
||||
|
@ -712,19 +719,28 @@ static void setNonblocking(SOCKET fd)
|
|||
{
|
||||
int readLen;
|
||||
|
||||
_unhandledData = NO;
|
||||
readLen = recv(_sock, buffer, len, 0);
|
||||
if (readLen == SOCKET_ERROR)
|
||||
{
|
||||
errno = WSAGetLastError();
|
||||
if (errno == WSAEINPROGRESS || errno == WSAEWOULDBLOCK)
|
||||
[self _setStatus: NSStreamStatusReading];
|
||||
{
|
||||
[self _setStatus: NSStreamStatusReading];
|
||||
}
|
||||
else if (errno != WSAEINTR)
|
||||
[self _recordError];
|
||||
{
|
||||
[self _recordError];
|
||||
}
|
||||
}
|
||||
else if (readLen == 0)
|
||||
[self _setStatus: NSStreamStatusAtEnd];
|
||||
{
|
||||
[self _setStatus: NSStreamStatusAtEnd];
|
||||
}
|
||||
else
|
||||
[self _setStatus: NSStreamStatusOpen];
|
||||
{
|
||||
[self _setStatus: NSStreamStatusOpen];
|
||||
}
|
||||
return readLen;
|
||||
}
|
||||
|
||||
|
@ -742,98 +758,95 @@ static void setNonblocking(SOCKET fd)
|
|||
|
||||
- (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)
|
||||
{
|
||||
/*
|
||||
* It is possible the stream is closed yet recieving event because
|
||||
* of not closed sibling
|
||||
*/
|
||||
NSAssert([_sibling streamStatus] != NSStreamStatusClosed,
|
||||
@"Received event for closed stream");
|
||||
@"Received event for closed stream");
|
||||
[_sibling _dispatch];
|
||||
return;
|
||||
}
|
||||
|
||||
if (WSAEnumNetworkEvents(_sock, _loopID, &ocurredEvents) == SOCKET_ERROR)
|
||||
{
|
||||
errno = WSAGetLastError();
|
||||
[self _recordError];
|
||||
}
|
||||
else if ([self streamStatus] == NSStreamStatusOpening)
|
||||
{
|
||||
unsigned i = [_modes count];
|
||||
|
||||
while (i-- > 0)
|
||||
{
|
||||
[_runloop removeStream: self mode: [_modes objectAtIndex: i]];
|
||||
}
|
||||
getReturn = getsockopt(_sock, SOL_SOCKET, SO_ERROR,
|
||||
(char*)&error, &len);
|
||||
|
||||
if (getReturn >= 0 && !error
|
||||
&& (ocurredEvents.lNetworkEvents & FD_CONNECT))
|
||||
{ // finish up the opening
|
||||
ocurredEvents.lNetworkEvents ^= FD_CONNECT;
|
||||
_passive = YES;
|
||||
[self open];
|
||||
[self _sendEvent: NSStreamEventOpenCompleted];
|
||||
// notify sibling
|
||||
if (_sibling)
|
||||
{
|
||||
[_sibling open];
|
||||
[_sibling _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];
|
||||
}
|
||||
}
|
||||
WSANETWORKEVENTS events;
|
||||
int error = 0;
|
||||
int getReturn = -1;
|
||||
|
||||
myStatus = [self streamStatus];
|
||||
switch (myStatus)
|
||||
{
|
||||
case NSStreamStatusError:
|
||||
if (WSAEnumNetworkEvents(_sock, _loopID, &events) == SOCKET_ERROR)
|
||||
{
|
||||
error = WSAGetLastError();
|
||||
}
|
||||
else NSLog(@"EVENTS:%x", events.lNetworkEvents);
|
||||
|
||||
if ([self streamStatus] == NSStreamStatusOpening)
|
||||
{
|
||||
unsigned i = [_modes count];
|
||||
|
||||
while (i-- > 0)
|
||||
{
|
||||
[_runloop removeStream: self mode: [_modes objectAtIndex: i]];
|
||||
}
|
||||
if (error == 0)
|
||||
{
|
||||
unsigned len = sizeof(error);
|
||||
|
||||
getReturn = getsockopt(_sock, SOL_SOCKET, SO_ERROR,
|
||||
(char*)&error, &len);
|
||||
}
|
||||
|
||||
if (getReturn >= 0 && error == 0
|
||||
&& (events.lNetworkEvents & FD_CONNECT))
|
||||
{ // finish up the opening
|
||||
_passive = YES;
|
||||
[self open];
|
||||
// notify sibling
|
||||
if (_sibling)
|
||||
{
|
||||
[_sibling open];
|
||||
[_sibling _sendEvent: NSStreamEventOpenCompleted];
|
||||
}
|
||||
[self _sendEvent: NSStreamEventOpenCompleted];
|
||||
}
|
||||
}
|
||||
|
||||
if (error != 0)
|
||||
{
|
||||
errno = error;
|
||||
[self _recordError];
|
||||
[_sibling _recordError];
|
||||
[self _sendEvent: NSStreamEventErrorOccurred];
|
||||
break;
|
||||
[_sibling _sendEvent: NSStreamEventErrorOccurred];
|
||||
}
|
||||
case NSStreamStatusOpen:
|
||||
else
|
||||
{
|
||||
[self _sendEvent: NSStreamEventHasBytesAvailable];
|
||||
break;
|
||||
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];
|
||||
}
|
||||
if ([self streamStatus] == NSStreamStatusAtEnd)
|
||||
{
|
||||
[self _sendEvent: NSStreamEventEndEncountered];
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (_sibling && [_sibling _isOpened])
|
||||
[_sibling _dispatch];
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -871,12 +884,6 @@ static void setNonblocking(SOCKET fd)
|
|||
|
||||
@implementation GSFileOutputStream
|
||||
|
||||
- (void) close
|
||||
{
|
||||
if (CloseHandle((HANDLE)_loopID) == 0)
|
||||
[self _recordError];
|
||||
[super close];
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
|
@ -947,6 +954,7 @@ static void setNonblocking(SOCKET fd)
|
|||
{
|
||||
DWORD writeLen;
|
||||
|
||||
_unhandledData = NO;
|
||||
if (_shouldAppend == YES)
|
||||
{
|
||||
SetFilePointer((HANDLE)_loopID, 0, 0, FILE_END);
|
||||
|
@ -1061,6 +1069,7 @@ static void setNonblocking(SOCKET fd)
|
|||
{
|
||||
NSStreamStatus myStatus = [self streamStatus];
|
||||
|
||||
_unhandledData = NO;
|
||||
if (len < 0)
|
||||
{
|
||||
return -1;
|
||||
|
@ -1152,6 +1161,11 @@ static void setNonblocking(SOCKET fd)
|
|||
{
|
||||
NSStreamStatus myStatus = [self streamStatus];
|
||||
|
||||
if (_unhandledData == YES || myStatus == NSStreamStatusError)
|
||||
{
|
||||
*trigger = NO;
|
||||
return NO;
|
||||
}
|
||||
*trigger = YES;
|
||||
if (myStatus == NSStreamStatusWriting)
|
||||
{
|
||||
|
@ -1218,6 +1232,7 @@ static void setNonblocking(SOCKET fd)
|
|||
{
|
||||
int writeLen;
|
||||
|
||||
_unhandledData = NO;
|
||||
writeLen = send(_sock, buffer, len, 0);
|
||||
if (writeLen == SOCKET_ERROR)
|
||||
{
|
||||
|
@ -1304,96 +1319,97 @@ static void setNonblocking(SOCKET fd)
|
|||
|
||||
- (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)
|
||||
{
|
||||
/*
|
||||
* It is possible the stream is closed yet recieving event because
|
||||
* of not closed sibling
|
||||
*/
|
||||
NSAssert([_sibling streamStatus] != NSStreamStatusClosed,
|
||||
@"Received event for closed stream");
|
||||
[_sibling _dispatch];
|
||||
return;
|
||||
}
|
||||
|
||||
if (WSAEnumNetworkEvents(_sock, _loopID, &ocurredEvents) == SOCKET_ERROR)
|
||||
{
|
||||
errno = WSAGetLastError();
|
||||
[self _recordError];
|
||||
}
|
||||
else if ([self streamStatus] == NSStreamStatusOpening)
|
||||
{
|
||||
unsigned i = [_modes count];
|
||||
|
||||
while (i-- > 0)
|
||||
{
|
||||
[_runloop removeStream: self mode: [_modes objectAtIndex: i]];
|
||||
}
|
||||
getReturn = getsockopt(_sock, SOL_SOCKET, SO_ERROR,
|
||||
(char*)&error, &len);
|
||||
|
||||
if (getReturn >= 0 && !error
|
||||
&& (ocurredEvents.lNetworkEvents & FD_CONNECT))
|
||||
{ // finish up the opening
|
||||
ocurredEvents.lNetworkEvents ^= FD_CONNECT;
|
||||
_passive = YES;
|
||||
[self open];
|
||||
// notify sibling
|
||||
if (_sibling)
|
||||
{
|
||||
[_sibling open];
|
||||
[_sibling _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) &&
|
||||
(_sibling && [_sibling _isOpened]))
|
||||
{
|
||||
ocurredEvents.lNetworkEvents ^= FD_READ;
|
||||
[_sibling _setStatus: NSStreamStatusOpen];
|
||||
}
|
||||
if (ocurredEvents.lNetworkEvents & FD_WRITE)
|
||||
{
|
||||
ocurredEvents.lNetworkEvents ^= FD_WRITE;
|
||||
[self _setStatus: NSStreamStatusOpen];
|
||||
}
|
||||
}
|
||||
myStatus = [self streamStatus];
|
||||
switch (myStatus)
|
||||
{
|
||||
case NSStreamStatusError:
|
||||
WSANETWORKEVENTS events;
|
||||
int error = 0;
|
||||
int getReturn = -1;
|
||||
|
||||
if (WSAEnumNetworkEvents(_sock, _loopID, &events) == SOCKET_ERROR)
|
||||
{
|
||||
error = WSAGetLastError();
|
||||
}
|
||||
else NSLog(@"EVENTS:%x", events.lNetworkEvents);
|
||||
|
||||
if ([self streamStatus] == NSStreamStatusOpening)
|
||||
{
|
||||
unsigned i = [_modes count];
|
||||
|
||||
while (i-- > 0)
|
||||
{
|
||||
[_runloop removeStream: self mode: [_modes objectAtIndex: i]];
|
||||
}
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
unsigned len = sizeof(error);
|
||||
|
||||
getReturn = getsockopt(_sock, SOL_SOCKET, SO_ERROR,
|
||||
(char*)&error, &len);
|
||||
}
|
||||
|
||||
if (getReturn >= 0 && error == 0
|
||||
&& (events.lNetworkEvents & FD_CONNECT))
|
||||
{ // finish up the opening
|
||||
events.lNetworkEvents ^= FD_CONNECT;
|
||||
_passive = YES;
|
||||
[self open];
|
||||
// notify sibling
|
||||
if (_sibling)
|
||||
{
|
||||
[_sibling open];
|
||||
[_sibling _sendEvent: NSStreamEventOpenCompleted];
|
||||
}
|
||||
[self _sendEvent: NSStreamEventOpenCompleted];
|
||||
}
|
||||
}
|
||||
|
||||
if (error != 0)
|
||||
{
|
||||
errno = error;
|
||||
[self _recordError];
|
||||
[_sibling _recordError];
|
||||
[self _sendEvent: NSStreamEventErrorOccurred];
|
||||
break;
|
||||
[_sibling _sendEvent: NSStreamEventErrorOccurred];
|
||||
}
|
||||
case NSStreamStatusOpen:
|
||||
else
|
||||
{
|
||||
[self _sendEvent: NSStreamEventHasSpaceAvailable];
|
||||
break;
|
||||
if (events.lNetworkEvents & FD_WRITE)
|
||||
{
|
||||
[self _setStatus: NSStreamStatusOpen];
|
||||
[self _sendEvent: NSStreamEventHasSpaceAvailable];
|
||||
}
|
||||
if (events.lNetworkEvents & FD_READ)
|
||||
{
|
||||
[_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];
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (_sibling && [_sibling _isOpened])
|
||||
[_sibling _dispatch];
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -1788,7 +1804,7 @@ static void setNonblocking(SOCKET fd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define SOCKET_BACKLOG 5
|
||||
#define SOCKET_BACKLOG 255
|
||||
|
||||
- (void) open
|
||||
{
|
||||
|
@ -1860,17 +1876,17 @@ static void setNonblocking(SOCKET fd)
|
|||
|
||||
- (void) _dispatch
|
||||
{
|
||||
WSANETWORKEVENTS ocurredEvents;
|
||||
WSANETWORKEVENTS events;
|
||||
|
||||
if (WSAEnumNetworkEvents(_sock, _loopID, &ocurredEvents) == SOCKET_ERROR)
|
||||
if (WSAEnumNetworkEvents(_sock, _loopID, &events) == SOCKET_ERROR)
|
||||
{
|
||||
errno = WSAGetLastError();
|
||||
[self _recordError];
|
||||
[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 _sendEvent: NSStreamEventHasBytesAvailable];
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue