2006-02-15 17:49:40 +00:00
|
|
|
#ifndef INCLUDED_GSSTREAM_H
|
|
|
|
#define INCLUDED_GSSTREAM_H
|
|
|
|
|
|
|
|
/** Implementation for GSStream for GNUStep
|
|
|
|
Copyright (C) 2006 Free Software Foundation, Inc.
|
|
|
|
|
|
|
|
Written by: Derek Zhou <derekzhou@gmail.com>
|
|
|
|
Written by: Richard Frith-Macdonald <rfm@gnu.org>
|
|
|
|
Date: 2006
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
2007-09-14 11:36:11 +00:00
|
|
|
modify it under the terms of the GNU Lesser General Public
|
2006-02-15 17:49:40 +00:00
|
|
|
License as published by the Free Software Foundation; either
|
2007-09-14 11:36:11 +00:00
|
|
|
version 3 of the License, or (at your option) any later version.
|
2006-02-15 17:49:40 +00:00
|
|
|
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
2007-09-14 11:36:11 +00:00
|
|
|
You should have received a copy of the GNU Lesser General Public
|
2006-02-15 17:49:40 +00:00
|
|
|
License along with this library; if not, write to the Free
|
|
|
|
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
Boston, MA 02111 USA.
|
|
|
|
|
|
|
|
NSInputStream and NSOutputStream are clusters rather than concrete classes
|
|
|
|
The inherance graph is:
|
|
|
|
NSStream
|
2008-01-04 06:59:49 +00:00
|
|
|
|-- GSStream
|
|
|
|
| `--GSSocketStream
|
2006-02-15 17:49:40 +00:00
|
|
|
|-- NSInputStream
|
|
|
|
| `--GSInputStream
|
2006-08-11 13:27:10 +00:00
|
|
|
| |-- GSDataInputStream
|
2006-02-15 17:49:40 +00:00
|
|
|
| |-- GSFileInputStream
|
2008-01-04 06:59:49 +00:00
|
|
|
| |-- GSPipeInputStream (mswindows only)
|
2006-02-15 17:49:40 +00:00
|
|
|
| `-- GSSocketInputStream
|
|
|
|
| |-- GSInetInputStream
|
|
|
|
| |-- GSLocalInputStream
|
|
|
|
| `-- GSInet6InputStream
|
2006-02-16 19:19:30 +00:00
|
|
|
|-- NSOutputStream
|
|
|
|
| `--GSOutputStream
|
2006-08-11 13:27:10 +00:00
|
|
|
| |-- GSBufferOutputStream
|
|
|
|
| |-- GSDataOutputStream
|
2006-02-16 19:19:30 +00:00
|
|
|
| |-- GSFileOutputStream
|
2008-01-04 06:59:49 +00:00
|
|
|
| |-- GSPipeOutputStream (mswindows only)
|
2006-02-16 19:19:30 +00:00
|
|
|
| `-- GSSocketOutputStream
|
|
|
|
| |-- GSInetOutputStream
|
|
|
|
| |-- GSLocalOutputStream
|
|
|
|
| `-- GSInet6InputStream
|
|
|
|
`-- GSServerStream
|
2008-01-04 06:59:49 +00:00
|
|
|
`-- GSAbstractServerStream
|
|
|
|
|-- GSLocalServerStream (mswindows)
|
|
|
|
`-- GSSocketServerStream
|
|
|
|
|-- GSInetServerStream
|
|
|
|
|-- GSInet6ServerStream
|
|
|
|
`-- GSLocalServerStream (gnu/linux)
|
2006-02-16 19:19:30 +00:00
|
|
|
*/
|
2006-02-15 17:49:40 +00:00
|
|
|
|
|
|
|
#include <Foundation/NSStream.h>
|
2006-03-21 15:33:05 +00:00
|
|
|
#include <Foundation/NSRunLoop.h>
|
2007-05-12 17:11:35 +00:00
|
|
|
#include <Foundation/NSMapTable.h>
|
2006-03-21 15:33:05 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Convenience methods used to add streams to the run loop.
|
|
|
|
*/
|
|
|
|
@interface NSRunLoop (NSStream)
|
|
|
|
- (void) addStream: (NSStream*)aStream mode: (NSString*)mode;
|
|
|
|
- (void) removeStream: (NSStream*)aStream mode: (NSString*)mode;
|
|
|
|
@end
|
|
|
|
|
|
|
|
@class NSMutableData;
|
2006-02-15 17:49:40 +00:00
|
|
|
|
|
|
|
#define IVARS \
|
|
|
|
{ \
|
|
|
|
id _delegate; /* Delegate controls operation. */\
|
|
|
|
NSMutableDictionary *_properties; /* storage for properties */\
|
|
|
|
BOOL _delegateValid;/* whether the delegate responds*/\
|
|
|
|
NSError *_lastError; /* last error occured */\
|
|
|
|
NSStreamStatus _currentStatus;/* current status */\
|
2007-05-12 17:11:35 +00:00
|
|
|
NSMapTable *_loops; /* Run loops and their modes. */\
|
2006-08-10 09:15:30 +00:00
|
|
|
void *_loopID; /* file descriptor etc. */\
|
|
|
|
int _events; /* Signalled events. */\
|
2006-02-15 17:49:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* GSInputStream and GSOutputStream both inherit methods from the
|
|
|
|
* GSStream class using 'behaviors', and must therefore share
|
|
|
|
* EXACTLY THE SAME initial ivar layout.
|
|
|
|
*/
|
|
|
|
@interface GSStream : NSStream
|
|
|
|
IVARS
|
|
|
|
@end
|
2006-03-21 15:33:05 +00:00
|
|
|
|
2008-01-04 06:59:49 +00:00
|
|
|
@interface GSAbstractServerStream : GSServerStream
|
|
|
|
IVARS
|
|
|
|
@end
|
|
|
|
|
2006-03-21 15:33:05 +00:00
|
|
|
@interface NSStream(Private)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Async notification
|
|
|
|
*/
|
|
|
|
- (void) _dispatch;
|
|
|
|
|
2006-02-15 17:49:40 +00:00
|
|
|
/**
|
|
|
|
* Return YES if the stream is opened, NO otherwise.
|
|
|
|
*/
|
|
|
|
- (BOOL) _isOpened;
|
|
|
|
|
2006-03-21 15:33:05 +00:00
|
|
|
/**
|
|
|
|
* Return previously set reference for IO in run loop.
|
|
|
|
*/
|
|
|
|
- (void*) _loopID;
|
|
|
|
|
2007-05-12 17:11:35 +00:00
|
|
|
/**
|
|
|
|
* Place the stream in all the scheduled runloops.
|
|
|
|
*/
|
|
|
|
- (void) _schedule;
|
|
|
|
|
2006-02-15 17:49:40 +00:00
|
|
|
/**
|
|
|
|
* send an event to delegate
|
|
|
|
*/
|
|
|
|
- (void) _sendEvent: (NSStreamEvent)event;
|
|
|
|
|
|
|
|
/**
|
2006-03-21 15:33:05 +00:00
|
|
|
* setter for IO event reference (file descriptor, file handle etc )
|
2006-02-15 17:49:40 +00:00
|
|
|
*/
|
2006-03-21 15:33:05 +00:00
|
|
|
- (void) _setLoopID: (void *)ref;
|
2006-02-15 17:49:40 +00:00
|
|
|
|
2006-02-16 19:19:30 +00:00
|
|
|
/**
|
2006-03-21 15:33:05 +00:00
|
|
|
* set the status to newStatus. an exception is error cannot
|
|
|
|
* be overwriten by closed
|
2006-02-16 19:19:30 +00:00
|
|
|
*/
|
2006-03-21 15:33:05 +00:00
|
|
|
- (void) _setStatus: (NSStreamStatus)newStatus;
|
2006-02-16 19:19:30 +00:00
|
|
|
|
2006-02-15 17:49:40 +00:00
|
|
|
/**
|
|
|
|
* record an error based on errno
|
|
|
|
*/
|
|
|
|
- (void) _recordError;
|
2006-08-08 13:31:50 +00:00
|
|
|
|
|
|
|
/**
|
2006-08-10 09:15:30 +00:00
|
|
|
* say whether there is unhandled data for the stream.
|
2006-08-08 13:31:50 +00:00
|
|
|
*/
|
|
|
|
- (BOOL) _unhandledData;
|
2007-05-12 17:11:35 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove the stream from all the scheduled runloops.
|
|
|
|
*/
|
|
|
|
- (void) _unschedule;
|
|
|
|
|
2006-02-15 17:49:40 +00:00
|
|
|
@end
|
|
|
|
|
|
|
|
@interface GSInputStream : NSInputStream
|
|
|
|
IVARS
|
|
|
|
@end
|
|
|
|
|
|
|
|
@interface GSOutputStream : NSOutputStream
|
|
|
|
IVARS
|
|
|
|
@end
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The concrete subclass of NSInputStream that reads from the memory
|
|
|
|
*/
|
2006-08-11 13:27:10 +00:00
|
|
|
@interface GSDataInputStream : GSInputStream
|
2006-02-15 17:49:40 +00:00
|
|
|
{
|
|
|
|
@private
|
|
|
|
NSData *_data;
|
|
|
|
unsigned long _pointer;
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
/**
|
2006-08-11 13:27:10 +00:00
|
|
|
* The concrete subclass of NSOutputStream that writes to a buffer
|
2006-02-15 17:49:40 +00:00
|
|
|
*/
|
2006-08-11 13:27:10 +00:00
|
|
|
@interface GSBufferOutputStream : GSOutputStream
|
|
|
|
{
|
|
|
|
@private
|
|
|
|
uint8_t *_buffer;
|
|
|
|
unsigned _capacity;
|
|
|
|
unsigned long _pointer;
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The concrete subclass of NSOutputStream that writes to a variable sise buffer
|
|
|
|
*/
|
|
|
|
@interface GSDataOutputStream : GSOutputStream
|
2006-02-15 17:49:40 +00:00
|
|
|
{
|
|
|
|
@private
|
|
|
|
NSMutableData *_data;
|
|
|
|
unsigned long _pointer;
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
2008-01-04 06:59:49 +00:00
|
|
|
#include "GSNetwork.h"
|
|
|
|
|
|
|
|
|
|
|
|
#define SOCKIVARS \
|
|
|
|
{ \
|
|
|
|
id _sibling; /* For bidirectional traffic. */\
|
|
|
|
BOOL _passive; /* YES means already connected. */\
|
|
|
|
BOOL _closing; /* Must close on next failure. */\
|
|
|
|
SOCKET _sock; /* Needed for ms-windows. */\
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The semi-abstract GSSocketStream class is not intended to be subclassed
|
|
|
|
* but is used to add behaviors to other socket based classes.
|
|
|
|
*/
|
|
|
|
@interface GSSocketStream : GSStream
|
|
|
|
SOCKIVARS
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get the sockaddr
|
|
|
|
*/
|
|
|
|
- (struct sockaddr*) _peerAddr;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* setter for closing flag ... the remote end has stopped either sending
|
|
|
|
* or receiving, so any I/O operation which would block means that the
|
|
|
|
* connection is no longer operable in that direction.
|
|
|
|
*/
|
|
|
|
- (void) _setClosing: (BOOL)passive;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* setter for passive (the underlying socket connection is already open and
|
|
|
|
* doesw not need to be re-opened).
|
|
|
|
*/
|
|
|
|
- (void) _setPassive: (BOOL)passive;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* setter for sibling
|
|
|
|
*/
|
|
|
|
- (void) _setSibling: (GSSocketStream*)sibling;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the socket used for this stream.
|
|
|
|
*/
|
|
|
|
- (void) _setSock: (SOCKET)sock;
|
|
|
|
|
|
|
|
/* Return the socket
|
|
|
|
*/
|
|
|
|
- (SOCKET) _sock;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the length of the socket addr
|
|
|
|
*/
|
|
|
|
- (socklen_t) _sockLen;
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The abstract subclass of NSInputStream that reads from a socket.
|
|
|
|
* It inherits from GSInputStream and adds behaviors from GSSocketStream
|
|
|
|
* so it must have the same instance variable layout as GSSocketStream.
|
|
|
|
*/
|
|
|
|
@interface GSSocketInputStream : GSInputStream
|
|
|
|
SOCKIVARS
|
|
|
|
@end
|
|
|
|
@interface GSSocketInputStream (AddedBehaviors)
|
|
|
|
- (struct sockaddr*) _peerAddr;
|
|
|
|
- (void) _setClosing: (BOOL)passive;
|
|
|
|
- (void) _setPassive: (BOOL)passive;
|
|
|
|
- (void) _setSibling: (GSSocketStream*)sibling;
|
|
|
|
- (void) _setSock: (SOCKET)sock;
|
|
|
|
- (SOCKET) _sock;
|
|
|
|
- (socklen_t) _sockLen;
|
|
|
|
@end
|
|
|
|
|
|
|
|
@interface GSInetInputStream : GSSocketInputStream
|
|
|
|
{
|
|
|
|
@private
|
|
|
|
struct sockaddr_in _peerAddr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* the designated initializer
|
|
|
|
*/
|
|
|
|
- (id) initToAddr: (NSString*)addr port: (int)port;
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
@interface GSInet6InputStream : GSSocketInputStream
|
|
|
|
{
|
|
|
|
@private
|
|
|
|
#if defined(AF_INET6)
|
|
|
|
struct sockaddr_in6 _peerAddr;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* the designated initializer
|
|
|
|
*/
|
|
|
|
- (id) initToAddr: (NSString*)addr port: (int)port;
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The abstract subclass of NSOutputStream that writes to a socket.
|
|
|
|
* It inherits from GSOutputStream and adds behaviors from GSSocketStream
|
|
|
|
* so it must have the same instance variable layout as GSSocketStream.
|
|
|
|
*/
|
|
|
|
@interface GSSocketOutputStream : GSOutputStream
|
|
|
|
SOCKIVARS
|
|
|
|
@end
|
|
|
|
@interface GSSocketOutputStream (AddedBehaviors)
|
|
|
|
- (struct sockaddr*) _peerAddr;
|
|
|
|
- (void) _setClosing: (BOOL)passive;
|
|
|
|
- (void) _setPassive: (BOOL)passive;
|
|
|
|
- (void) _setSibling: (GSSocketStream*)sibling;
|
|
|
|
- (void) _setSock: (SOCKET)sock;
|
|
|
|
- (SOCKET) _sock;
|
|
|
|
- (socklen_t) _sockLen;
|
|
|
|
@end
|
|
|
|
|
|
|
|
@interface GSInetOutputStream : GSSocketOutputStream
|
|
|
|
{
|
|
|
|
@private
|
|
|
|
struct sockaddr_in _peerAddr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* the designated initializer
|
|
|
|
*/
|
|
|
|
- (id) initToAddr: (NSString*)addr port: (int)port;
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
@interface GSInet6OutputStream : GSSocketOutputStream
|
|
|
|
{
|
|
|
|
@private
|
|
|
|
#if defined(AF_INET6)
|
|
|
|
struct sockaddr_in6 _peerAddr;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* the designated initializer
|
|
|
|
*/
|
|
|
|
- (id) initToAddr: (NSString*)addr port: (int)port;
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The subclass of NSStream that accepts connections from a socket.
|
|
|
|
* It inherits from GSAbstractServerStream and adds behaviors from
|
|
|
|
* GSSocketStream so it must have the same instance variable layout
|
|
|
|
* as GSSocketStream.
|
|
|
|
*/
|
|
|
|
@interface GSSocketServerStream : GSAbstractServerStream
|
|
|
|
SOCKIVARS
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the class of the inputStream associated with this
|
|
|
|
* type of serverStream.
|
|
|
|
*/
|
|
|
|
- (Class) _inputStreamClass;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the class of the outputStream associated with this
|
|
|
|
* type of serverStream.
|
|
|
|
*/
|
|
|
|
- (Class) _outputStreamClass;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the sockaddr for this server
|
|
|
|
*/
|
|
|
|
- (struct sockaddr*) _serverAddr;
|
|
|
|
|
|
|
|
@end
|
|
|
|
@interface GSSocketServerStream (AddedBehaviors)
|
|
|
|
- (struct sockaddr*) _peerAddr;
|
|
|
|
- (void) _setClosing: (BOOL)passive;
|
|
|
|
- (void) _setPassive: (BOOL)passive;
|
|
|
|
- (void) _setSibling: (GSSocketStream*)sibling;
|
|
|
|
- (void) _setSock: (SOCKET)sock;
|
|
|
|
- (SOCKET) _sock;
|
|
|
|
- (socklen_t) _sockLen;
|
|
|
|
@end
|
|
|
|
|
|
|
|
@interface GSInetServerStream : GSSocketServerStream
|
|
|
|
{
|
|
|
|
@private
|
|
|
|
struct sockaddr_in _serverAddr;
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
@interface GSInet6ServerStream : GSSocketServerStream
|
|
|
|
{
|
|
|
|
@private
|
|
|
|
#if defined(AF_INET6)
|
|
|
|
struct sockaddr_in6 _serverAddr;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
2006-02-15 17:49:40 +00:00
|
|
|
#endif
|
|
|
|
|