mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-30 16:30:41 +00:00
mingw stream improvements
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@23254 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
068ca34b74
commit
d0852086a5
6 changed files with 665 additions and 253 deletions
33
ChangeLog
33
ChangeLog
|
@ -1,11 +1,18 @@
|
||||||
2006-08-11 Richard Frith-Macdonald <rfm@gnu.org>
|
2006-08-11 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
* Source/NSTask.m: Fixup for path validation error on mingw32
|
* Source/NSTask.m: Fixup for path validation error on mingw32
|
||||||
|
* Headers/Foundation/NSStream.h: improve documentation.
|
||||||
|
* Source/GSStream.h:
|
||||||
|
* Source/GSStream.m:
|
||||||
|
* Source/unix/NSStream.m:
|
||||||
|
* Source/win32/NSStreamWin32.m:
|
||||||
|
Add lots of error checking, simplify a little, get local streams on
|
||||||
|
mingw to close down properly.
|
||||||
|
|
||||||
2006-08-10 Richard Frith-Macdonald <rfm@gnu.org>
|
2006-08-10 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
* Source\GSStream.m:
|
* Source/GSStream.m:
|
||||||
* Source\win32\NSStreamWin32.m:
|
* Source/win32/NSStreamWin32.m:
|
||||||
Fix error in pipe read offset. Imitial implementation of local
|
Fix error in pipe read offset. Imitial implementation of local
|
||||||
'unix domain sockets' (actually named pipe) stream.
|
'unix domain sockets' (actually named pipe) stream.
|
||||||
|
|
||||||
|
@ -16,10 +23,10 @@
|
||||||
|
|
||||||
2006-08-10 Richard Frith-Macdonald <rfm@gnu.org>
|
2006-08-10 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
* Source\GSStream.h:
|
* Source/GSStream.h:
|
||||||
* Source\GSStream.m:
|
* Source/GSStream.m:
|
||||||
* Source\unix\NSStream.m:
|
* Source/unix/NSStream.m:
|
||||||
* Source\win32\NSStreamWin32.m:
|
* Source/win32/NSStreamWin32.m:
|
||||||
Ensure all events are posted. Fixup for winsock write signalling.
|
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>
|
||||||
|
@ -930,13 +937,13 @@
|
||||||
|
|
||||||
* Source/NSUserDefaults.m: Restructure for lazy creation of defaults
|
* Source/NSUserDefaults.m: Restructure for lazy creation of defaults
|
||||||
database ... only create when we attempt to write.
|
database ... only create when we attempt to write.
|
||||||
* Source\NSSocketPort.m: Include GSPrivate.h
|
* Source/NSSocketPort.m: Include GSPrivate.h
|
||||||
* Source\NSRunLoop.m: ditto
|
* Source/NSRunLoop.m: ditto
|
||||||
* Source\unix\GSRunLoopCtxt.m: ditto
|
* Source/unix/GSRunLoopCtxt.m: ditto
|
||||||
* Source\GSPrivate.h: ditto
|
* Source/GSPrivate.h: ditto
|
||||||
* Source\win32\GSFileHandleWin32.m: ditto
|
* Source/win32/GSFileHandleWin32.m: ditto
|
||||||
* Source\win32\GSRunLoopCtxt.m: ditto
|
* Source/win32/GSRunLoopCtxt.m: ditto
|
||||||
* Headers\Foundation\NSNotificationQueue.h: Move library internal
|
* Headers/Foundation/NSNotificationQueue.h: Move library internal
|
||||||
function declarations to GSPrivate.h, thanks to Lloyd Dupont for
|
function declarations to GSPrivate.h, thanks to Lloyd Dupont for
|
||||||
spotting problem.
|
spotting problem.
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,8 @@ typedef enum {
|
||||||
outputStream: (NSOutputStream **)outputStream;
|
outputStream: (NSOutputStream **)outputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes the receiver.
|
* Closes the receiver.<br />
|
||||||
|
* Repeated calls to this method on the same stream are quietly ignored.
|
||||||
*/
|
*/
|
||||||
- (void) close;
|
- (void) close;
|
||||||
|
|
||||||
|
@ -80,7 +81,10 @@ typedef enum {
|
||||||
- (id) delegate;
|
- (id) delegate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens the receiving stream.
|
* Opens the receiving stream.<br />
|
||||||
|
* Upon completion of the open operation, an NSStreamEventOpenCompleted
|
||||||
|
* event is sent to the recevier's delegate.<br />
|
||||||
|
* Repeated calls to this method on the same stream are quietly ignored.
|
||||||
*/
|
*/
|
||||||
- (void) open;
|
- (void) open;
|
||||||
|
|
||||||
|
@ -91,12 +95,17 @@ typedef enum {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the receiver from the NSRunLoop specified by aRunLoop
|
* Removes the receiver from the NSRunLoop specified by aRunLoop
|
||||||
* running in the mode.
|
* running in the mode.<br />
|
||||||
|
* Attempts to remove the receiver from a run loop or a mode in
|
||||||
|
* which it has not been scheduled are quietly ignored.
|
||||||
*/
|
*/
|
||||||
- (void) removeFromRunLoop: (NSRunLoop *)aRunLoop forMode: (NSString *)mode;
|
- (void) removeFromRunLoop: (NSRunLoop *)aRunLoop forMode: (NSString *)mode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Schedules the receiver on aRunLoop using the specified mode.
|
* Schedules the receiver on aRunLoop using the specified mode.<br />
|
||||||
|
* You must not attempt to add a stream to more than one run loop,
|
||||||
|
* but you may call this method multiple times to add the receiver
|
||||||
|
* in different modes for the same run loop.
|
||||||
*/
|
*/
|
||||||
- (void) scheduleInRunLoop: (NSRunLoop *)aRunLoop forMode: (NSString *)mode;
|
- (void) scheduleInRunLoop: (NSRunLoop *)aRunLoop forMode: (NSString *)mode;
|
||||||
|
|
||||||
|
@ -262,14 +271,17 @@ typedef enum {
|
||||||
* that is a stream that binds to a socket and accepts incoming connections
|
* that is a stream that binds to a socket and accepts incoming connections
|
||||||
*/
|
*/
|
||||||
@interface GSServerStream : NSStream
|
@interface GSServerStream : NSStream
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Createe a ip (ipv6) server stream
|
* Createe a ip (ipv6) server stream
|
||||||
*/
|
*/
|
||||||
+ (id) serverStreamToAddr: (NSString*)addr port: (int)port;
|
+ (id) serverStreamToAddr: (NSString*)addr port: (int)port;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a local (unix domain) server stream
|
* Create a local (unix domain or named pipe) server stream
|
||||||
*/
|
*/
|
||||||
+ (id) serverStreamToAddr: (NSString*)addr;
|
+ (id) serverStreamToAddr: (NSString*)addr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the method that accepts a connection and generates two streams
|
* This is the method that accepts a connection and generates two streams
|
||||||
* as the server side inputStream and OutputStream.
|
* as the server side inputStream and OutputStream.
|
||||||
|
@ -283,8 +295,10 @@ typedef enum {
|
||||||
* the designated initializer for a ip (ipv6) server stream
|
* the designated initializer for a ip (ipv6) server stream
|
||||||
*/
|
*/
|
||||||
- (id) initToAddr: (NSString*)addr port: (int)port;
|
- (id) initToAddr: (NSString*)addr port: (int)port;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the designated initializer for a local (unix domain) server stream
|
* the designated initializer for a local (unix domain or named pipe)
|
||||||
|
* server stream
|
||||||
*/
|
*/
|
||||||
- (id) initToAddr: (NSString*)addr;
|
- (id) initToAddr: (NSString*)addr;
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
NSStream
|
NSStream
|
||||||
|-- NSInputStream
|
|-- NSInputStream
|
||||||
| `--GSInputStream
|
| `--GSInputStream
|
||||||
| |-- GSMemoryInputStream
|
| |-- GSDataInputStream
|
||||||
| |-- GSFileInputStream
|
| |-- GSFileInputStream
|
||||||
| `-- GSSocketInputStream
|
| `-- GSSocketInputStream
|
||||||
| |-- GSInetInputStream
|
| |-- GSInetInputStream
|
||||||
|
@ -36,7 +36,8 @@
|
||||||
| `-- GSInet6InputStream
|
| `-- GSInet6InputStream
|
||||||
|-- NSOutputStream
|
|-- NSOutputStream
|
||||||
| `--GSOutputStream
|
| `--GSOutputStream
|
||||||
| |-- GSMemoryOutputStream
|
| |-- GSBufferOutputStream
|
||||||
|
| |-- GSDataOutputStream
|
||||||
| |-- GSFileOutputStream
|
| |-- GSFileOutputStream
|
||||||
| `-- GSSocketOutputStream
|
| `-- GSSocketOutputStream
|
||||||
| |-- GSInetOutputStream
|
| |-- GSInetOutputStream
|
||||||
|
@ -144,7 +145,7 @@ IVARS
|
||||||
/**
|
/**
|
||||||
* The concrete subclass of NSInputStream that reads from the memory
|
* The concrete subclass of NSInputStream that reads from the memory
|
||||||
*/
|
*/
|
||||||
@interface GSMemoryInputStream : GSInputStream
|
@interface GSDataInputStream : GSInputStream
|
||||||
{
|
{
|
||||||
@private
|
@private
|
||||||
NSData *_data;
|
NSData *_data;
|
||||||
|
@ -158,14 +159,30 @@ IVARS
|
||||||
@end
|
@end
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The concrete subclass of NSOutputStream that writes to memory
|
* The concrete subclass of NSOutputStream that writes to a buffer
|
||||||
*/
|
*/
|
||||||
@interface GSMemoryOutputStream : GSOutputStream
|
@interface GSBufferOutputStream : GSOutputStream
|
||||||
|
{
|
||||||
|
@private
|
||||||
|
uint8_t *_buffer;
|
||||||
|
unsigned _capacity;
|
||||||
|
unsigned long _pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this is the bridge method for asynchronized operation. Do not call.
|
||||||
|
*/
|
||||||
|
- (void) _dispatch;
|
||||||
|
@end
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The concrete subclass of NSOutputStream that writes to a variable sise buffer
|
||||||
|
*/
|
||||||
|
@interface GSDataOutputStream : GSOutputStream
|
||||||
{
|
{
|
||||||
@private
|
@private
|
||||||
NSMutableData *_data;
|
NSMutableData *_data;
|
||||||
unsigned long _pointer;
|
unsigned long _pointer;
|
||||||
BOOL _fixedSize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include <Foundation/NSError.h>
|
#include <Foundation/NSError.h>
|
||||||
#include <Foundation/NSValue.h>
|
#include <Foundation/NSValue.h>
|
||||||
#include <Foundation/NSHost.h>
|
#include <Foundation/NSHost.h>
|
||||||
|
#include <Foundation/NSDebug.h>
|
||||||
|
|
||||||
#include "GSStream.h"
|
#include "GSStream.h"
|
||||||
|
|
||||||
|
@ -132,9 +133,14 @@ static RunLoopEventType typeForStream(NSStream *aStream)
|
||||||
|
|
||||||
- (void) close
|
- (void) close
|
||||||
{
|
{
|
||||||
NSAssert(_currentStatus != NSStreamStatusNotOpen
|
if (_currentStatus == NSStreamStatusNotOpen)
|
||||||
&& _currentStatus != NSStreamStatusClosed,
|
{
|
||||||
@"Attempt to close a stream not yet opened.");
|
NSDebugMLog(@"Attempt to close unopened stream %@", self);
|
||||||
|
}
|
||||||
|
if (_currentStatus == NSStreamStatusClosed)
|
||||||
|
{
|
||||||
|
NSDebugMLog(@"Attempt to close already closed stream %@", self);
|
||||||
|
}
|
||||||
if (_runloop)
|
if (_runloop)
|
||||||
{
|
{
|
||||||
unsigned i = [_modes count];
|
unsigned i = [_modes count];
|
||||||
|
@ -186,9 +192,10 @@ static RunLoopEventType typeForStream(NSStream *aStream)
|
||||||
|
|
||||||
- (void) open
|
- (void) open
|
||||||
{
|
{
|
||||||
NSAssert(_currentStatus == NSStreamStatusNotOpen
|
if (_currentStatus != NSStreamStatusNotOpen)
|
||||||
|| _currentStatus == NSStreamStatusOpening,
|
{
|
||||||
@"Attempt to open a stream already opened.");
|
NSDebugMLog(@"Attempt to re-open stream %@", self);
|
||||||
|
}
|
||||||
[self _setStatus: NSStreamStatusOpen];
|
[self _setStatus: NSStreamStatusOpen];
|
||||||
if (_runloop)
|
if (_runloop)
|
||||||
{
|
{
|
||||||
|
@ -364,9 +371,6 @@ static RunLoopEventType typeForStream(NSStream *aStream)
|
||||||
|
|
||||||
- (void) _sendEvent: (NSStreamEvent)event
|
- (void) _sendEvent: (NSStreamEvent)event
|
||||||
{
|
{
|
||||||
NSStreamStatus last = [self streamStatus];
|
|
||||||
NSStreamStatus current;
|
|
||||||
|
|
||||||
if (event == NSStreamEventNone)
|
if (event == NSStreamEventNone)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -454,21 +458,6 @@ static RunLoopEventType typeForStream(NSStream *aStream)
|
||||||
[NSException raise: NSInvalidArgumentException
|
[NSException raise: NSInvalidArgumentException
|
||||||
format: @"Unknown event (%d) passed to _sendEvent:", event];
|
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)
|
|
||||||
{
|
|
||||||
[self _sendEvent: NSStreamEventErrorOccurred];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) _setLoopID: (void *)ref
|
- (void) _setLoopID: (void *)ref
|
||||||
|
@ -493,18 +482,35 @@ static RunLoopEventType typeForStream(NSStream *aStream)
|
||||||
|
|
||||||
- (BOOL) runLoopShouldBlock: (BOOL*)trigger
|
- (BOOL) runLoopShouldBlock: (BOOL*)trigger
|
||||||
{
|
{
|
||||||
if ([self _unhandledData] == YES
|
if (_events
|
||||||
|| _currentStatus == NSStreamStatusError
|
& (NSStreamEventHasBytesAvailable | NSStreamEventHasSpaceAvailable))
|
||||||
|| _currentStatus == NSStreamStatusAtEnd)
|
|
||||||
{
|
{
|
||||||
/* If we have an unhandled data event, we should not watch for more
|
/* If we have an unhandled data event, we should not watch for more
|
||||||
* or trigger until the appropriate rad or write has been done.
|
* or trigger until the appropriate read or write has been done.
|
||||||
* If an error has occurred, we should not watch for any events at all.
|
|
||||||
*/
|
*/
|
||||||
*trigger = NO;
|
*trigger = NO;
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
else if (_loopID == (void*)self)
|
if (_currentStatus == NSStreamStatusError &&
|
||||||
|
(_events & NSStreamEventErrorOccurred) == NSStreamEventErrorOccurred)
|
||||||
|
{
|
||||||
|
/* If an error has occurred (and been handled),
|
||||||
|
* we should not watch for any events at all.
|
||||||
|
*/
|
||||||
|
*trigger = NO;
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
if (_currentStatus == NSStreamStatusAtEnd &&
|
||||||
|
(_events & NSStreamEventEndEncountered) == NSStreamEventEndEncountered)
|
||||||
|
{
|
||||||
|
/* If an error has occurred (and been handled),
|
||||||
|
* we should not watch for any events at all.
|
||||||
|
*/
|
||||||
|
*trigger = NO;
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_loopID == (void*)self)
|
||||||
{
|
{
|
||||||
/* If _loopID is the receiver, the stream is not receiving external
|
/* 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
|
* input, so it must trigger an event when the loop runs and must not
|
||||||
|
@ -522,6 +528,7 @@ static RunLoopEventType typeForStream(NSStream *aStream)
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation GSInputStream
|
@implementation GSInputStream
|
||||||
|
|
||||||
+ (void) initialize
|
+ (void) initialize
|
||||||
{
|
{
|
||||||
if (self == [GSInputStream class])
|
if (self == [GSInputStream class])
|
||||||
|
@ -529,9 +536,31 @@ static RunLoopEventType typeForStream(NSStream *aStream)
|
||||||
GSObjCAddClassBehavior(self, [GSStream class]);
|
GSObjCAddClassBehavior(self, [GSStream class]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL) hasBytesAvailable
|
||||||
|
{
|
||||||
|
if (_currentStatus == NSStreamStatusOpen)
|
||||||
|
{
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
if (_currentStatus == NSStreamStatusAtEnd)
|
||||||
|
{
|
||||||
|
if ((_events & NSStreamEventEndEncountered) == 0)
|
||||||
|
{
|
||||||
|
/* We have not sent the appropriate event yet, so the
|
||||||
|
* client must not have issued a read:maxLength:
|
||||||
|
* (which is the point at which we should send).
|
||||||
|
*/
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation GSOutputStream
|
@implementation GSOutputStream
|
||||||
|
|
||||||
+ (void) initialize
|
+ (void) initialize
|
||||||
{
|
{
|
||||||
if (self == [GSOutputStream class])
|
if (self == [GSOutputStream class])
|
||||||
|
@ -539,6 +568,27 @@ static RunLoopEventType typeForStream(NSStream *aStream)
|
||||||
GSObjCAddClassBehavior(self, [GSStream class]);
|
GSObjCAddClassBehavior(self, [GSStream class]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL) hasSpaceAvailable
|
||||||
|
{
|
||||||
|
if (_currentStatus == NSStreamStatusOpen)
|
||||||
|
{
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
if (_currentStatus == NSStreamStatusAtEnd)
|
||||||
|
{
|
||||||
|
if ((_events & NSStreamEventEndEncountered) == 0)
|
||||||
|
{
|
||||||
|
/* We have not sent the appropriate event yet, so the
|
||||||
|
* client must not have issued a write:maxLength:
|
||||||
|
* (which is the point at which we should send).
|
||||||
|
*/
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@implementation GSAbstractServerStream
|
@implementation GSAbstractServerStream
|
||||||
+ (void) initialize
|
+ (void) initialize
|
||||||
|
@ -551,7 +601,7 @@ static RunLoopEventType typeForStream(NSStream *aStream)
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
@implementation GSMemoryInputStream
|
@implementation GSDataInputStream
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the designated initializer
|
* the designated initializer
|
||||||
|
@ -576,10 +626,28 @@ static RunLoopEventType typeForStream(NSStream *aStream)
|
||||||
|
|
||||||
- (int) read: (uint8_t *)buffer maxLength: (unsigned int)len
|
- (int) read: (uint8_t *)buffer maxLength: (unsigned int)len
|
||||||
{
|
{
|
||||||
unsigned long dataSize = [_data length];
|
unsigned long dataSize;
|
||||||
unsigned long copySize;
|
unsigned long copySize;
|
||||||
|
|
||||||
|
if (buffer == 0)
|
||||||
|
{
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"null pointer for buffer"];
|
||||||
|
}
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"zero byte read write requested"];
|
||||||
|
}
|
||||||
|
|
||||||
_events &= ~NSStreamEventHasSpaceAvailable;
|
_events &= ~NSStreamEventHasSpaceAvailable;
|
||||||
|
|
||||||
|
if ([self streamStatus] == NSStreamStatusClosed)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dataSize = [_data length];
|
||||||
NSAssert(dataSize >= _pointer, @"Buffer overflow!");
|
NSAssert(dataSize >= _pointer, @"Buffer overflow!");
|
||||||
if (len + _pointer > dataSize)
|
if (len + _pointer > dataSize)
|
||||||
{
|
{
|
||||||
|
@ -597,6 +665,7 @@ static RunLoopEventType typeForStream(NSStream *aStream)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
[self _setStatus: NSStreamStatusAtEnd];
|
[self _setStatus: NSStreamStatusAtEnd];
|
||||||
|
[self _sendEvent: NSStreamEventEndEncountered];
|
||||||
}
|
}
|
||||||
return copySize;
|
return copySize;
|
||||||
}
|
}
|
||||||
|
@ -639,71 +708,132 @@ static RunLoopEventType typeForStream(NSStream *aStream)
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
@implementation GSMemoryOutputStream
|
@implementation GSBufferOutputStream
|
||||||
|
|
||||||
- (id) initToBuffer: (uint8_t *)buffer capacity: (unsigned int)capacity
|
- (id) initToBuffer: (uint8_t *)buffer capacity: (unsigned int)capacity
|
||||||
{
|
{
|
||||||
if ((self = [super init]) != nil)
|
if ((self = [super init]) != nil)
|
||||||
{
|
{
|
||||||
if (!buffer)
|
_buffer = buffer;
|
||||||
{
|
_capacity = capacity;
|
||||||
_data = [NSMutableData new];
|
|
||||||
_fixedSize = NO;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_data = [[NSMutableData alloc] initWithBytesNoCopy: buffer
|
|
||||||
length: capacity freeWhenDone: NO];
|
|
||||||
_fixedSize = YES;
|
|
||||||
}
|
|
||||||
_pointer = 0;
|
_pointer = 0;
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) dealloc
|
|
||||||
{
|
|
||||||
RELEASE(_data);
|
|
||||||
[super dealloc];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (int) write: (const uint8_t *)buffer maxLength: (unsigned int)len
|
- (int) write: (const uint8_t *)buffer maxLength: (unsigned int)len
|
||||||
{
|
{
|
||||||
_events &= ~NSStreamEventHasBytesAvailable;
|
if (buffer == 0)
|
||||||
if (_fixedSize)
|
|
||||||
{
|
{
|
||||||
unsigned long dataLen = [_data length];
|
[NSException raise: NSInvalidArgumentException
|
||||||
uint8_t *origin = (uint8_t *)[_data mutableBytes];
|
format: @"null pointer for buffer"];
|
||||||
|
}
|
||||||
if (_pointer+len>dataLen)
|
if (len == 0)
|
||||||
len = dataLen - _pointer;
|
{
|
||||||
memcpy(origin+_pointer, buffer, len);
|
[NSException raise: NSInvalidArgumentException
|
||||||
_pointer = _pointer + len;
|
format: @"zero byte length write requested"];
|
||||||
}
|
}
|
||||||
else
|
|
||||||
[_data appendBytes: buffer length: len];
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL) hasSpaceAvailable
|
_events &= ~NSStreamEventHasBytesAvailable;
|
||||||
{
|
|
||||||
if (_fixedSize)
|
if ([self streamStatus] == NSStreamStatusClosed)
|
||||||
return [_data length]>_pointer;
|
{
|
||||||
else
|
return 0;
|
||||||
return YES;
|
}
|
||||||
|
|
||||||
|
if ((_pointer + len) > _capacity)
|
||||||
|
{
|
||||||
|
len = _capacity - _pointer;
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
[self _setStatus: NSStreamStatusAtEnd];
|
||||||
|
[self _sendEvent: NSStreamEventEndEncountered];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memcpy((_buffer + _pointer), buffer, len);
|
||||||
|
_pointer += len;
|
||||||
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id) propertyForKey: (NSString *)key
|
- (id) propertyForKey: (NSString *)key
|
||||||
{
|
{
|
||||||
if ([key isEqualToString: NSStreamFileCurrentOffsetKey])
|
if ([key isEqualToString: NSStreamFileCurrentOffsetKey])
|
||||||
{
|
{
|
||||||
if (_fixedSize)
|
return [NSNumber numberWithLong: _pointer];
|
||||||
return [NSNumber numberWithLong: _pointer];
|
}
|
||||||
else
|
return [super propertyForKey: key];
|
||||||
return [NSNumber numberWithLong:[_data length]];
|
}
|
||||||
|
|
||||||
|
- (void) _dispatch
|
||||||
|
{
|
||||||
|
BOOL av = [self hasSpaceAvailable];
|
||||||
|
NSStreamEvent myEvent = av ? NSStreamEventHasSpaceAvailable :
|
||||||
|
NSStreamEventEndEncountered;
|
||||||
|
|
||||||
|
[self _sendEvent: myEvent];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation GSDataOutputStream
|
||||||
|
|
||||||
|
- (id) init
|
||||||
|
{
|
||||||
|
if ((self = [super init]) != nil)
|
||||||
|
{
|
||||||
|
_data = [NSMutableData new];
|
||||||
|
_pointer = 0;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) dealloc
|
||||||
|
{
|
||||||
|
RELEASE(_data);
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (int) write: (const uint8_t *)buffer maxLength: (unsigned int)len
|
||||||
|
{
|
||||||
|
if (buffer == 0)
|
||||||
|
{
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"null pointer for buffer"];
|
||||||
|
}
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"zero byte length write requested"];
|
||||||
|
}
|
||||||
|
|
||||||
|
_events &= ~NSStreamEventHasBytesAvailable;
|
||||||
|
|
||||||
|
if ([self streamStatus] == NSStreamStatusClosed)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[_data appendBytes: buffer length: len];
|
||||||
|
_pointer += len;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) hasSpaceAvailable
|
||||||
|
{
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) propertyForKey: (NSString *)key
|
||||||
|
{
|
||||||
|
if ([key isEqualToString: NSStreamFileCurrentOffsetKey])
|
||||||
|
{
|
||||||
|
return [NSNumber numberWithLong: _pointer];
|
||||||
|
}
|
||||||
|
else if ([key isEqualToString: NSStreamDataWrittenToMemoryStreamKey])
|
||||||
|
{
|
||||||
|
return _data;
|
||||||
}
|
}
|
||||||
else if ([key isEqualToString: NSStreamDataWrittenToMemoryStreamKey])
|
|
||||||
return _data;
|
|
||||||
return [super propertyForKey: key];
|
return [super propertyForKey: key];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -297,7 +297,24 @@ static void setNonblocking(int fd)
|
||||||
{
|
{
|
||||||
int readLen;
|
int readLen;
|
||||||
|
|
||||||
|
if (buffer == 0)
|
||||||
|
{
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"null pointer for buffer"];
|
||||||
|
}
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"zero byte read write requested"];
|
||||||
|
}
|
||||||
|
|
||||||
_events &= ~NSStreamEventHasBytesAvailable;
|
_events &= ~NSStreamEventHasBytesAvailable;
|
||||||
|
|
||||||
|
if ([self streamStatus] == NSStreamStatusClosed)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
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 +492,24 @@ static void setNonblocking(int fd)
|
||||||
{
|
{
|
||||||
int readLen;
|
int readLen;
|
||||||
|
|
||||||
|
if (buffer == 0)
|
||||||
|
{
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"null pointer for buffer"];
|
||||||
|
}
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"zero byte read write requested"];
|
||||||
|
}
|
||||||
|
|
||||||
_events &= ~NSStreamEventHasBytesAvailable;
|
_events &= ~NSStreamEventHasBytesAvailable;
|
||||||
|
|
||||||
|
if ([self streamStatus] == NSStreamStatusClosed)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
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 +710,24 @@ static void setNonblocking(int fd)
|
||||||
{
|
{
|
||||||
int writeLen;
|
int writeLen;
|
||||||
|
|
||||||
|
if (buffer == 0)
|
||||||
|
{
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"null pointer for buffer"];
|
||||||
|
}
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"zero byte length write requested"];
|
||||||
|
}
|
||||||
|
|
||||||
_events &= ~NSStreamEventHasSpaceAvailable;
|
_events &= ~NSStreamEventHasSpaceAvailable;
|
||||||
|
|
||||||
|
if ([self streamStatus] == NSStreamStatusClosed)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
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 +841,24 @@ static void setNonblocking(int fd)
|
||||||
{
|
{
|
||||||
int writeLen;
|
int writeLen;
|
||||||
|
|
||||||
|
if (buffer == 0)
|
||||||
|
{
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"null pointer for buffer"];
|
||||||
|
}
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"zero byte length write requested"];
|
||||||
|
}
|
||||||
|
|
||||||
_events &= ~NSStreamEventHasSpaceAvailable;
|
_events &= ~NSStreamEventHasSpaceAvailable;
|
||||||
|
|
||||||
|
if ([self streamStatus] == NSStreamStatusClosed)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
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];
|
||||||
|
@ -1186,7 +1254,7 @@ static void setNonblocking(int fd)
|
||||||
|
|
||||||
+ (id) inputStreamWithData: (NSData *)data
|
+ (id) inputStreamWithData: (NSData *)data
|
||||||
{
|
{
|
||||||
return AUTORELEASE([[GSMemoryInputStream alloc] initWithData: data]);
|
return AUTORELEASE([[GSDataInputStream alloc] initWithData: data]);
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (id) inputStreamWithFileAtPath: (NSString *)path
|
+ (id) inputStreamWithFileAtPath: (NSString *)path
|
||||||
|
@ -1194,24 +1262,6 @@ static void setNonblocking(int fd)
|
||||||
return AUTORELEASE([[GSFileInputStream alloc] initWithFileAtPath: path]);
|
return AUTORELEASE([[GSFileInputStream alloc] initWithFileAtPath: path]);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id) initWithData: (NSData *)data
|
|
||||||
{
|
|
||||||
RELEASE(self);
|
|
||||||
return [[GSMemoryInputStream alloc] initWithData: data];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id) initWithFileAtPath: (NSString *)path
|
|
||||||
{
|
|
||||||
RELEASE(self);
|
|
||||||
return [[GSFileInputStream alloc] initWithFileAtPath: path];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (int) read: (uint8_t *)buffer maxLength: (unsigned int)len
|
|
||||||
{
|
|
||||||
[self subclassResponsibility: _cmd];
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL) getBuffer: (uint8_t **)buffer length: (unsigned int *)len
|
- (BOOL) getBuffer: (uint8_t **)buffer length: (unsigned int *)len
|
||||||
{
|
{
|
||||||
[self subclassResponsibility: _cmd];
|
[self subclassResponsibility: _cmd];
|
||||||
|
@ -1224,19 +1274,31 @@ static void setNonblocking(int fd)
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (id) initWithData: (NSData *)data
|
||||||
|
{
|
||||||
|
RELEASE(self);
|
||||||
|
return [[GSDataInputStream alloc] initWithData: data];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) initWithFileAtPath: (NSString *)path
|
||||||
|
{
|
||||||
|
RELEASE(self);
|
||||||
|
return [[GSFileInputStream alloc] initWithFileAtPath: path];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (int) read: (uint8_t *)buffer maxLength: (unsigned int)len
|
||||||
|
{
|
||||||
|
[self subclassResponsibility: _cmd];
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation NSOutputStream
|
@implementation NSOutputStream
|
||||||
|
|
||||||
+ (id) outputStreamToMemory
|
|
||||||
{
|
|
||||||
return AUTORELEASE([[GSMemoryOutputStream alloc]
|
|
||||||
initToBuffer: NULL capacity: 0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (id) outputStreamToBuffer: (uint8_t *)buffer capacity: (unsigned int)capacity
|
+ (id) outputStreamToBuffer: (uint8_t *)buffer capacity: (unsigned int)capacity
|
||||||
{
|
{
|
||||||
return AUTORELEASE([[GSMemoryOutputStream alloc]
|
return AUTORELEASE([[GSBufferOutputStream alloc]
|
||||||
initToBuffer: buffer capacity: capacity]);
|
initToBuffer: buffer capacity: capacity]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1246,16 +1308,21 @@ static void setNonblocking(int fd)
|
||||||
initToFileAtPath: path append: shouldAppend]);
|
initToFileAtPath: path append: shouldAppend]);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id) initToMemory
|
+ (id) outputStreamToMemory
|
||||||
{
|
{
|
||||||
RELEASE(self);
|
return AUTORELEASE([[GSDataOutputStream alloc] init]);
|
||||||
return [[GSMemoryOutputStream alloc] initToBuffer: NULL capacity: 0];
|
}
|
||||||
|
|
||||||
|
- (BOOL) hasSpaceAvailable
|
||||||
|
{
|
||||||
|
[self subclassResponsibility: _cmd];
|
||||||
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id) initToBuffer: (uint8_t *)buffer capacity: (unsigned int)capacity
|
- (id) initToBuffer: (uint8_t *)buffer capacity: (unsigned int)capacity
|
||||||
{
|
{
|
||||||
RELEASE(self);
|
RELEASE(self);
|
||||||
return [[GSMemoryOutputStream alloc] initToBuffer: buffer capacity: capacity];
|
return [[GSBufferOutputStream alloc] initToBuffer: buffer capacity: capacity];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id) initToFileAtPath: (NSString *)path append: (BOOL)shouldAppend
|
- (id) initToFileAtPath: (NSString *)path append: (BOOL)shouldAppend
|
||||||
|
@ -1265,18 +1332,18 @@ static void setNonblocking(int fd)
|
||||||
append: shouldAppend];
|
append: shouldAppend];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (id) initToMemory
|
||||||
|
{
|
||||||
|
RELEASE(self);
|
||||||
|
return [[GSDataOutputStream alloc] init];
|
||||||
|
}
|
||||||
|
|
||||||
- (int) write: (const uint8_t *)buffer maxLength: (unsigned int)len
|
- (int) write: (const uint8_t *)buffer maxLength: (unsigned int)len
|
||||||
{
|
{
|
||||||
[self subclassResponsibility: _cmd];
|
[self subclassResponsibility: _cmd];
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) hasSpaceAvailable
|
|
||||||
{
|
|
||||||
[self subclassResponsibility: _cmd];
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation GSServerStream
|
@implementation GSServerStream
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include <Foundation/NSValue.h>
|
#include <Foundation/NSValue.h>
|
||||||
#include <Foundation/NSHost.h>
|
#include <Foundation/NSHost.h>
|
||||||
#include <Foundation/NSProcessInfo.h>
|
#include <Foundation/NSProcessInfo.h>
|
||||||
|
#include <Foundation/NSDebug.h>
|
||||||
|
|
||||||
#include "../GSStream.h"
|
#include "../GSStream.h"
|
||||||
|
|
||||||
|
@ -73,6 +74,7 @@ typedef int socklen_t;
|
||||||
unsigned want; // Amount of data we want to read.
|
unsigned want; // Amount of data we want to read.
|
||||||
DWORD size; // Number of bytes returned by read.
|
DWORD size; // Number of bytes returned by read.
|
||||||
GSPipeOutputStream *_sibling;
|
GSPipeOutputStream *_sibling;
|
||||||
|
BOOL hadEOF;
|
||||||
}
|
}
|
||||||
- (NSStreamStatus) _check;
|
- (NSStreamStatus) _check;
|
||||||
- (void) _queue;
|
- (void) _queue;
|
||||||
|
@ -154,6 +156,8 @@ typedef int socklen_t;
|
||||||
unsigned want;
|
unsigned want;
|
||||||
DWORD size;
|
DWORD size;
|
||||||
GSPipeInputStream *_sibling;
|
GSPipeInputStream *_sibling;
|
||||||
|
BOOL closing;
|
||||||
|
BOOL writtenEOF;
|
||||||
}
|
}
|
||||||
- (NSStreamStatus) _check;
|
- (NSStreamStatus) _check;
|
||||||
- (void) _queue;
|
- (void) _queue;
|
||||||
|
@ -298,13 +302,6 @@ static void setNonblocking(SOCKET fd)
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) hasBytesAvailable
|
|
||||||
{
|
|
||||||
if ([self _isOpened] && [self streamStatus] != NSStreamStatusAtEnd)
|
|
||||||
return YES;
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id) initWithFileAtPath: (NSString *)path
|
- (id) initWithFileAtPath: (NSString *)path
|
||||||
{
|
{
|
||||||
if ((self = [super init]) != nil)
|
if ((self = [super init]) != nil)
|
||||||
|
@ -351,7 +348,24 @@ static void setNonblocking(SOCKET fd)
|
||||||
{
|
{
|
||||||
DWORD readLen;
|
DWORD readLen;
|
||||||
|
|
||||||
|
if (buffer == 0)
|
||||||
|
{
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"null pointer for buffer"];
|
||||||
|
}
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"zero byte length read requested"];
|
||||||
|
}
|
||||||
|
|
||||||
_events &= ~NSStreamEventHasBytesAvailable;
|
_events &= ~NSStreamEventHasBytesAvailable;
|
||||||
|
|
||||||
|
if ([self streamStatus] == NSStreamStatusClosed)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (ReadFile((HANDLE)_loopID, buffer, len, &readLen, NULL) == 0)
|
if (ReadFile((HANDLE)_loopID, buffer, len, &readLen, NULL) == 0)
|
||||||
{
|
{
|
||||||
[self _recordError];
|
[self _recordError];
|
||||||
|
@ -360,6 +374,7 @@ static void setNonblocking(SOCKET fd)
|
||||||
else if (readLen == 0)
|
else if (readLen == 0)
|
||||||
{
|
{
|
||||||
[self _setStatus: NSStreamStatusAtEnd];
|
[self _setStatus: NSStreamStatusAtEnd];
|
||||||
|
[self _sendEvent: NSStreamEventEndEncountered];
|
||||||
}
|
}
|
||||||
return (int)readLen;
|
return (int)readLen;
|
||||||
}
|
}
|
||||||
|
@ -383,26 +398,43 @@ static void setNonblocking(SOCKET fd)
|
||||||
|
|
||||||
- (void) close
|
- (void) close
|
||||||
{
|
{
|
||||||
if (want > 0 && handle != INVALID_HANDLE_VALUE)
|
length = offset = 0;
|
||||||
{
|
|
||||||
want = 0;
|
|
||||||
CancelIo(handle);
|
|
||||||
}
|
|
||||||
if (_loopID != INVALID_HANDLE_VALUE)
|
if (_loopID != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
CloseHandle((HANDLE)_loopID);
|
CloseHandle((HANDLE)_loopID);
|
||||||
}
|
}
|
||||||
if (handle != INVALID_HANDLE_VALUE && [_sibling _isOpened] == NO)
|
if (handle != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
if (CloseHandle(handle) == 0)
|
/* If we have an outstanding read in progess, we must cancel it
|
||||||
|
* before closing the pipe.
|
||||||
|
*/
|
||||||
|
if (want > 0)
|
||||||
{
|
{
|
||||||
[self _recordError];
|
want = 0;
|
||||||
|
CancelIo(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We can only close the pipe if there is no sibling using it.
|
||||||
|
*/
|
||||||
|
if ([_sibling _isOpened] == NO)
|
||||||
|
{
|
||||||
|
if (DisconnectNamedPipe(handle) == 0)
|
||||||
|
{
|
||||||
|
if ((errno = GetLastError()) != ERROR_PIPE_NOT_CONNECTED)
|
||||||
|
{
|
||||||
|
[self _recordError];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (CloseHandle(handle) == 0)
|
||||||
|
{
|
||||||
|
[self _recordError];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handle = INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
length = offset = 0;
|
|
||||||
[super close];
|
[super close];
|
||||||
handle = INVALID_HANDLE_VALUE;
|
|
||||||
_loopID = (void*)INVALID_HANDLE_VALUE;
|
_loopID = (void*)INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) dealloc
|
- (void) dealloc
|
||||||
|
@ -426,13 +458,6 @@ static void setNonblocking(SOCKET fd)
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) hasBytesAvailable
|
|
||||||
{
|
|
||||||
if ([self streamStatus] == NSStreamStatusOpen)
|
|
||||||
return YES;
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id) init
|
- (id) init
|
||||||
{
|
{
|
||||||
if ((self = [super init]) != nil)
|
if ((self = [super init]) != nil)
|
||||||
|
@ -459,8 +484,8 @@ static void setNonblocking(SOCKET fd)
|
||||||
|
|
||||||
if (GetOverlappedResult(handle, &ov, &size, TRUE) == 0)
|
if (GetOverlappedResult(handle, &ov, &size, TRUE) == 0)
|
||||||
{
|
{
|
||||||
errno = GetLastError();
|
if ((errno = GetLastError()) == ERROR_HANDLE_EOF
|
||||||
if (errno == ERROR_HANDLE_EOF
|
|| errno == ERROR_PIPE_NOT_CONNECTED
|
||||||
|| errno == ERROR_BROKEN_PIPE)
|
|| errno == ERROR_BROKEN_PIPE)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -469,6 +494,7 @@ static void setNonblocking(SOCKET fd)
|
||||||
*/
|
*/
|
||||||
offset = length = want = 0;
|
offset = length = want = 0;
|
||||||
[self _setStatus: NSStreamStatusOpen];
|
[self _setStatus: NSStreamStatusOpen];
|
||||||
|
hadEOF = YES;
|
||||||
}
|
}
|
||||||
else if (errno != ERROR_IO_PENDING)
|
else if (errno != ERROR_IO_PENDING)
|
||||||
{
|
{
|
||||||
|
@ -479,6 +505,12 @@ static void setNonblocking(SOCKET fd)
|
||||||
[self _recordError];
|
[self _recordError];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (size == 0)
|
||||||
|
{
|
||||||
|
length = want = 0;
|
||||||
|
[self _setStatus: NSStreamStatusOpen];
|
||||||
|
hadEOF = YES;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -492,7 +524,7 @@ static void setNonblocking(SOCKET fd)
|
||||||
|
|
||||||
- (void) _queue
|
- (void) _queue
|
||||||
{
|
{
|
||||||
if ([self streamStatus] == NSStreamStatusOpen)
|
if (hadEOF == NO && [self streamStatus] == NSStreamStatusOpen)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
@ -508,14 +540,14 @@ static void setNonblocking(SOCKET fd)
|
||||||
length = size;
|
length = size;
|
||||||
if (length == 0)
|
if (length == 0)
|
||||||
{
|
{
|
||||||
[self _setStatus: NSStreamStatusAtEnd];
|
hadEOF = YES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((errno = GetLastError()) == ERROR_HANDLE_EOF
|
else if ((errno = GetLastError()) == ERROR_HANDLE_EOF
|
||||||
|
|| errno == ERROR_PIPE_NOT_CONNECTED
|
||||||
|| errno == ERROR_BROKEN_PIPE)
|
|| errno == ERROR_BROKEN_PIPE)
|
||||||
{
|
{
|
||||||
offset = length = 0;
|
hadEOF = YES;
|
||||||
[self _setStatus: NSStreamStatusOpen]; // Read of zero length
|
|
||||||
}
|
}
|
||||||
else if (errno != ERROR_IO_PENDING)
|
else if (errno != ERROR_IO_PENDING)
|
||||||
{
|
{
|
||||||
|
@ -530,24 +562,38 @@ static void setNonblocking(SOCKET fd)
|
||||||
|
|
||||||
- (int) read: (uint8_t *)buffer maxLength: (unsigned int)len
|
- (int) read: (uint8_t *)buffer maxLength: (unsigned int)len
|
||||||
{
|
{
|
||||||
NSStreamStatus myStatus = [self streamStatus];
|
NSStreamStatus myStatus;
|
||||||
|
|
||||||
|
if (buffer == 0)
|
||||||
|
{
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"null pointer for buffer"];
|
||||||
|
}
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"zero byte length read requested"];
|
||||||
|
}
|
||||||
|
|
||||||
_events &= ~NSStreamEventHasBytesAvailable;
|
_events &= ~NSStreamEventHasBytesAvailable;
|
||||||
|
|
||||||
|
myStatus = [self streamStatus];
|
||||||
if (myStatus == NSStreamStatusReading)
|
if (myStatus == NSStreamStatusReading)
|
||||||
{
|
{
|
||||||
myStatus = [self _check];
|
myStatus = [self _check];
|
||||||
}
|
}
|
||||||
if (myStatus == NSStreamStatusAtEnd)
|
if (myStatus == NSStreamStatusClosed)
|
||||||
{
|
{
|
||||||
return 0; // At EOF
|
return 0;
|
||||||
}
|
|
||||||
if (len <= 0
|
|
||||||
|| (myStatus != NSStreamStatusReading && myStatus != NSStreamStatusOpen))
|
|
||||||
{
|
|
||||||
return -1; // Bad length or status
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset == length)
|
if (offset == length)
|
||||||
{
|
{
|
||||||
|
if (myStatus == NSStreamStatusError)
|
||||||
|
{
|
||||||
|
[self _sendEvent: NSStreamEventErrorOccurred];
|
||||||
|
return -1; // Waiting for read.
|
||||||
|
}
|
||||||
if (myStatus == NSStreamStatusOpen)
|
if (myStatus == NSStreamStatusOpen)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -555,10 +601,11 @@ static void setNonblocking(SOCKET fd)
|
||||||
* so we must be at EOF.
|
* so we must be at EOF.
|
||||||
*/
|
*/
|
||||||
[self _setStatus: NSStreamStatusAtEnd];
|
[self _setStatus: NSStreamStatusAtEnd];
|
||||||
return 0;
|
[self _sendEvent: NSStreamEventEndEncountered];
|
||||||
}
|
}
|
||||||
return -1; // Waiting for read.
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We already have data buffered ... return some or all of it.
|
* We already have data buffered ... return some or all of it.
|
||||||
*/
|
*/
|
||||||
|
@ -775,7 +822,24 @@ static void setNonblocking(SOCKET fd)
|
||||||
{
|
{
|
||||||
int readLen;
|
int readLen;
|
||||||
|
|
||||||
|
if (buffer == 0)
|
||||||
|
{
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"null pointer for buffer"];
|
||||||
|
}
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"zero byte length read requested"];
|
||||||
|
}
|
||||||
|
|
||||||
_events &= ~NSStreamEventHasBytesAvailable;
|
_events &= ~NSStreamEventHasBytesAvailable;
|
||||||
|
|
||||||
|
if ([self streamStatus] == NSStreamStatusClosed)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
readLen = recv(_sock, buffer, len, 0);
|
readLen = recv(_sock, buffer, len, 0);
|
||||||
if (readLen == SOCKET_ERROR)
|
if (readLen == SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
|
@ -806,13 +870,6 @@ static void setNonblocking(SOCKET fd)
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) hasBytesAvailable
|
|
||||||
{
|
|
||||||
if ([self streamStatus] == NSStreamStatusOpen)
|
|
||||||
return YES;
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) _dispatch
|
- (void) _dispatch
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -995,13 +1052,6 @@ static void setNonblocking(SOCKET fd)
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) hasSpaceAvailable
|
|
||||||
{
|
|
||||||
if ([self streamStatus] == NSStreamStatusOpen)
|
|
||||||
return YES;
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id) initToFileAtPath: (NSString *)path append: (BOOL)shouldAppend
|
- (id) initToFileAtPath: (NSString *)path append: (BOOL)shouldAppend
|
||||||
{
|
{
|
||||||
if ((self = [super init]) != nil)
|
if ((self = [super init]) != nil)
|
||||||
|
@ -1056,7 +1106,24 @@ static void setNonblocking(SOCKET fd)
|
||||||
{
|
{
|
||||||
DWORD writeLen;
|
DWORD writeLen;
|
||||||
|
|
||||||
|
if (buffer == 0)
|
||||||
|
{
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"null pointer for buffer"];
|
||||||
|
}
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"zero byte length write requested"];
|
||||||
|
}
|
||||||
|
|
||||||
_events &= ~NSStreamEventHasSpaceAvailable;
|
_events &= ~NSStreamEventHasSpaceAvailable;
|
||||||
|
|
||||||
|
if ([self streamStatus] == NSStreamStatusClosed)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (_shouldAppend == YES)
|
if (_shouldAppend == YES)
|
||||||
{
|
{
|
||||||
SetFilePointer((HANDLE)_loopID, 0, 0, FILE_END);
|
SetFilePointer((HANDLE)_loopID, 0, 0, FILE_END);
|
||||||
|
@ -1084,21 +1151,67 @@ static void setNonblocking(SOCKET fd)
|
||||||
|
|
||||||
- (void) close
|
- (void) close
|
||||||
{
|
{
|
||||||
|
/* If we have a write in progress, we must wait for it to complete,
|
||||||
|
* so we just set a flag to close as soon as the write finishes.
|
||||||
|
*/
|
||||||
|
if ([self streamStatus] == NSStreamStatusWriting)
|
||||||
|
{
|
||||||
|
closing = YES;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Where we have a sibling, we can't close the pipe handle, so the
|
||||||
|
* only way to tell the remote end we have finished is to write a
|
||||||
|
* zero length packet to it.
|
||||||
|
*/
|
||||||
|
if ([_sibling _isOpened] == YES && writtenEOF == NO)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
writtenEOF = YES;
|
||||||
|
ov.Offset = 0;
|
||||||
|
ov.OffsetHigh = 0;
|
||||||
|
ov.hEvent = (HANDLE)_loopID;
|
||||||
|
size = 0;
|
||||||
|
rc = WriteFile(handle, "", 0, &size, &ov);
|
||||||
|
if (rc == 0)
|
||||||
|
{
|
||||||
|
if ((errno = GetLastError()) == ERROR_IO_PENDING)
|
||||||
|
{
|
||||||
|
[self _setStatus: NSStreamStatusWriting];
|
||||||
|
return; // Wait for write to complete
|
||||||
|
}
|
||||||
|
[self _recordError]; // Failed to write EOF
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = want = 0;
|
||||||
if (_loopID != INVALID_HANDLE_VALUE)
|
if (_loopID != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
CloseHandle((HANDLE)_loopID);
|
CloseHandle((HANDLE)_loopID);
|
||||||
}
|
}
|
||||||
if (handle != INVALID_HANDLE_VALUE && [_sibling _isOpened] == NO)
|
if (handle != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
if (CloseHandle(handle) == 0)
|
if ([_sibling _isOpened] == NO)
|
||||||
{
|
{
|
||||||
[self _recordError];
|
if (DisconnectNamedPipe(handle) == 0)
|
||||||
|
{
|
||||||
|
if ((errno = GetLastError()) != ERROR_PIPE_NOT_CONNECTED)
|
||||||
|
{
|
||||||
|
[self _recordError];
|
||||||
|
}
|
||||||
|
[self _recordError];
|
||||||
|
}
|
||||||
|
if (CloseHandle(handle) == 0)
|
||||||
|
{
|
||||||
|
[self _recordError];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
handle = INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
offset = want = 0;
|
|
||||||
[super close];
|
[super close];
|
||||||
_loopID = (void*)INVALID_HANDLE_VALUE;
|
_loopID = (void*)INVALID_HANDLE_VALUE;
|
||||||
handle = INVALID_HANDLE_VALUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) dealloc
|
- (void) dealloc
|
||||||
|
@ -1112,13 +1225,6 @@ static void setNonblocking(SOCKET fd)
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) hasSpaceAvailable
|
|
||||||
{
|
|
||||||
if ([self streamStatus] == NSStreamStatusOpen)
|
|
||||||
return YES;
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id) init
|
- (id) init
|
||||||
{
|
{
|
||||||
if ((self = [super init]) != nil)
|
if ((self = [super init]) != nil)
|
||||||
|
@ -1179,19 +1285,33 @@ static void setNonblocking(SOCKET fd)
|
||||||
{
|
{
|
||||||
NSStreamStatus myStatus = [self streamStatus];
|
NSStreamStatus myStatus = [self streamStatus];
|
||||||
|
|
||||||
_events &= ~NSStreamEventHasSpaceAvailable;
|
if (buffer == 0)
|
||||||
if (len < 0)
|
|
||||||
{
|
{
|
||||||
return -1;
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"null pointer for buffer"];
|
||||||
}
|
}
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"zero byte length write requested"];
|
||||||
|
}
|
||||||
|
|
||||||
|
_events &= ~NSStreamEventHasSpaceAvailable;
|
||||||
|
|
||||||
if (myStatus == NSStreamStatusWriting)
|
if (myStatus == NSStreamStatusWriting)
|
||||||
{
|
{
|
||||||
myStatus = [self _check];
|
myStatus = [self _check];
|
||||||
}
|
}
|
||||||
|
if (myStatus == NSStreamStatusClosed)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if ((myStatus != NSStreamStatusOpen && myStatus != NSStreamStatusWriting))
|
if ((myStatus != NSStreamStatusOpen && myStatus != NSStreamStatusWriting))
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len > (sizeof(data) - offset))
|
if (len > (sizeof(data) - offset))
|
||||||
{
|
{
|
||||||
len = sizeof(data) - offset;
|
len = sizeof(data) - offset;
|
||||||
|
@ -1231,6 +1351,10 @@ static void setNonblocking(SOCKET fd)
|
||||||
offset = want = 0;
|
offset = want = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (closing == YES && [self streamStatus] != NSStreamStatusWriting)
|
||||||
|
{
|
||||||
|
[self close];
|
||||||
|
}
|
||||||
return [self streamStatus];
|
return [self streamStatus];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1313,7 +1437,7 @@ static void setNonblocking(SOCKET fd)
|
||||||
_sibling = sibling;
|
_sibling = sibling;
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void)setPassive: (BOOL)passive
|
-(void) setPassive: (BOOL)passive
|
||||||
{
|
{
|
||||||
_passive = passive;
|
_passive = passive;
|
||||||
}
|
}
|
||||||
|
@ -1354,7 +1478,24 @@ static void setNonblocking(SOCKET fd)
|
||||||
{
|
{
|
||||||
int writeLen;
|
int writeLen;
|
||||||
|
|
||||||
|
if (buffer == 0)
|
||||||
|
{
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"null pointer for buffer"];
|
||||||
|
}
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"zero byte length write requested"];
|
||||||
|
}
|
||||||
|
|
||||||
_events &= ~NSStreamEventHasSpaceAvailable;
|
_events &= ~NSStreamEventHasSpaceAvailable;
|
||||||
|
|
||||||
|
if ([self streamStatus] == NSStreamStatusClosed)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
writeLen = send(_sock, buffer, len, 0);
|
writeLen = send(_sock, buffer, len, 0);
|
||||||
if (writeLen == SOCKET_ERROR)
|
if (writeLen == SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
|
@ -1376,13 +1517,6 @@ static void setNonblocking(SOCKET fd)
|
||||||
return writeLen;
|
return writeLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) hasSpaceAvailable
|
|
||||||
{
|
|
||||||
if ([self streamStatus] == NSStreamStatusOpen)
|
|
||||||
return YES;
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) open
|
- (void) open
|
||||||
{
|
{
|
||||||
// could be opened because of sibling
|
// could be opened because of sibling
|
||||||
|
@ -1691,16 +1825,37 @@ static void setNonblocking(SOCKET fd)
|
||||||
SECURITY_ATTRIBUTES saAttr;
|
SECURITY_ATTRIBUTES saAttr;
|
||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
|
|
||||||
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
if ([path length] == 0)
|
||||||
saAttr.bInheritHandle = TRUE;
|
{
|
||||||
saAttr.lpSecurityDescriptor = NULL;
|
NSDebugMLog(@"address nil or empty");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if ([path length] > 240)
|
||||||
|
{
|
||||||
|
NSDebugMLog(@"address (%@) too long", path);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if ([path rangeOfString: @"\\"].length > 0)
|
||||||
|
{
|
||||||
|
NSDebugMLog(@"illegal backslash in (%@)", path);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if ([path rangeOfString: @"/"].length > 0)
|
||||||
|
{
|
||||||
|
NSDebugMLog(@"illegal slash in (%@)", path);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We allocate a new within the local pipe area
|
* We allocate a new within the local pipe area
|
||||||
*/
|
*/
|
||||||
name = [[@"\\\\.\\pipe\\" stringByAppendingString: path]
|
name = [[@"\\\\.\\pipe\\GSLocal" stringByAppendingString: path]
|
||||||
fileSystemRepresentation];
|
fileSystemRepresentation];
|
||||||
|
|
||||||
|
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||||
|
saAttr.bInheritHandle = TRUE;
|
||||||
|
saAttr.lpSecurityDescriptor = NULL;
|
||||||
|
|
||||||
handle = CreateFileW(name,
|
handle = CreateFileW(name,
|
||||||
GENERIC_WRITE|GENERIC_READ,
|
GENERIC_WRITE|GENERIC_READ,
|
||||||
0,
|
0,
|
||||||
|
@ -1720,15 +1875,17 @@ static void setNonblocking(SOCKET fd)
|
||||||
outs = AUTORELEASE([GSPipeOutputStream new]);
|
outs = AUTORELEASE([GSPipeOutputStream new]);
|
||||||
|
|
||||||
[ins _setHandle: handle];
|
[ins _setHandle: handle];
|
||||||
|
[ins setSibling: outs];
|
||||||
[outs _setHandle: handle];
|
[outs _setHandle: handle];
|
||||||
|
[outs setSibling: ins];
|
||||||
|
|
||||||
|
done:
|
||||||
if (inputStream)
|
if (inputStream)
|
||||||
{
|
{
|
||||||
[ins setSibling: outs];
|
|
||||||
*inputStream = ins;
|
*inputStream = ins;
|
||||||
}
|
}
|
||||||
if (outputStream)
|
if (outputStream)
|
||||||
{
|
{
|
||||||
[outs setSibling: ins];
|
|
||||||
*outputStream = outs;
|
*outputStream = outs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1875,7 +2032,7 @@ static void setNonblocking(SOCKET fd)
|
||||||
|
|
||||||
+ (id) inputStreamWithData: (NSData *)data
|
+ (id) inputStreamWithData: (NSData *)data
|
||||||
{
|
{
|
||||||
return AUTORELEASE([[GSMemoryInputStream alloc] initWithData: data]);
|
return AUTORELEASE([[GSDataInputStream alloc] initWithData: data]);
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (id) inputStreamWithFileAtPath: (NSString *)path
|
+ (id) inputStreamWithFileAtPath: (NSString *)path
|
||||||
|
@ -1883,24 +2040,6 @@ static void setNonblocking(SOCKET fd)
|
||||||
return AUTORELEASE([[GSFileInputStream alloc] initWithFileAtPath: path]);
|
return AUTORELEASE([[GSFileInputStream alloc] initWithFileAtPath: path]);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id) initWithData: (NSData *)data
|
|
||||||
{
|
|
||||||
RELEASE(self);
|
|
||||||
return [[GSMemoryInputStream alloc] initWithData: data];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id) initWithFileAtPath: (NSString *)path
|
|
||||||
{
|
|
||||||
RELEASE(self);
|
|
||||||
return [[GSFileInputStream alloc] initWithFileAtPath: path];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (int) read: (uint8_t *)buffer maxLength: (unsigned int)len
|
|
||||||
{
|
|
||||||
[self subclassResponsibility: _cmd];
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL) getBuffer: (uint8_t **)buffer length: (unsigned int *)len
|
- (BOOL) getBuffer: (uint8_t **)buffer length: (unsigned int *)len
|
||||||
{
|
{
|
||||||
[self subclassResponsibility: _cmd];
|
[self subclassResponsibility: _cmd];
|
||||||
|
@ -1913,19 +2052,36 @@ static void setNonblocking(SOCKET fd)
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (id) initWithData: (NSData *)data
|
||||||
|
{
|
||||||
|
RELEASE(self);
|
||||||
|
return [[GSDataInputStream alloc] initWithData: data];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) initWithFileAtPath: (NSString *)path
|
||||||
|
{
|
||||||
|
RELEASE(self);
|
||||||
|
return [[GSFileInputStream alloc] initWithFileAtPath: path];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (int) read: (uint8_t *)buffer maxLength: (unsigned int)len
|
||||||
|
{
|
||||||
|
[self subclassResponsibility: _cmd];
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation NSOutputStream
|
@implementation NSOutputStream
|
||||||
|
|
||||||
+ (id) outputStreamToMemory
|
+ (id) outputStreamToMemory
|
||||||
{
|
{
|
||||||
return AUTORELEASE([[GSMemoryOutputStream alloc]
|
return AUTORELEASE([[GSDataOutputStream alloc] init]);
|
||||||
initToBuffer: NULL capacity: 0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (id) outputStreamToBuffer: (uint8_t *)buffer capacity: (unsigned int)capacity
|
+ (id) outputStreamToBuffer: (uint8_t *)buffer capacity: (unsigned int)capacity
|
||||||
{
|
{
|
||||||
return AUTORELEASE([[GSMemoryOutputStream alloc]
|
return AUTORELEASE([[GSBufferOutputStream alloc]
|
||||||
initToBuffer: buffer capacity: capacity]);
|
initToBuffer: buffer capacity: capacity]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1935,16 +2091,16 @@ static void setNonblocking(SOCKET fd)
|
||||||
initToFileAtPath: path append: shouldAppend]);
|
initToFileAtPath: path append: shouldAppend]);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id) initToMemory
|
- (BOOL) hasSpaceAvailable
|
||||||
{
|
{
|
||||||
RELEASE(self);
|
[self subclassResponsibility: _cmd];
|
||||||
return [[GSMemoryOutputStream alloc] initToBuffer: NULL capacity: 0];
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id) initToBuffer: (uint8_t *)buffer capacity: (unsigned int)capacity
|
- (id) initToBuffer: (uint8_t *)buffer capacity: (unsigned int)capacity
|
||||||
{
|
{
|
||||||
RELEASE(self);
|
RELEASE(self);
|
||||||
return [[GSMemoryOutputStream alloc] initToBuffer: buffer capacity: capacity];
|
return [[GSBufferOutputStream alloc] initToBuffer: buffer capacity: capacity];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id) initToFileAtPath: (NSString *)path append: (BOOL)shouldAppend
|
- (id) initToFileAtPath: (NSString *)path append: (BOOL)shouldAppend
|
||||||
|
@ -1954,18 +2110,18 @@ static void setNonblocking(SOCKET fd)
|
||||||
append: shouldAppend];
|
append: shouldAppend];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (id) initToMemory
|
||||||
|
{
|
||||||
|
RELEASE(self);
|
||||||
|
return [[GSDataOutputStream alloc] init];
|
||||||
|
}
|
||||||
|
|
||||||
- (int) write: (const uint8_t *)buffer maxLength: (unsigned int)len
|
- (int) write: (const uint8_t *)buffer maxLength: (unsigned int)len
|
||||||
{
|
{
|
||||||
[self subclassResponsibility: _cmd];
|
[self subclassResponsibility: _cmd];
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) hasSpaceAvailable
|
|
||||||
{
|
|
||||||
[self subclassResponsibility: _cmd];
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation GSServerStream
|
@implementation GSServerStream
|
||||||
|
@ -2213,9 +2369,30 @@ static void setNonblocking(SOCKET fd)
|
||||||
|
|
||||||
- (id) initToAddr: (NSString*)addr
|
- (id) initToAddr: (NSString*)addr
|
||||||
{
|
{
|
||||||
|
if ([addr length] == 0)
|
||||||
|
{
|
||||||
|
NSDebugMLog(@"address nil or empty");
|
||||||
|
DESTROY(self);
|
||||||
|
}
|
||||||
|
if ([addr length] > 246)
|
||||||
|
{
|
||||||
|
NSDebugMLog(@"address (%@) too long", addr);
|
||||||
|
DESTROY(self);
|
||||||
|
}
|
||||||
|
if ([addr rangeOfString: @"\\"].length > 0)
|
||||||
|
{
|
||||||
|
NSDebugMLog(@"illegal backslash in (%@)", addr);
|
||||||
|
DESTROY(self);
|
||||||
|
}
|
||||||
|
if ([addr rangeOfString: @"/"].length > 0)
|
||||||
|
{
|
||||||
|
NSDebugMLog(@"illegal slash in (%@)", addr);
|
||||||
|
DESTROY(self);
|
||||||
|
}
|
||||||
|
|
||||||
if ((self = [super init]) != nil)
|
if ((self = [super init]) != nil)
|
||||||
{
|
{
|
||||||
path = RETAIN([@"\\\\.\\pipe\\" stringByAppendingString: addr]);
|
path = RETAIN([@"\\\\.\\pipe\\GSLocal" stringByAppendingString: addr]);
|
||||||
_loopID = INVALID_HANDLE_VALUE;
|
_loopID = INVALID_HANDLE_VALUE;
|
||||||
handle = INVALID_HANDLE_VALUE;
|
handle = INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
|
@ -2245,7 +2422,7 @@ static void setNonblocking(SOCKET fd)
|
||||||
|
|
||||||
handle = CreateNamedPipeW([path fileSystemRepresentation],
|
handle = CreateNamedPipeW([path fileSystemRepresentation],
|
||||||
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
|
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
|
||||||
PIPE_TYPE_BYTE,
|
PIPE_TYPE_MESSAGE,
|
||||||
PIPE_UNLIMITED_INSTANCES,
|
PIPE_UNLIMITED_INSTANCES,
|
||||||
BUFSIZ*64,
|
BUFSIZ*64,
|
||||||
BUFSIZ*64,
|
BUFSIZ*64,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue