Some tweaks for invocations and for networking.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@25140 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2007-05-11 08:26:59 +00:00
parent 1855046feb
commit 7c633ab823
6 changed files with 355 additions and 29 deletions

View file

@ -1,3 +1,14 @@
2007-05-11 Richard Frith-Macdonald <rfm@gnu.org>
* Source/GSStream.m:
* Source/unix/NSStream.m:
* Source/win32/NSStreamWin32.m:
* Headers/Foundation/NSStream.h:
First hack at extensions to get address and port properties for
network streams.
* Source/GSFFIInvocation.m:
Attempt to use forward2 if available.
2007-05-11 Richard Frith-Macdonald <rfm@gnu.org> 2007-05-11 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSURLResponse.m: * Source/NSURLResponse.m:

View file

@ -329,6 +329,15 @@ GS_EXPORT NSString * const NSStreamSOCKSProxyVersion4;
GS_EXPORT NSString * const NSStreamSOCKSProxyVersion5; GS_EXPORT NSString * const NSStreamSOCKSProxyVersion5;
GS_EXPORT NSString * const NSStreamSOCKSProxyVersionKey; GS_EXPORT NSString * const NSStreamSOCKSProxyVersionKey;
/** May be used to read the local IP address of a tcp/ip network stream. */
GS_EXPORT NSString * const GSStreamLocalAddressKey;
/** May be used to read the local port of a tcp/ip network stream. */
GS_EXPORT NSString * const GSStreamLocalPortKey;
/** May be used to read the remote IP address of a tcp/ip network stream. */
GS_EXPORT NSString * const GSStreamRemoteAddressKey;
/** May be used to read the remote port of a tcp/ip network stream. */
GS_EXPORT NSString * const GSStreamRemotePortKey;
/** /**
* Informal protocol for delegates of instance of the [NSStream] class. * Informal protocol for delegates of instance of the [NSStream] class.
*/ */

View file

