From aa685d65505c5721cb09cb973956957ce3ce8cdd Mon Sep 17 00:00:00 2001 From: rfm Date: Fri, 11 May 2007 08:26:59 +0000 Subject: [PATCH] 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 --- ChangeLog | 11 +++ Headers/Foundation/NSStream.h | 9 ++ Source/GSFFIInvocation.m | 56 ++++++++----- Source/GSStream.m | 9 ++ Source/unix/NSStream.m | 154 ++++++++++++++++++++++++++++++++-- Source/win32/NSStreamWin32.m | 145 ++++++++++++++++++++++++++++++++ 6 files changed, 355 insertions(+), 29 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9d0d68731..5e34802d9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2007-05-11 Richard Frith-Macdonald + + * 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 * Source/NSURLResponse.m: diff --git a/Headers/Foundation/NSStream.h b/Headers/Foundation/NSStream.h index 7df6c8fb9..505bef5f3 100644 --- a/Headers/Foundation/NSStream.h +++ b/Headers/Foundation/NSStream.h @@ -329,6 +329,15 @@ GS_EXPORT NSString * const NSStreamSOCKSProxyVersion4; GS_EXPORT NSString * const NSStreamSOCKSProxyVersion5; 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. */ diff --git a/Source/GSFFIInvocation.m b/Source/GSFFIInvocation.m index 7f55423b0..3389dd04b 100644 --- a/Source/GSFFIInvocation.m +++ b/Source/GSFFIInvocation.m @@ -141,37 +141,40 @@ gs_find_by_receiver_best_typed_sel (id receiver, SEL sel) @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; ffi_closure *cclosure; - NSMethodSignature *sig; - /* Determine the method types so we can construct the frame. We may not - 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; + sig = [receiver methodSignatureForSelector: sel]; - if (sel_type) + if (sig == nil) { - sig = [NSMethodSignature signatureWithObjCTypes: sel_type]; - } - else - { - static NSMethodSignature *def = nil; + const char *sel_type; - /* - * Default signature is for a method returning an object. + /* Determine the method types so we can construct the frame. We may not + 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)); @@ -188,7 +191,7 @@ static IMP gs_objc_msg_forward (SEL sel) [NSException raise: NSMallocException format: @"Allocating closure"]; } if (ffi_prep_closure(cclosure, &(cframe->cif), - GSFFIInvocationCallback, cframe) != FFI_OK) + GSFFIInvocationCallback, cframe) != FFI_OK) { [NSException raise: NSGenericException format: @"Preping closure"]; } @@ -196,9 +199,18 @@ static IMP gs_objc_msg_forward (SEL sel) return (IMP)cclosure; } +static IMP gs_objc_msg_forward (SEL sel) +{ + return gs_objc_msg_forward2 (nil, sel); +} + + (void) load { +#if HAVE_FORWARD2 + __objc_msg_forward2 = gs_objc_msg_forward2; +#else __objc_msg_forward = gs_objc_msg_forward; +#endif } - (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 */ if ([sig methodReturnType] && *[sig methodReturnType] == _C_ID - && ((NSInvocation_t *)invocation)->_validReturn == YES) + && ((NSInvocation_t *)invocation)->_validReturn == YES) { AUTORELEASE(*(id *)retp); ((NSInvocation_t *)invocation)->_validReturn = NO; diff --git a/Source/GSStream.m b/Source/GSStream.m index 8c1184f72..2bc55b6d6 100644 --- a/Source/GSStream.m +++ b/Source/GSStream.m @@ -73,6 +73,15 @@ NSString * const NSStreamSOCKSProxyVersion5 NSString * const 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. diff --git a/Source/unix/NSStream.m b/Source/unix/NSStream.m index f27d16b00..e77b9203d 100644 --- a/Source/unix/NSStream.m +++ b/Source/unix/NSStream.m @@ -31,6 +31,7 @@ #include #include #include +#include #include "../GSStream.h" @@ -54,6 +55,99 @@ #define socklen_t uint32_t #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 */ @@ -80,7 +174,7 @@ - (socklen_t) sockLen; /** - * get the sockaddr + * get the remote sockaddr */ - (struct sockaddr*) peerAddr; @@ -626,7 +720,7 @@ static void setNonblocking(int fd) if ((self = [super init]) != nil) { _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)); if (ptonReturn == 0) // error { @@ -636,6 +730,17 @@ static void setNonblocking(int fd) return self; } +- (id) propertyForKey: (NSString *)key +{ + id result = propertyForInet4Stream((intptr_t)_loopID, key); + + if (result == nil) + { + result = [super propertyForKey: key]; + } + return result; +} + @end @implementation GSInet6InputStream @@ -658,7 +763,7 @@ static void setNonblocking(int fd) if ((self = [super init]) != nil) { _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)); if (ptonReturn == 0) // error { @@ -667,6 +772,18 @@ static void setNonblocking(int fd) } return self; } + +- (id) propertyForKey: (NSString *)key +{ + id result = propertyForInet6Stream((intptr_t)_loopID, key); + + if (result == nil) + { + result = [super propertyForKey: key]; + } + return result; +} + #else - (id) initToAddr: (NSString*)addr port: (int)port { @@ -1038,7 +1155,7 @@ static void setNonblocking(int fd) if ((self = [super init]) != nil) { _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)); if (ptonReturn == 0) // error { @@ -1048,6 +1165,17 @@ static void setNonblocking(int fd) return self; } +- (id) propertyForKey: (NSString *)key +{ + id result = propertyForInet4Stream((intptr_t)_loopID, key); + + if (result == nil) + { + result = [super propertyForKey: key]; + } + return result; +} + @end @implementation GSInet6OutputStream @@ -1070,7 +1198,7 @@ static void setNonblocking(int fd) if ((self = [super init]) != nil) { _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)); if (ptonReturn == 0) // error { @@ -1079,6 +1207,18 @@ static void setNonblocking(int fd) } return self; } + +- (id) propertyForKey: (NSString *)key +{ + id result = propertyForInet6Stream((intptr_t)_loopID, key); + + if (result == nil) + { + result = [super propertyForKey: key]; + } + return result; +} + #else - (id) initToAddr: (NSString*)addr port: (int)port { @@ -1585,7 +1725,7 @@ static void setNonblocking(int fd) [super init]; _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)); _loopID = (void*)(intptr_t)socket(AF_INET, SOCK_STREAM, 0); if (ptonReturn == 0 || _loopID < 0) // error @@ -1628,7 +1768,7 @@ static void setNonblocking(int fd) [super init]; _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)); _loopID = (void*)(intptr_t)socket(AF_INET6, SOCK_STREAM, 0); if (ptonReturn == 0 || _loopID < 0) // error diff --git a/Source/win32/NSStreamWin32.m b/Source/win32/NSStreamWin32.m index 24662692a..741335e5f 100644 --- a/Source/win32/NSStreamWin32.m +++ b/Source/win32/NSStreamWin32.m @@ -42,6 +42,7 @@ #include #include #include +#include #include "../GSStream.h" #include "../GSPrivate.h" @@ -50,6 +51,47 @@ 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 */ @@ -1030,6 +1072,98 @@ static void setNonblocking(SOCKET fd) 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 @implementation GSFileOutputStream @@ -1772,6 +1906,17 @@ static void setNonblocking(SOCKET fd) return self; } +- (id) propertyForKey: (NSString *)key +{ + id result = propertyForInet4Stream((intptr_t)_loopID, key); + + if (result == nil) + { + result = [super propertyForKey: key]; + } + return result; +} + @end @implementation NSStream