mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-31 16:50:58 +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
71148081f7
commit
85ada8322a
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/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>
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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];
|
||||||
}
|
}
|
||||||
|
|
|
@ -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];
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue