mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
Add NSSocketPort class.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@15198 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
34242770a3
commit
74a7312255
3 changed files with 449 additions and 2 deletions
|
@ -1,3 +1,9 @@
|
|||
2002-12-02 Jonathan Gapen <jagapen@wisc.edu>
|
||||
|
||||
* Headers/gnustep/base/NSPort.h: Add NSSocketPort interface.
|
||||
* Source/NSSocketPort.m: New file. New MacOS X class partially
|
||||
implemented; serves as BSD socket wrapper.
|
||||
|
||||
2002-12-02 Adam Fedor <fedor@gnu.org>
|
||||
|
||||
* base.make.in (CONFIG_SYSTEM_LIBS): Set only if shared=no.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Interface for abstract superclass NSPort for use with NSConnection
|
||||
Copyright (C) 1997 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997,2002 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Richard Frith-Macdonald <richard@brainstorm.co.uk>
|
||||
Created: August 1997
|
||||
|
@ -19,13 +19,23 @@
|
|||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
AutogsdocSource: NSPort.m
|
||||
AutogsdocSource: NSSocketPort.m
|
||||
*/
|
||||
|
||||
#ifndef __NSPort_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __NSPort_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <Foundation/NSObject.h>
|
||||
|
||||
#ifdef __MINGW__
|
||||
#include <winsock2.h>
|
||||
#include <wininet.h>
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
@class NSMutableArray;
|
||||
@class NSConnection;
|
||||
@class NSDate;
|
||||
|
@ -88,4 +98,42 @@ GS_EXPORT NSString* NSPortDidBecomeInvalidNotification;
|
|||
|
||||
#define PortBecameInvalidNotification NSPortDidBecomeInvalidNotification
|
||||
|
||||
#ifndef STRICT_OPENSTEP
|
||||
typedef int NSSocketNativeHandle;
|
||||
|
||||
@interface NSSocketPort : NSPort <NSCoding, NSCopying>
|
||||
{
|
||||
NSSocketNativeHandle _socket;
|
||||
int _protocolFamily;
|
||||
int _socketType;
|
||||
int _protocol;
|
||||
NSData *_remoteAddrData;
|
||||
}
|
||||
|
||||
- (id) init;
|
||||
- (id) initWithTCPPort: (unsigned short)portNumber;
|
||||
- (id) initWithProtocolFamily: (int)family
|
||||
socketType: (int)type
|
||||
protocol: (int)protocol
|
||||
address: (NSData *)addressData;
|
||||
- (id) initWithProtocolFamily: (int)family
|
||||
socketType: (int)type
|
||||
protocol: (int)protocol
|
||||
socket: (NSSocketNativeHandle)sock;
|
||||
- (id) initRemoteWithTCPPort: (unsigned short)portNumber
|
||||
host: (NSString *)host;
|
||||
- (id) initRemoteWithProtocolFamily: (int)family
|
||||
socketType: (int)type
|
||||
protocol: (int)protocol
|
||||
address: (NSData *)addressData;
|
||||
|
||||
- (NSData *) address;
|
||||
- (int) protocol;
|
||||
- (int) protocolFamily;
|
||||
- (NSSocketNativeHandle) socket;
|
||||
- (int) socketType;
|
||||
|
||||
@end
|
||||
#endif
|
||||
|
||||
#endif /* __NSPort_h_GNUSTEP_BASE_INCLUDE */
|
||||
|
|
393
Source/NSSocketPort.m
Normal file
393
Source/NSSocketPort.m
Normal file
|
@ -0,0 +1,393 @@
|
|||
/** Implementation of a port based on BSD sockets
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Jonathan Gapen <jagapen@wisc.edu>
|
||||
Created: December 2002
|
||||
|
||||
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 Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 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 Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
|
||||
<title>NSSocketPort class reference</title>
|
||||
$Date$ $Revision$
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <Foundation/NSAutoreleasePool.h>
|
||||
#include <Foundation/NSData.h>
|
||||
#include <Foundation/NSDebug.h>
|
||||
#include <Foundation/NSException.h>
|
||||
#include <Foundation/NSHost.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <Foundation/NSNotificationQueue.h>
|
||||
#include <Foundation/NSPort.h>
|
||||
#include <Foundation/NSPortCoder.h>
|
||||
#include <Foundation/NSPortNameServer.h>
|
||||
#include <Foundation/NSRunLoop.h>
|
||||
#include <Foundation/NSZone.h>
|
||||
|
||||
#ifndef __MINGW__
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#include <wininet.h>
|
||||
#define close closesocket
|
||||
#endif /* __MINGW__ */
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* <code>NSSocketPort</code> on MacOS X(tm) is a concrete subclass of
|
||||
* NSPort which implements Distributed Objects communication between
|
||||
* hosts on a network. However, the GNUstep distributed objects system's
|
||||
* NSPort class uses TCP/IP for all of its communication. The GNUstep
|
||||
* <code>NSSocketPort</code>, then, is useful as a convenient method to
|
||||
* create and encapsulate BSD sockets:
|
||||
* </p>
|
||||
* <example>
|
||||
* int fileDesc;
|
||||
* NSFileHandle *smtpHandle;
|
||||
*
|
||||
* fileDesc = [[NSSocketPort alloc] initRemoteWithTCPPort: 25
|
||||
* host: @"mail.example.com"];
|
||||
* smtpHandle = [[NSFileHandle alloc] initWithFileDescriptor: fileDesc];
|
||||
* </example>
|
||||
*/
|
||||
@implementation NSSocketPort
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [NSSocketPort class])
|
||||
{
|
||||
[self setVersion: 1];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the receiver with a local socket to accept TCP connections
|
||||
* on a non-conflicting port number chosen by the system.
|
||||
*/
|
||||
- (id) init
|
||||
{
|
||||
return [self initWithTCPPort: 0];
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
if (_socket > -1)
|
||||
{
|
||||
NSDebugMLLog(@"NSSocketPort", @"closing socket descriptor %d", _socket);
|
||||
close(_socket);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the receiver as a local socket to accept connections on
|
||||
* TCP port <em>portNumber</em>. If <em>portNumber</em> is zero,
|
||||
* the system will chose a non-conflicting port number. <br />
|
||||
* NOTE: This method currently does not support IPv6 connections.
|
||||
*/
|
||||
- (id) initWithTCPPort: (unsigned short)portNumber
|
||||
{
|
||||
struct sockaddr_in sa;
|
||||
NSData *saData;
|
||||
|
||||
/* Clear memory, as recommended. */
|
||||
memset(&sa, 0, sizeof(struct sockaddr_in));
|
||||
sa.sin_len = sizeof(struct sockaddr_in);
|
||||
sa.sin_family = PF_INET;
|
||||
sa.sin_port = htons(portNumber);
|
||||
sa.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
saData = [NSData dataWithBytes: &sa length: sizeof(struct sockaddr_in)];
|
||||
if (saData == nil)
|
||||
{
|
||||
RELEASE(self);
|
||||
return nil;
|
||||
}
|
||||
|
||||
return [self initWithProtocolFamily: PF_INET
|
||||
socketType: SOCK_STREAM
|
||||
protocol: 0
|
||||
address: saData];
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the receiver as a local socket to accept connections on a
|
||||
* socket of <em>type</em> with the <em>protocol</em> from the protocol
|
||||
* family <em>family</em>. The <em>addrData</em> should contain a copy
|
||||
* of the protocol family-specific address data in an NSData object.
|
||||
*/
|
||||
- (id) initWithProtocolFamily: (int)family
|
||||
socketType: (int)type
|
||||
protocol: (int)protocol
|
||||
address: (NSData *)addrData
|
||||
{
|
||||
int s = -1;
|
||||
|
||||
if (addrData == nil)
|
||||
{
|
||||
NSDebugMLLog(@"NSSocketPort", @"Nil value passed for address.");
|
||||
goto iWPFAFailed;
|
||||
}
|
||||
|
||||
s = socket(family, type, protocol);
|
||||
if (s == -1)
|
||||
{
|
||||
NSLog(@"socket: %s", GSLastErrorStr(errno));
|
||||
goto iWPFAFailed;
|
||||
}
|
||||
|
||||
if (bind(s, (struct sockaddr *)[addrData bytes], [addrData length]) == -1)
|
||||
{
|
||||
NSLog(@"bind: %s", GSLastErrorStr(errno));
|
||||
goto iWPFAFailed;
|
||||
}
|
||||
|
||||
if (listen(s, SOMAXCONN) == -1)
|
||||
{
|
||||
NSLog(@"listen: %s", GSLastErrorStr(errno));
|
||||
goto iWPFAFailed;
|
||||
}
|
||||
|
||||
return [self initWithProtocolFamily: family
|
||||
socketType: type
|
||||
protocol: protocol
|
||||
socket: (NSSocketNativeHandle)s];
|
||||
|
||||
iWPFAFailed:
|
||||
if (s > -1)
|
||||
close(s);
|
||||
RELEASE(self);
|
||||
return nil;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the receiver with <em>socket</em>, the platform-native handle
|
||||
* to a previously initialized listen-mode socket of type <em>type</em>
|
||||
* with the protocol <em>protocol</em> from the protocol family
|
||||
* <em>family</em>. <br />
|
||||
* The receiver will close the socket upon deallocation.
|
||||
*/
|
||||
- (id) initWithProtocolFamily: (int)family
|
||||
socketType: (int)type
|
||||
protocol: (int)protocol
|
||||
socket: (NSSocketNativeHandle)socket
|
||||
{
|
||||
_protocolFamily = family;
|
||||
_socketType = type;
|
||||
_protocol = protocol;
|
||||
_socket = socket;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the receiver to connect to a remote TCP socket on port
|
||||
* <em>portNumber</em> of host <em>hostname</em>. The receiver delays
|
||||
* initiation of the connection until it has data to send. <br />
|
||||
* NOTE: This method currently does not support IPv6 connections.
|
||||
*/
|
||||
- (id) initRemoteWithTCPPort: (unsigned short)portNumber
|
||||
host: (NSString *)hostname
|
||||
{
|
||||
struct sockaddr_in sa;
|
||||
const char *address;
|
||||
NSData *addrData;
|
||||
|
||||
address = [[[NSHost hostWithName: hostname] address] cString];
|
||||
if (address == NULL)
|
||||
{
|
||||
RELEASE(self);
|
||||
return nil;
|
||||
}
|
||||
|
||||
/* Clear memory, as recommended. */
|
||||
memset(&sa, 0, sizeof(struct sockaddr_in));
|
||||
|
||||
sa.sin_len = sizeof(struct sockaddr_in);
|
||||
sa.sin_family = PF_INET;
|
||||
sa.sin_port = htons(portNumber);
|
||||
sa.sin_addr.s_addr = inet_addr(address);
|
||||
|
||||
addrData = [NSData dataWithBytes: &sa length: sizeof(struct sockaddr_in)];
|
||||
if (addrData == nil)
|
||||
{
|
||||
RELEASE(self);
|
||||
return nil;
|
||||
}
|
||||
|
||||
return [self initRemoteWithProtocolFamily: PF_INET
|
||||
socketType: SOCK_STREAM
|
||||
protocol: 0
|
||||
address: addrData];
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the receiver to connect to a remote socket of <em>type</em>
|
||||
* with <em>protocol</em> from the protocol family <em>family</em>. The
|
||||
* <em>addrData</em> should contain a copy of the protocol family-specific
|
||||
* address data in an NSData object.
|
||||
*/
|
||||
- (id) initRemoteWithProtocolFamily: (int)family
|
||||
socketType: (int)type
|
||||
protocol: (int)protocol
|
||||
address: (NSData *)addrData
|
||||
{
|
||||
if (addrData == nil)
|
||||
{
|
||||
NSDebugMLLog(@"NSSocketPort", @"Nil value passed for address.");
|
||||
RELEASE(self);
|
||||
return nil;
|
||||
}
|
||||
|
||||
_socket = socket(family, type, protocol);
|
||||
if (_socket == -1)
|
||||
{
|
||||
NSLog(@"socket: %s", GSLastErrorStr(errno));
|
||||
RELEASE(self);
|
||||
return nil;
|
||||
}
|
||||
|
||||
_protocolFamily = family;
|
||||
_socketType = type;
|
||||
_protocol = protocol;
|
||||
_remoteAddrData = RETAIN(addrData);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the protocol family-specific socket address in an NSData object.
|
||||
*/
|
||||
- (NSData *) address
|
||||
{
|
||||
char sa[SOCK_MAXADDRLEN];
|
||||
int len = SOCK_MAXADDRLEN;
|
||||
|
||||
if (_remoteAddrData != nil)
|
||||
{
|
||||
return _remoteAddrData;
|
||||
}
|
||||
else if (getsockname(_socket, (struct sockaddr *)&sa, &len) == 0)
|
||||
{
|
||||
return [NSData dataWithBytes: &sa length: len];
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"getsockname: %s", GSLastErrorStr(errno));
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the socket protocol.
|
||||
*/
|
||||
- (int) protocol
|
||||
{
|
||||
return _protocol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the socket protocol family.
|
||||
*/
|
||||
- (int) protocolFamily
|
||||
{
|
||||
return _protocolFamily;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the platform-native socket handle.
|
||||
*/
|
||||
- (NSSocketNativeHandle) socket
|
||||
{
|
||||
return _socket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the socket type.
|
||||
*/
|
||||
- (int) socketType
|
||||
{
|
||||
return _socketType;
|
||||
}
|
||||
|
||||
/* Concrete NSPort method implementations. */
|
||||
- (void) invalidate
|
||||
{
|
||||
/* Sockets don't close when the connection drops, they time out.
|
||||
Invalidation is not possible; the caller must notice the error. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Experimentation */
|
||||
- (void) doesNotRecognizeSelector: (SEL)aSelector
|
||||
{
|
||||
NSDebugLog(@"NSSocketPort", @"NSSocketPort does not recognize selector %@\n",
|
||||
NSStringFromSelector(aSelector));
|
||||
}
|
||||
|
||||
/* NSCopying */
|
||||
/**
|
||||
* FIXME: The Apple documentation does not explain what it means to copy an
|
||||
* NSSocketPort and I do not have access to a MacOS X system to check.
|
||||
*/
|
||||
- (id) copyWithZone: (NSZone *)zone
|
||||
{
|
||||
if (zone == NULL)
|
||||
zone = NSDefaultMallocZone();
|
||||
|
||||
if (NSShouldRetainWithZone(self, zone) == YES)
|
||||
return RETAIN(self);
|
||||
else
|
||||
{
|
||||
NSSocketPort *copy = NSAllocateObject([self class], 0, zone);
|
||||
|
||||
if (copy != nil)
|
||||
{
|
||||
/* Insulate against NSPort changes. */
|
||||
[copy setDelegate: [self delegate]];
|
||||
|
||||
copy->_socket = dup(_socket);
|
||||
copy->_protocolFamily = _protocolFamily;
|
||||
copy->_socketType = _socketType;
|
||||
copy->_protocol = _protocol;
|
||||
_remoteAddrData = [_remoteAddrData copyWithZone: zone];
|
||||
}
|
||||
|
||||
return RETAIN(copy);
|
||||
}
|
||||
}
|
||||
|
||||
/* NSCoding */
|
||||
- (void) encodeWithCoder: (NSCoder *)encoder
|
||||
{
|
||||
NSParameterAssert([encoder isKindOfClass: [NSPortCoder class]]);
|
||||
NSDebugMLLog(@"NSSocketPort", @"called");
|
||||
}
|
||||
|
||||
- (id) initWithCoder: (NSCoder *)decoder
|
||||
{
|
||||
NSParameterAssert([decoder isKindOfClass: [NSPortCoder class]]);
|
||||
NSDebugMLLog(@"NSSocketPort", @"called");
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
Loading…
Reference in a new issue