@ -141,37 +141,40 @@ gs_find_by_receiver_best_typed_sel (id receiver, SEL sel)
@implementation GSFFIInvocation @implementation GSFFIInvocation
static IMP gs_objc_msg_forward (SEL sel) static IMP gs_objc_msg_forward2 (id receiver, SEL sel)
{ {
const char *sel_type;
cifframe_t *cframe; cifframe_t *cframe;
ffi_closure *cclosure; ffi_closure *cclosure;
NSMethodSignature *sig; NSMethodSignature *sig;
/* Determine the method types so we can construct the frame. We may not sig = [receiver methodSignatureForSelector: sel];
get the right one, though. What to do then? Perhaps it can be fixed up
in the callback, but only under limited circumstances.
*/
sel_type = sel_get_type (sel);
sig = nil;
if (sel_type) if (sig == nil)
{ {
sig = [NSMethodSignature signatureWithObjCTypes: sel_type]; const char *sel_type;
}
else
{
static NSMethodSignature *def = nil;
/* /* Determine the method types so we can construct the frame. We may not
* Default signature is for a method returning an object. get the right one, though. What to do then? Perhaps it can be fixed up
in the callback, but only under limited circumstances.
*/ */
if (def == nil) sel_type = sel_get_type (sel);
if (sel_type)
{ {
def = RETAIN([NSMethodSignature signatureWithObjCTypes: "@@:"]); sig = [NSMethodSignature signatureWithObjCTypes: sel_type];
}
else
{
static NSMethodSignature *def = nil;
/*
* Default signature is for a method returning an object.
*/
if (def == nil)
{
def = RETAIN([NSMethodSignature signatureWithObjCTypes: "@@:"]);
}
sig = def;
} }
sig = def;
} }
NSCAssert1(sig, @"No signature for selector %@", NSStringFromSelector(sel)); NSCAssert1(sig, @"No signature for selector %@", NSStringFromSelector(sel));
@ -188,7 +191,7 @@ static IMP gs_objc_msg_forward (SEL sel)
[NSException raise: NSMallocException format: @"Allocating closure"]; [NSException raise: NSMallocException format: @"Allocating closure"];
} }
if (ffi_prep_closure(cclosure, &(cframe->cif), if (ffi_prep_closure(cclosure, &(cframe->cif),
GSFFIInvocationCallback, cframe) != FFI_OK) GSFFIInvocationCallback, cframe) != FFI_OK)
{ {
[NSException raise: NSGenericException format: @"Preping closure"]; [NSException raise: NSGenericException format: @"Preping closure"];
} }
@ -196,9 +199,18 @@ static IMP gs_objc_msg_forward (SEL sel)
return (IMP)cclosure; return (IMP)cclosure;
} }
static IMP gs_objc_msg_forward (SEL sel)
{
return gs_objc_msg_forward2 (nil, sel);
}
+ (void) load + (void) load
{ {
#if HAVE_FORWARD2
__objc_msg_forward2 = gs_objc_msg_forward2;
#else
__objc_msg_forward = gs_objc_msg_forward; __objc_msg_forward = gs_objc_msg_forward;
#endif
} }
- (id) initWithArgframe: (arglist_t)frame selector: (SEL)aSelector - (id) initWithArgframe: (arglist_t)frame selector: (SEL)aSelector
@ -522,7 +534,7 @@ GSFFIInvocationCallback(ffi_cif *cif, void *retp, void **args, void *user)
not the invocation so it will be demallocd at the end of this call not the invocation so it will be demallocd at the end of this call
*/ */
if ([sig methodReturnType] && *[sig methodReturnType] == _C_ID if ([sig methodReturnType] && *[sig methodReturnType] == _C_ID
&& ((NSInvocation_t *)invocation)->_validReturn == YES) && ((NSInvocation_t *)invocation)->_validReturn == YES)
{ {
AUTORELEASE(*(id *)retp); AUTORELEASE(*(id *)retp);
((NSInvocation_t *)invocation)->_validReturn = NO; ((NSInvocation_t *)invocation)->_validReturn = NO;

View file

@ -73,6 +73,15 @@ NSString * const NSStreamSOCKSProxyVersion5
NSString * const NSStreamSOCKSProxyVersionKey NSString * const NSStreamSOCKSProxyVersionKey
= @"NSStreamSOCKSProxyVersionKey"; = @"NSStreamSOCKSProxyVersionKey";
NSString * const GSStreamLocalAddressKey
= @"GSStreamLocalAddressKey";
NSString * const GSStreamLocalPortKey
= @"GSStreamLocalPortKey";
NSString * const GSStreamRemoteAddressKey
= @"GSStreamRemoteAddressKey";
NSString * const GSStreamRemotePortKey
= @"GSStreamRemotePortKey";
/* /*
* Determine the type of event to use when adding a stream to the run loop. * Determine the type of event to use when adding a stream to the run loop.

View file

@ -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/NSByteOrder.h>
#include "../GSStream.h" #include "../GSStream.h"
@ -54,6 +55,99 @@
#define socklen_t uint32_t #define socklen_t uint32_t
#endif #endif
static id propertyForInet4Stream(int descriptor, NSString *key)
{
struct sockaddr_in sin;
unsigned size = sizeof(sin);
id result = nil;
if ([key isEqualToString: GSStreamLocalAddressKey])
{
if (getsockname(descriptor, (struct sockaddr*)&sin, &size) != -1)
{
result = [NSString stringWithUTF8String:
(char*)inet_ntoa(sin.sin_addr)];
}
}
else if ([key isEqualToString: GSStreamLocalPortKey])
{
if (getsockname(descriptor, (struct sockaddr*)&sin, &size) != -1)
{
result = [NSString stringWithFormat: @"%d",
(int)GSSwapBigI16ToHost(sin.sin_port)];
}
}
else if ([key isEqualToString: GSStreamRemoteAddressKey])
{
if (getpeername(descriptor, (struct sockaddr*)&sin, &size) != -1)
{
result = [NSString stringWithUTF8String:
(char*)inet_ntoa(sin.sin_addr)];
}
}
else if ([key isEqualToString: GSStreamRemotePortKey])
{
if (getpeername(descriptor, (struct sockaddr*)&sin, &size) != -1)
{
result = [NSString stringWithFormat: @"%d",
(int)GSSwapBigI16ToHost(sin.sin_port)];
}
}
return result;
}
#if defined(AF_INET6)
static id propertyForInet6Stream(int descriptor, NSString *key)
{
struct sockaddr_in6 sin;
unsigned size = sizeof(sin);
id result = nil;
if ([key isEqualToString: GSStreamLocalAddressKey])
{
if (getsockname(descriptor, (struct sockaddr*)&sin, &size) != -1)
{
char buf[INET6_ADDRSTRLEN+1];
if (inet_ntop(AF_INET6, &(sin.sin6_addr), buf, INET6_ADDRSTRLEN) == 0)
{
buf[INET6_ADDRSTRLEN] = '\0';
result = [NSString stringWithUTF8String: buf];
}
}
}
else if ([key isEqualToString: GSStreamLocalPortKey])
{
if (getsockname(descriptor, (struct sockaddr*)&sin, &size) != -1)
{
result = [NSString stringWithFormat: @"%d",
(int)GSSwapBigI16ToHost(sin.sin6_port)];
}
}
else if ([key isEqualToString: GSStreamRemoteAddressKey])
{
if (getpeername(descriptor, (struct sockaddr*)&sin, &size) != -1)
{
char buf[INET6_ADDRSTRLEN+1];
if (inet_ntop(AF_INET6, &(sin.sin6_addr), buf, INET6_ADDRSTRLEN) == 0)
{
buf[INET6_ADDRSTRLEN] = '\0';
result = [NSString stringWithUTF8String: buf];
}
}
}
else if ([key isEqualToString: GSStreamRemotePortKey])
{
if (getpeername(descriptor, (struct sockaddr*)&sin, &size) != -1)
{
result = [NSString stringWithFormat: @"%d",
(int)GSSwapBigI16ToHost(sin.sin6_port)];
}
}
return result;
}
#endif
/** /**
* The concrete subclass of NSInputStream that reads from a file * The concrete subclass of NSInputStream that reads from a file
*/ */
@ -80,7 +174,7 @@
- (socklen_t) sockLen; - (socklen_t) sockLen;
/** /**
* get the sockaddr * get the remote sockaddr
*/ */
- (struct sockaddr*) peerAddr; - (struct sockaddr*) peerAddr;
@ -626,7 +720,7 @@ static void setNonblocking(int fd)
if ((self = [super init]) != nil) if ((self = [super init]) != nil)
{ {
_peerAddr.sin_family = AF_INET; _peerAddr.sin_family = AF_INET;
_peerAddr.sin_port = htons(port); _peerAddr.sin_port = GSSwapHostI16ToBig(port);
ptonReturn = inet_pton(AF_INET, addr_c, &(_peerAddr.sin_addr)); ptonReturn = inet_pton(AF_INET, addr_c, &(_peerAddr.sin_addr));
if (ptonReturn == 0) // error if (ptonReturn == 0) // error
{ {
@ -636,6 +730,17 @@ static void setNonblocking(int fd)
return self; return self;
} }
- (id) propertyForKey: (NSString *)key
{
id result = propertyForInet4Stream((intptr_t)_loopID, key);
if (result == nil)
{
result = [super propertyForKey: key];
}
return result;
}
@end @end
@implementation GSInet6InputStream @implementation GSInet6InputStream
@ -658,7 +763,7 @@ static void setNonblocking(int fd)
if ((self = [super init]) != nil) if ((self = [super init]) != nil)
{ {
_peerAddr.sin6_family = AF_INET6; _peerAddr.sin6_family = AF_INET6;
_peerAddr.sin6_port = htons(port); _peerAddr.sin6_port = GSSwapHostI16ToBig(port);
ptonReturn = inet_pton(AF_INET6, addr_c, &(_peerAddr.sin6_addr)); ptonReturn = inet_pton(AF_INET6, addr_c, &(_peerAddr.sin6_addr));
if (ptonReturn == 0) // error if (ptonReturn == 0) // error
{ {
@ -667,6 +772,18 @@ static void setNonblocking(int fd)
} }
return self; return self;
} }
- (id) propertyForKey: (NSString *)key
{
id result = propertyForInet6Stream((intptr_t)_loopID, key);
if (result == nil)
{
result = [super propertyForKey: key];
}
return result;
}
#else #else
- (id) initToAddr: (NSString*)addr port: (int)port - (id) initToAddr: (NSString*)addr port: (int)port
{ {
@ -1038,7 +1155,7 @@ static void setNonblocking(int fd)
if ((self = [super init]) != nil) if ((self = [super init]) != nil)
{ {
_peerAddr.sin_family = AF_INET; _peerAddr.sin_family = AF_INET;
_peerAddr.sin_port = htons(port); _peerAddr.sin_port = GSSwapHostI16ToBig(port);
ptonReturn = inet_pton(AF_INET, addr_c, &(_peerAddr.sin_addr)); ptonReturn = inet_pton(AF_INET, addr_c, &(_peerAddr.sin_addr));
if (ptonReturn == 0) // error if (ptonReturn == 0) // error
{ {
@ -1048,6 +1165,17 @@ static void setNonblocking(int fd)
return self; return self;
} }
- (id) propertyForKey: (NSString *)key
{
id result = propertyForInet4Stream((intptr_t)_loopID, key);
if (result == nil)
{
result = [super propertyForKey: key];
}
return result;
}
@end @end
@implementation GSInet6OutputStream @implementation GSInet6OutputStream
@ -1070,7 +1198,7 @@ static void setNonblocking(int fd)
if ((self = [super init]) != nil) if ((self = [super init]) != nil)
{ {
_peerAddr.sin6_family = AF_INET6; _peerAddr.sin6_family = AF_INET6;
_peerAddr.sin6_port = htons(port); _peerAddr.sin6_port = GSSwapHostI16ToBig(port);
ptonReturn = inet_pton(AF_INET6, addr_c, &(_peerAddr.sin6_addr)); ptonReturn = inet_pton(AF_INET6, addr_c, &(_peerAddr.sin6_addr));
if (ptonReturn == 0) // error if (ptonReturn == 0) // error
{ {
@ -1079,6 +1207,18 @@ static void setNonblocking(int fd)
} }
return self; return self;
} }
- (id) propertyForKey: (NSString *)key
{
id result = propertyForInet6Stream((intptr_t)_loopID, key);
if (result == nil)
{
result = [super propertyForKey: key];
}
return result;
}
#else #else
- (id) initToAddr: (NSString*)addr port: (int)port - (id) initToAddr: (NSString*)addr port: (int)port
{ {
@ -1585,7 +1725,7 @@ static void setNonblocking(int fd)
[super init]; [super init];
_serverAddr.sin_family = AF_INET; _serverAddr.sin_family = AF_INET;
_serverAddr.sin_port = htons(port); _serverAddr.sin_port = GSSwapHostI16ToBig(port);
ptonReturn = inet_pton(AF_INET, addr_c, &(_serverAddr.sin_addr)); ptonReturn = inet_pton(AF_INET, addr_c, &(_serverAddr.sin_addr));
_loopID = (void*)(intptr_t)socket(AF_INET, SOCK_STREAM, 0); _loopID = (void*)(intptr_t)socket(AF_INET, SOCK_STREAM, 0);
if (ptonReturn == 0 || _loopID < 0) // error if (ptonReturn == 0 || _loopID < 0) // error
@ -1628,7 +1768,7 @@ static void setNonblocking(int fd)
[super init]; [super init];
_serverAddr.sin6_family = AF_INET6; _serverAddr.sin6_family = AF_INET6;
_serverAddr.sin6_port = htons(port); _serverAddr.sin6_port = GSSwapHostI16ToBig(port);
ptonReturn = inet_pton(AF_INET6, addr_c, &(_serverAddr.sin6_addr)); ptonReturn = inet_pton(AF_INET6, addr_c, &(_serverAddr.sin6_addr));
_loopID = (void*)(intptr_t)socket(AF_INET6, SOCK_STREAM, 0); _loopID = (void*)(intptr_t)socket(AF_INET6, SOCK_STREAM, 0);
if (ptonReturn == 0 || _loopID < 0) // error if (ptonReturn == 0 || _loopID < 0) // error

View file

@ -42,6 +42,7 @@
#include <Foundation/NSHost.h> #include <Foundation/NSHost.h>
#include <Foundation/NSProcessInfo.h> #include <Foundation/NSProcessInfo.h>
#include <Foundation/NSDebug.h> #include <Foundation/NSDebug.h>
#include <Foundation/NSByteOrder.h>
#include "../GSStream.h" #include "../GSStream.h"
#include "../GSPrivate.h" #include "../GSPrivate.h"
@ -50,6 +51,47 @@
typedef int socklen_t; typedef int socklen_t;
static id propertyForInet4Stream(int descriptor, NSString *key)
{
struct sockaddr_in sin;
unsigned size = sizeof(sin);
id result = nil;
if ([key isEqualToString: GSStreamLocalAddressKey])
{
if (getsockname(descriptor, (struct sockaddr*)&sin, &size) != -1)
{
result = [NSString stringWithUTF8String:
(char*)inet_ntoa(sin.sin_addr)];
}
}
else if ([key isEqualToString: GSStreamLocalPortKey])
{
if (getsockname(descriptor, (struct sockaddr*)&sin, &size) != -1)
{
result = [NSString stringWithFormat: @"%d",
(int)GSSwapBigI16ToHost(sin.sin_port)];
}
}
else if ([key isEqualToString: GSStreamRemoteAddressKey])
{
if (getpeername(descriptor, (struct sockaddr*)&sin, &size) != -1)
{
result = [NSString stringWithUTF8String:
(char*)inet_ntoa(sin.sin_addr)];
}
}
else if ([key isEqualToString: GSStreamRemotePortKey])
{
if (getpeername(descriptor, (struct sockaddr*)&sin, &size) != -1)
{
result = [NSString stringWithFormat: @"%d",
(int)GSSwapBigI16ToHost(sin.sin_port)];
}
}
return result;
}
/** /**
* The concrete subclass of NSInputStream that reads from a file * The concrete subclass of NSInputStream that reads from a file
*/ */
@ -1030,6 +1072,98 @@ static void setNonblocking(SOCKET fd)
return self; return self;
} }
static id propertyForInet4Stream(int descriptor, NSString *key)
{
struct sockaddr_in sin;
unsigned size = sizeof(sin);
id result = nil;
if ([key isEqualToString: GSStreamLocalAddressKey])
{
if (getsockname(descriptor, (struct sockaddr*)&sin, &size) != -1)
{
result = [NSString stringWithUTF8String:
(char*)inet_ntoa(sin.sin_addr)];
}
}
else if ([key isEqualToString: GSStreamLocalPortKey])
{
if (getsockname(descriptor, (struct sockaddr*)&sin, &size) != -1)
{
result = [NSString stringWithFormat: @"%d",
(int)GSSwapBigI16ToHost(sin.sin_port)];
}
}
else if ([key isEqualToString: GSStreamRemoteAddressKey])
{
if (getpeername(descriptor, (struct sockaddr*)&sin, &size) != -1)
{
result = [NSString stringWithUTF8String:
(char*)inet_ntoa(sin.sin_addr)];
}
}
else if ([key isEqualToString: GSStreamRemotePortKey])
{
if (getpeername(descriptor, (struct sockaddr*)&sin, &size) != -1)
{
result = [NSString stringWithFormat: @"%d",
(int)GSSwapBigI16ToHost(sin.sin_port)];
}
}
return result;
}
#if defined(AF_INET6)
static id propertyForInet6Stream(int descriptor, NSString *key)
{
struct sockaddr_in6 sin;
unsigned size = sizeof(sin);
id result = nil;
if ([key isEqualToString: GSStreamLocalAddressKey])
{
if (getsockname(descriptor, (struct sockaddr*)&sin, &size) != -1)
{
char buf[INET6_ADDRSTRLEN+1];
if (inet_ntop(AF_INET6, &(sin.sin6_addr), buf, INET6_ADDRSTRLEN) == 0)
{
buf[INET6_ADDRSTRLEN] = '\0';
result = [NSString stringWithUTF8String: buf];
}
}
}
else if ([key isEqualToString: GSStreamLocalPortKey])
{
if (getsockname(descriptor, (struct sockaddr*)&sin, &size) != -1)
{
result = [NSString stringWithFormat: @"%d",
(int)GSSwapBigI16ToHost(sin.sin6_port)];
}
}
else if ([key isEqualToString: GSStreamRemoteAddressKey])
{
if (getpeername(descriptor, (struct sockaddr*)&sin, &size) != -1)
{
char buf[INET6_ADDRSTRLEN+1];
if (inet_ntop(AF_INET6, &(sin.sin6_addr), buf, INET6_ADDRSTRLEN) == 0)
{
buf[INET6_ADDRSTRLEN] = '\0';
result = [NSString stringWithUTF8String: buf];
}
}
}
else if ([key isEqualToString: GSStreamRemotePortKey])
{
if (getpeername(descriptor, (struct sockaddr*)&sin, &size) != -1)
{
result = [NSString stringWithFormat: @"%d",
(int)GSSwapBigI16ToHost(sin.sin6_port)];
}
}
return result;
}
#endif
@end @end
@implementation GSFileOutputStream @implementation GSFileOutputStream
@ -1772,6 +1906,17 @@ static void setNonblocking(SOCKET fd)
return self; return self;
} }
- (id) propertyForKey: (NSString *)key
{
id result = propertyForInet4Stream((intptr_t)_loopID, key);
if (result == nil)
{
result = [super propertyForKey: key];
}
return result;
}
@end @end
@implementation NSStream @implementation NSStream