Restructuring of socket streams for maintainability and consistency between windows and unix

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@25854 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2008-01-04 06:59:49 +00:00
parent 56f3cf18df
commit 1abfa12b99
7 changed files with 1925 additions and 2347 deletions

View file

@ -1,3 +1,20 @@
2007-01-04 Richard Frith-Macdonald <rfm@gnu.org>
* Headers/Foundation/NSStream.h: Tweak comments.
* Source/GSNetwork.h: New file for common networking declarations.
* Source/GSStream.h:
* Source/GSStream.m:
* Source/unix/NSStream.m:
* Source/win32/NSStream.m:
Extract socket networking code for both unix and windows into
semi-abstract superclasses for input/output/server streams so
that we avoid huge duplication of code and can maintain the
socket code more easily.
Alter the behavior of the code on windows so that when the
other end closes the connection we should be able to read all
data in transit in the same way as on unix (ie don't close
the local end until a read/write actually fails).
2007-01-03 Richard Frith-Macdonald <rfm@gnu.org>
* Source/inet_pton.c: Add mswindows implementation of

View file

@ -254,18 +254,18 @@ typedef enum {
/**
* Creates and returns by reference an NSInputStream object and
* NSOutputStream object for a local socket connection with the
* specified path. To use them you need to open them and wait
* on the NSStreamEventOpenCompleted event on one of them
* NSOutputStream object for a local socket or named pipe connection
* with the specified path. To use them you need to open them and wait
* on the NSStreamEventOpenCompleted event on one of them.
*/
+ (void) getLocalStreamsToPath: (NSString *)path
inputStream: (NSInputStream **)inputStream
outputStream: (NSOutputStream **)outputStream;
/**
* Creates and returns by reference an NSInputStream object and NSOutputStream
* object for a anonymous local socket. Although you still need to open them,
* the open will be instantanious, and no NSStreamEventOpenCompleted event
* will be delivered.
* object for a anonymous local socket or pipe. Although you still need to
* open them, the open will be instantaneous, and no NSStreamEventOpenCompleted
* event will be delivered.
*/
+ (void) pipeWithInputStream: (NSInputStream **)inputStream
outputStream: (NSOutputStream **)outputStream;

83
Source/GSNetwork.h Normal file
View file

@ -0,0 +1,83 @@
#ifndef INCLUDED_GSNETWORK_H
#define INCLUDED_GSNETWORK_H 1
/* GSNetwork.h - This collects the system header files needed for
networking code. In future it may also contain internal wrappers
to standardise networking operations.
Copyright (C) 2008, Free Software Foundation, Inc.
Written by: Richard Frith-Macdonald <rfm@gnu.org>
Created: Jan 2008
This file is part of the GNUstep Base Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
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.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02111 USA.
*/
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#if defined(__MINGW32__)
#include <io.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <wininet.h>
#if !defined(EAFNOSUPPORT)
#define EAFNOSUPPORT WSAEAFNOSUPPORT
#endif
#define BADSOCKET(X) ((X) == INVALID_SOCKET)
#define GSNETERROR WSAGetLastError()
#define GSWOULDBLOCK (GSNETERROR == WSAEWOULDBLOCK || GSNETERROR == WSAEINPROGRESS)
#else
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#ifndef AF_LOCAL
#define AF_LOCAL AF_UNIX
#endif
#ifndef PF_LOCAL
#define PF_LOCAL PF_UNIX
#endif
#define SOCKET int /* Socket type */
#define BADSOCKET(X) ((X) < 0)
#define GSNETERROR errno
#define GSWOULDBLOCK (errno == EINPROGRESS)
#endif /* __MINGW32__ */
#ifndef INADDRSZ
#define INADDRSZ 4
#endif
#ifndef socklen_t
#define socklen_t uint32_t
#endif
#endif

View file

@ -26,10 +26,13 @@
NSInputStream and NSOutputStream are clusters rather than concrete classes
The inherance graph is:
NSStream
|-- GSStream
| `--GSSocketStream
|-- NSInputStream
| `--GSInputStream
| |-- GSDataInputStream
| |-- GSFileInputStream
| |-- GSPipeInputStream (mswindows only)
| `-- GSSocketInputStream
| |-- GSInetInputStream
| |-- GSLocalInputStream
@ -39,16 +42,18 @@
| |-- GSBufferOutputStream
| |-- GSDataOutputStream
| |-- GSFileOutputStream
| |-- GSPipeOutputStream (mswindows only)
| `-- GSSocketOutputStream
| |-- GSInetOutputStream
| |-- GSLocalOutputStream
| `-- GSInet6InputStream
`-- GSServerStream
`-- GSAbstractServerStream
`-- GSSocketServerStream
|-- GSInetServerStream
|-- GSInet6ServerStream
`-- GSLocalServerStream
`-- GSAbstractServerStream
|-- GSLocalServerStream (mswindows)
`-- GSSocketServerStream
|-- GSInetServerStream
|-- GSInet6ServerStream
`-- GSLocalServerStream (gnu/linux)
*/
#include <Foundation/NSStream.h>
@ -86,6 +91,10 @@
IVARS
@end
@interface GSAbstractServerStream : GSServerStream
IVARS
@end
@interface NSStream(Private)
/**
@ -149,10 +158,6 @@ IVARS
IVARS
@end
@interface GSAbstractServerStream : GSServerStream
IVARS
@end
/**
* The concrete subclass of NSInputStream that reads from the memory
*/
@ -187,5 +192,208 @@ IVARS
}
@end
#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
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff