mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-30 08:21:25 +00:00
winsock stream fixes
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@23243 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
8fb233e3dc
commit
6f9c159619
5 changed files with 181 additions and 77 deletions
|
@ -1,3 +1,11 @@
|
||||||
|
2006-08-10 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
|
* Source\GSStream.h:
|
||||||
|
* Source\GSStream.m:
|
||||||
|
* Source\unix\NSStream.m:
|
||||||
|
* Source\win32\NSStreamWin32.m:
|
||||||
|
Ensure all events are posted. Fixup for winsock write signalling.
|
||||||
|
|
||||||
2006-08-09 Richard Frith-Macdonald <rfm@gnu.org>
|
2006-08-09 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
* Documentation/Base.gsdoc: Improve links to macros.
|
* Documentation/Base.gsdoc: Improve links to macros.
|
||||||
|
|
|
@ -68,12 +68,12 @@
|
||||||
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. */\
|
||||||
NSRunLoop *_runloop; /* currently scheduled loop. */\
|
NSRunLoop *_runloop; /* currently scheduled loop. */\
|
||||||
void *_loopID; /* file descriptor etc */\
|
void *_loopID; /* file descriptor etc. */\
|
||||||
|
int _events; /* Signalled events. */\
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -124,7 +124,7 @@ IVARS
|
||||||
- (void) _recordError;
|
- (void) _recordError;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* say whether there is unahdnled data for the stream.
|
* say whether there is unhandled data for the stream.
|
||||||
*/
|
*/
|
||||||
- (BOOL) _unhandledData;
|
- (BOOL) _unhandledData;
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -144,8 +144,11 @@ static RunLoopEventType typeForStream(NSStream *aStream)
|
||||||
[_runloop removeStream: self mode: [_modes objectAtIndex: i]];
|
[_runloop removeStream: self mode: [_modes objectAtIndex: i]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_unhandledData = NO;
|
|
||||||
[self _setStatus: NSStreamStatusClosed];
|
[self _setStatus: NSStreamStatusClosed];
|
||||||
|
/* We don't want to send any events the the delegate after the
|
||||||
|
* stream has been closed.
|
||||||
|
*/
|
||||||
|
_delegateValid = NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) dealloc
|
- (void) dealloc
|
||||||
|
@ -213,18 +216,19 @@ static RunLoopEventType typeForStream(NSStream *aStream)
|
||||||
|
|
||||||
- (void) removeFromRunLoop: (NSRunLoop *)aRunLoop forMode: (NSString *)mode
|
- (void) removeFromRunLoop: (NSRunLoop *)aRunLoop forMode: (NSString *)mode
|
||||||
{
|
{
|
||||||
NSAssert(_runloop == aRunLoop,
|
if (_runloop == aRunLoop)
|
||||||
@"Attempt to remove unscheduled runloop");
|
|
||||||
if ([_modes containsObject: mode])
|
|
||||||
{
|
{
|
||||||
if ([self _isOpened])
|
if ([_modes containsObject: mode])
|
||||||
{
|
{
|
||||||
[_runloop removeStream: self mode: mode];
|
if ([self _isOpened])
|
||||||
}
|
{
|
||||||
[_modes removeObject: mode];
|
[_runloop removeStream: self mode: mode];
|
||||||
if ([_modes count] == 0)
|
}
|
||||||
{
|
[_modes removeObject: mode];
|
||||||
DESTROY(_runloop);
|
if ([_modes count] == 0)
|
||||||
|
{
|
||||||
|
DESTROY(_runloop);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -256,8 +260,15 @@ static RunLoopEventType typeForStream(NSStream *aStream)
|
||||||
{
|
{
|
||||||
_delegate = self;
|
_delegate = self;
|
||||||
}
|
}
|
||||||
_delegateValid
|
if ([self streamStatus] != NSStreamStatusClosed
|
||||||
= [_delegate respondsToSelector: @selector(stream:handleEvent:)];
|
&& [self streamStatus] != NSStreamStatusError)
|
||||||
|
{
|
||||||
|
/* We don't want to send any events the the delegate after the
|
||||||
|
* stream has been closed.
|
||||||
|
*/
|
||||||
|
_delegateValid
|
||||||
|
= [_delegate respondsToSelector: @selector(stream:handleEvent:)];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) setProperty: (id)property forKey: (NSString *)key
|
- (BOOL) setProperty: (id)property forKey: (NSString *)key
|
||||||
|
@ -359,47 +370,106 @@ static RunLoopEventType typeForStream(NSStream *aStream)
|
||||||
NSStreamStatus last = [self streamStatus];
|
NSStreamStatus last = [self streamStatus];
|
||||||
NSStreamStatus current;
|
NSStreamStatus current;
|
||||||
|
|
||||||
if (event == NSStreamEventHasSpaceAvailable
|
if (event == NSStreamEventNone)
|
||||||
|| event == NSStreamEventHasBytesAvailable)
|
|
||||||
{
|
{
|
||||||
/* If we have a data event, we mark the stream as having unhandled
|
return;
|
||||||
* 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)
|
else if (event == NSStreamEventOpenCompleted)
|
||||||
{
|
{
|
||||||
[_delegate stream: self handleEvent: event];
|
if ((_events & event) == 0)
|
||||||
}
|
|
||||||
|
|
||||||
while ((current = [self streamStatus]) != last)
|
|
||||||
{
|
|
||||||
last = current;
|
|
||||||
|
|
||||||
/* If we our status changed while the handler was dealing with an
|
|
||||||
* event, we must send it the new event to let it know.
|
|
||||||
*/
|
|
||||||
if (current == NSStreamStatusAtEnd)
|
|
||||||
{
|
{
|
||||||
|
_events |= NSStreamEventOpenCompleted;
|
||||||
if (_delegateValid == YES)
|
if (_delegateValid == YES)
|
||||||
{
|
{
|
||||||
event = NSStreamEventEndEncountered;
|
[_delegate stream: self
|
||||||
[_delegate stream: self handleEvent: event];
|
handleEvent: NSStreamEventOpenCompleted];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if (event == NSStreamEventHasBytesAvailable)
|
||||||
|
{
|
||||||
|
if ((_events & NSStreamEventOpenCompleted) == 0)
|
||||||
|
{
|
||||||
|
_events |= NSStreamEventOpenCompleted;
|
||||||
|
if (_delegateValid == YES)
|
||||||
|
{
|
||||||
|
[_delegate stream: self
|
||||||
|
handleEvent: NSStreamEventOpenCompleted];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((_events & NSStreamEventHasBytesAvailable) == 0)
|
||||||
|
{
|
||||||
|
_events |= NSStreamEventHasBytesAvailable;
|
||||||
|
if (_delegateValid == YES)
|
||||||
|
{
|
||||||
|
[_delegate stream: self
|
||||||
|
handleEvent: NSStreamEventHasBytesAvailable];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (event == NSStreamEventHasSpaceAvailable)
|
||||||
|
{
|
||||||
|
if ((_events & NSStreamEventOpenCompleted) == 0)
|
||||||
|
{
|
||||||
|
_events |= NSStreamEventOpenCompleted;
|
||||||
|
if (_delegateValid == YES)
|
||||||
|
{
|
||||||
|
[_delegate stream: self
|
||||||
|
handleEvent: NSStreamEventOpenCompleted];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((_events & NSStreamEventHasSpaceAvailable) == 0)
|
||||||
|
{
|
||||||
|
_events |= NSStreamEventHasSpaceAvailable;
|
||||||
|
if (_delegateValid == YES)
|
||||||
|
{
|
||||||
|
[_delegate stream: self
|
||||||
|
handleEvent: NSStreamEventHasSpaceAvailable];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (event == NSStreamEventErrorOccurred)
|
||||||
|
{
|
||||||
|
if ((_events & NSStreamEventErrorOccurred) == 0)
|
||||||
|
{
|
||||||
|
_events |= NSStreamEventErrorOccurred;
|
||||||
|
if (_delegateValid == YES)
|
||||||
|
{
|
||||||
|
[_delegate stream: self
|
||||||
|
handleEvent: NSStreamEventErrorOccurred];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (event == NSStreamEventEndEncountered)
|
||||||
|
{
|
||||||
|
if ((_events & NSStreamEventEndEncountered) == 0)
|
||||||
|
{
|
||||||
|
_events |= NSStreamEventEndEncountered;
|
||||||
|
if (_delegateValid == YES)
|
||||||
|
{
|
||||||
|
[_delegate stream: self
|
||||||
|
handleEvent: NSStreamEventEndEncountered];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"Unknown event (%d) passed to _sendEvent:", event];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If our status changed while the handler was dealing with an
|
||||||
|
* event, we may need to send it the new event to let it know.
|
||||||
|
*/
|
||||||
|
if ((current = [self streamStatus]) != last)
|
||||||
|
{
|
||||||
|
if (current == NSStreamStatusAtEnd)
|
||||||
|
{
|
||||||
|
[self _sendEvent: NSStreamEventEndEncountered];
|
||||||
|
}
|
||||||
else if (current == NSStreamStatusError)
|
else if (current == NSStreamStatusError)
|
||||||
{
|
{
|
||||||
if (_delegateValid == YES)
|
[self _sendEvent: NSStreamEventErrorOccurred];
|
||||||
{
|
|
||||||
event = NSStreamEventErrorOccurred;
|
|
||||||
[_delegate stream: self handleEvent: event];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return; // not an event.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -421,12 +491,17 @@ static RunLoopEventType typeForStream(NSStream *aStream)
|
||||||
|
|
||||||
- (BOOL) _unhandledData
|
- (BOOL) _unhandledData
|
||||||
{
|
{
|
||||||
return _unhandledData;
|
if (_events
|
||||||
|
& (NSStreamEventHasBytesAvailable | NSStreamEventHasSpaceAvailable))
|
||||||
|
{
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) runLoopShouldBlock: (BOOL*)trigger
|
- (BOOL) runLoopShouldBlock: (BOOL*)trigger
|
||||||
{
|
{
|
||||||
if (_unhandledData == YES
|
if ([self _unhandledData] == YES
|
||||||
|| _currentStatus == NSStreamStatusError
|
|| _currentStatus == NSStreamStatusError
|
||||||
|| _currentStatus == NSStreamStatusAtEnd)
|
|| _currentStatus == NSStreamStatusAtEnd)
|
||||||
{
|
{
|
||||||
|
@ -512,7 +587,7 @@ static RunLoopEventType typeForStream(NSStream *aStream)
|
||||||
unsigned long dataSize = [_data length];
|
unsigned long dataSize = [_data length];
|
||||||
unsigned long copySize;
|
unsigned long copySize;
|
||||||
|
|
||||||
_unhandledData = NO;
|
_events &= ~NSStreamEventHasSpaceAvailable;
|
||||||
NSAssert(dataSize >= _pointer, @"Buffer overflow!");
|
NSAssert(dataSize >= _pointer, @"Buffer overflow!");
|
||||||
if (len + _pointer > dataSize)
|
if (len + _pointer > dataSize)
|
||||||
{
|
{
|
||||||
|
@ -602,7 +677,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;
|
_events &= ~NSStreamEventHasBytesAvailable;
|
||||||
if (_fixedSize)
|
if (_fixedSize)
|
||||||
{
|
{
|
||||||
unsigned long dataLen = [_data length];
|
unsigned long dataLen = [_data length];
|
||||||
|
|
|
@ -297,7 +297,7 @@ static void setNonblocking(int fd)
|
||||||
{
|
{
|
||||||
int readLen;
|
int readLen;
|
||||||
|
|
||||||
_unhandledData = NO;
|
_events &= ~NSStreamEventHasBytesAvailable;
|
||||||
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];
|
||||||
|
@ -475,7 +475,7 @@ static void setNonblocking(int fd)
|
||||||
{
|
{
|
||||||
int readLen;
|
int readLen;
|
||||||
|
|
||||||
_unhandledData = NO;
|
_events &= ~NSStreamEventHasBytesAvailable;
|
||||||
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];
|
||||||
|
@ -676,7 +676,7 @@ static void setNonblocking(int fd)
|
||||||
{
|
{
|
||||||
int writeLen;
|
int writeLen;
|
||||||
|
|
||||||
_unhandledData = NO;
|
_events &= ~NSStreamEventHasSpaceAvailable;
|
||||||
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];
|
||||||
|
@ -790,7 +790,7 @@ static void setNonblocking(int fd)
|
||||||
{
|
{
|
||||||
int writeLen;
|
int writeLen;
|
||||||
|
|
||||||
_unhandledData = NO;
|
_events &= ~NSStreamEventHasSpaceAvailable;
|
||||||
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];
|
||||||
|
@ -1386,7 +1386,7 @@ static void setNonblocking(int fd)
|
||||||
socklen_t len = [ins sockLen];
|
socklen_t len = [ins sockLen];
|
||||||
int acceptReturn = accept((intptr_t)_loopID, [ins peerAddr], &len);
|
int acceptReturn = accept((intptr_t)_loopID, [ins peerAddr], &len);
|
||||||
|
|
||||||
_unhandledData = NO;
|
_events &= ~NSStreamEventHasBytesAvailable;
|
||||||
if (acceptReturn < 0)
|
if (acceptReturn < 0)
|
||||||
{ // test for real error
|
{ // test for real error
|
||||||
if (errno != EWOULDBLOCK
|
if (errno != EWOULDBLOCK
|
||||||
|
|
|
@ -330,7 +330,7 @@ static void setNonblocking(SOCKET fd)
|
||||||
{
|
{
|
||||||
DWORD readLen;
|
DWORD readLen;
|
||||||
|
|
||||||
_unhandledData = NO;
|
_events &= ~NSStreamEventHasBytesAvailable;
|
||||||
if (ReadFile((HANDLE)_loopID, buffer, len, &readLen, NULL) == 0)
|
if (ReadFile((HANDLE)_loopID, buffer, len, &readLen, NULL) == 0)
|
||||||
{
|
{
|
||||||
[self _recordError];
|
[self _recordError];
|
||||||
|
@ -509,7 +509,7 @@ static void setNonblocking(SOCKET fd)
|
||||||
{
|
{
|
||||||
NSStreamStatus myStatus = [self streamStatus];
|
NSStreamStatus myStatus = [self streamStatus];
|
||||||
|
|
||||||
_unhandledData = NO;
|
_events &= ~NSStreamEventHasBytesAvailable;
|
||||||
if (myStatus == NSStreamStatusReading)
|
if (myStatus == NSStreamStatusReading)
|
||||||
{
|
{
|
||||||
myStatus = [self _check];
|
myStatus = [self _check];
|
||||||
|
@ -595,7 +595,7 @@ static void setNonblocking(SOCKET fd)
|
||||||
{
|
{
|
||||||
NSStreamStatus myStatus = [self streamStatus];
|
NSStreamStatus myStatus = [self streamStatus];
|
||||||
|
|
||||||
if (_unhandledData == YES || myStatus == NSStreamStatusError)
|
if ([self _unhandledData] == YES || myStatus == NSStreamStatusError)
|
||||||
{
|
{
|
||||||
*trigger = NO;
|
*trigger = NO;
|
||||||
return NO;
|
return NO;
|
||||||
|
@ -735,7 +735,7 @@ static void setNonblocking(SOCKET fd)
|
||||||
{
|
{
|
||||||
int readLen;
|
int readLen;
|
||||||
|
|
||||||
_unhandledData = NO;
|
_events &= ~NSStreamEventHasBytesAvailable;
|
||||||
readLen = recv(_sock, buffer, len, 0);
|
readLen = recv(_sock, buffer, len, 0);
|
||||||
if (readLen == SOCKET_ERROR)
|
if (readLen == SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
|
@ -847,18 +847,25 @@ else NSLog(@"EVENTS 0x%x on %p", events.lNetworkEvents, self);
|
||||||
{
|
{
|
||||||
if (events.lNetworkEvents & FD_WRITE)
|
if (events.lNetworkEvents & FD_WRITE)
|
||||||
{
|
{
|
||||||
|
NSAssert([_sibling _isOpened], NSInternalInconsistencyException);
|
||||||
|
/* Clear NSStreamStatusWriting if it was set */
|
||||||
[_sibling _setStatus: NSStreamStatusOpen];
|
[_sibling _setStatus: NSStreamStatusOpen];
|
||||||
while ([_sibling hasSpaceAvailable]
|
|
||||||
&& [_sibling _unhandledData] == NO)
|
|
||||||
{
|
|
||||||
[_sibling _sendEvent: NSStreamEventHasSpaceAvailable];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
/* On winsock a socket is always writable unless it has had
|
||||||
|
* failure/closure or a write blocked and we have not been
|
||||||
|
* signalled again.
|
||||||
|
*/
|
||||||
|
while ([_sibling _unhandledData] == NO
|
||||||
|
&& [_sibling hasSpaceAvailable])
|
||||||
|
{
|
||||||
|
[_sibling _sendEvent: NSStreamEventHasSpaceAvailable];
|
||||||
|
}
|
||||||
|
|
||||||
if (events.lNetworkEvents & FD_READ)
|
if (events.lNetworkEvents & FD_READ)
|
||||||
{
|
{
|
||||||
[self _setStatus: NSStreamStatusOpen];
|
[self _setStatus: NSStreamStatusOpen];
|
||||||
while ([self hasBytesAvailable]
|
while ([self hasBytesAvailable]
|
||||||
&& _unhandledData == NO)
|
&& [self _unhandledData] == NO)
|
||||||
{
|
{
|
||||||
[self _sendEvent: NSStreamEventHasBytesAvailable];
|
[self _sendEvent: NSStreamEventHasBytesAvailable];
|
||||||
}
|
}
|
||||||
|
@ -871,7 +878,7 @@ else NSLog(@"EVENTS 0x%x on %p", events.lNetworkEvents, self);
|
||||||
[_sibling _sendEvent: NSStreamEventEndEncountered];
|
[_sibling _sendEvent: NSStreamEventEndEncountered];
|
||||||
}
|
}
|
||||||
while ([self hasBytesAvailable]
|
while ([self hasBytesAvailable]
|
||||||
&& _unhandledData == NO)
|
&& [self _unhandledData] == NO)
|
||||||
{
|
{
|
||||||
[self _sendEvent: NSStreamEventHasBytesAvailable];
|
[self _sendEvent: NSStreamEventHasBytesAvailable];
|
||||||
}
|
}
|
||||||
|
@ -1007,7 +1014,7 @@ else NSLog(@"EVENTS 0x%x on %p", events.lNetworkEvents, self);
|
||||||
{
|
{
|
||||||
DWORD writeLen;
|
DWORD writeLen;
|
||||||
|
|
||||||
_unhandledData = NO;
|
_events &= ~NSStreamEventHasSpaceAvailable;
|
||||||
if (_shouldAppend == YES)
|
if (_shouldAppend == YES)
|
||||||
{
|
{
|
||||||
SetFilePointer((HANDLE)_loopID, 0, 0, FILE_END);
|
SetFilePointer((HANDLE)_loopID, 0, 0, FILE_END);
|
||||||
|
@ -1122,7 +1129,7 @@ else NSLog(@"EVENTS 0x%x on %p", events.lNetworkEvents, self);
|
||||||
{
|
{
|
||||||
NSStreamStatus myStatus = [self streamStatus];
|
NSStreamStatus myStatus = [self streamStatus];
|
||||||
|
|
||||||
_unhandledData = NO;
|
_events &= ~NSStreamEventHasSpaceAvailable;
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1214,7 +1221,7 @@ else NSLog(@"EVENTS 0x%x on %p", events.lNetworkEvents, self);
|
||||||
{
|
{
|
||||||
NSStreamStatus myStatus = [self streamStatus];
|
NSStreamStatus myStatus = [self streamStatus];
|
||||||
|
|
||||||
if (_unhandledData == YES || myStatus == NSStreamStatusError)
|
if ([self _unhandledData] == YES || myStatus == NSStreamStatusError)
|
||||||
{
|
{
|
||||||
*trigger = NO;
|
*trigger = NO;
|
||||||
return NO;
|
return NO;
|
||||||
|
@ -1285,7 +1292,7 @@ else NSLog(@"EVENTS 0x%x on %p", events.lNetworkEvents, self);
|
||||||
{
|
{
|
||||||
int writeLen;
|
int writeLen;
|
||||||
|
|
||||||
_unhandledData = NO;
|
_events &= ~NSStreamEventHasSpaceAvailable;
|
||||||
writeLen = send(_sock, buffer, len, 0);
|
writeLen = send(_sock, buffer, len, 0);
|
||||||
if (writeLen == SOCKET_ERROR)
|
if (writeLen == SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
|
@ -1466,13 +1473,19 @@ else NSLog(@"EVENTS 0x%x on %p", events.lNetworkEvents, self);
|
||||||
{
|
{
|
||||||
if (events.lNetworkEvents & FD_WRITE)
|
if (events.lNetworkEvents & FD_WRITE)
|
||||||
{
|
{
|
||||||
|
/* Clear NSStreamStatusWriting if it was set */
|
||||||
[self _setStatus: NSStreamStatusOpen];
|
[self _setStatus: NSStreamStatusOpen];
|
||||||
while ([self hasSpaceAvailable]
|
|
||||||
&& _unhandledData == NO)
|
|
||||||
{
|
|
||||||
[self _sendEvent: NSStreamEventHasSpaceAvailable];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* On winsock a socket is always writable unless it has had
|
||||||
|
* failure/closure or a write blocked and we have not been
|
||||||
|
* signalled again.
|
||||||
|
*/
|
||||||
|
while ([self _unhandledData] == NO && [self hasSpaceAvailable])
|
||||||
|
{
|
||||||
|
[self _sendEvent: NSStreamEventHasSpaceAvailable];
|
||||||
|
}
|
||||||
|
|
||||||
if (events.lNetworkEvents & FD_READ)
|
if (events.lNetworkEvents & FD_READ)
|
||||||
{
|
{
|
||||||
[_sibling _setStatus: NSStreamStatusOpen];
|
[_sibling _setStatus: NSStreamStatusOpen];
|
||||||
|
@ -1504,6 +1517,14 @@ else NSLog(@"EVENTS 0x%x on %p", events.lNetworkEvents, self);
|
||||||
- (BOOL) runLoopShouldBlock: (BOOL*)trigger
|
- (BOOL) runLoopShouldBlock: (BOOL*)trigger
|
||||||
{
|
{
|
||||||
*trigger = YES;
|
*trigger = YES;
|
||||||
|
if ([self _unhandledData] == NO && [self streamStatus] == NSStreamStatusOpen)
|
||||||
|
{
|
||||||
|
/* In winsock, a writable status is only signalled if an earlier
|
||||||
|
* write failed (because it would block), so we must simulate the
|
||||||
|
* writable event by having the run loop trigger without blocking.
|
||||||
|
*/
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
@ -1949,7 +1970,7 @@ else NSLog(@"EVENTS 0x%x on %p", events.lNetworkEvents, self);
|
||||||
socklen_t len = [ins sockLen];
|
socklen_t len = [ins sockLen];
|
||||||
int acceptReturn = accept(_sock, [ins peerAddr], &len);
|
int acceptReturn = accept(_sock, [ins peerAddr], &len);
|
||||||
|
|
||||||
_unhandledData = NO;
|
_events &= ~NSStreamEventHasBytesAvailable;
|
||||||
if (acceptReturn == INVALID_SOCKET)
|
if (acceptReturn == INVALID_SOCKET)
|
||||||
{
|
{
|
||||||
errno = WSAGetLastError();// test for real error
|
errno = WSAGetLastError();// test for real error
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue