Support outgoing connections bound to a specific local address.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@18953 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
CaS 2004-03-29 14:53:37 +00:00
parent 3c85fee35b
commit 1a0cf15c79
7 changed files with 108 additions and 17 deletions

View file

@ -10,6 +10,15 @@
contigure.ac: contigure.ac:
Add --enable-xslt option to require stylesheet support (in case we want Add --enable-xslt option to require stylesheet support (in case we want
to start uisng it to generate documentation) to start uisng it to generate documentation)
* Headers/Foundation/NSURLHandle.h:
* Source/GSFileHandle.m:
* Source/GSHTTPURLHandle.m:
* Source/NSFileHandle.m:
* Source/NSURLHandle.m:
Support binding to specific local ip address for outgoing connections
in gnustep extensions.
* Source/GSMime.m: ([-setContent:]), ([-addContent:]) Check that
content of a multipart document consists of GSMimeDocument objects.
2004-03-29 Adrian Robert <arobert@cogsci.ucsd.edu> 2004-03-29 Adrian Robert <arobert@cogsci.ucsd.edu>

View file

@ -42,6 +42,7 @@ GS_EXPORT NSString * const NSHTTPPropertyRedirectionHeadersKey;
GS_EXPORT NSString * const NSHTTPPropertyErrorPageDataKey; GS_EXPORT NSString * const NSHTTPPropertyErrorPageDataKey;
#ifndef NO_GNUSTEP #ifndef NO_GNUSTEP
GS_EXPORT NSString * const GSHTTPPropertyLocalHostKey;
GS_EXPORT NSString * const GSHTTPPropertyMethodKey; GS_EXPORT NSString * const GSHTTPPropertyMethodKey;
GS_EXPORT NSString * const GSHTTPPropertyProxyHostKey; GS_EXPORT NSString * const GSHTTPPropertyProxyHostKey;
GS_EXPORT NSString * const GSHTTPPropertyProxyPortKey; GS_EXPORT NSString * const GSHTTPPropertyProxyPortKey;

View file

@ -3317,6 +3317,11 @@ static NSCharacterSet *tokenSet = nil;
*/ */
- (void) addContent: (id)newContent - (void) addContent: (id)newContent
{ {
if ([newContent isKindOfClass: [GSMimeDocument class]] == NO)
{
[NSException raise: NSInvalidArgumentException
format: @"Content to add is not a GSMimeDocument"];
}
if (content == nil) if (content == nil)
{ {
content = [NSMutableArray new]; content = [NSMutableArray new];
@ -4469,6 +4474,18 @@ static NSCharacterSet *tokenSet = nil;
{ {
if (newContent != content) if (newContent != content)
{ {
unsigned c = [newContent count];
while (c-- > 0)
{
id o = [newContent objectAtIndex: c];
if ([o isKindOfClass: [GSMimeDocument class]] == NO)
{
[NSException raise: NSInvalidArgumentException
format: @"Content contains non-GSMimeDocument"];
}
}
newContent = [newContent mutableCopy]; newContent = [newContent mutableCopy];
ASSIGN(content, newContent); ASSIGN(content, newContent);
RELEASE(newContent); RELEASE(newContent);

View file

@ -685,6 +685,8 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
static BOOL beenHere = NO; static BOOL beenHere = NO;
SOCKET net; SOCKET net;
struct sockaddr_in sin; struct sockaddr_in sin;
struct sockaddr_in lsin;
NSString *lhost = nil;
NSString *shost = nil; NSString *shost = nil;
NSString *sport = nil; NSString *sport = nil;
@ -720,6 +722,30 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
return nil; return nil;
} }
if ([p hasPrefix: @"bind-"] == YES)
{
NSRange r;
lhost = [p substringFromIndex: 5];
r = [lhost rangeOfString: @":"];
if (r.length > 0)
{
p = [lhost substringFromIndex: NSMaxRange(r)];
lhost = [lhost substringToIndex: r.location];
}
else
{
p = nil;
}
if (getAddr(lhost, p, @"tcp", &lsin) == NO)
{
NSLog(@"bad bind address specification");
RELEASE(self);
return nil;
}
p = @"tcp";
}
/** /**
* A protocol fo the form 'socks-...' controls socks operation, * A protocol fo the form 'socks-...' controls socks operation,
* overriding defaults and environment variables.<br /> * overriding defaults and environment variables.<br />
@ -795,6 +821,21 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
RELEASE(self); RELEASE(self);
return nil; return nil;
} }
if (lhost != nil)
{
if (bind(net, (struct sockaddr *)&lsin, sizeof(lsin)) == SOCKET_ERROR)
{
NSLog(@"unable to bind to port %s:%d - %s", inet_ntoa(lsin.sin_addr),
GSSwapBigI16ToHost(sin.sin_port), GSLastErrorStr(errno));
#if defined(__MINGW__)
(void) closesocket(net);
#else
(void) close(net);
#endif
RELEASE(self);
return nil;
}
}
#if defined(__MINGW__) #if defined(__MINGW__)
self = [self initWithNativeHandle: (void*)net closeOnDealloc: YES]; self = [self initWithNativeHandle: (void*)net closeOnDealloc: YES];

View file

@ -161,6 +161,12 @@ char emp[64] = {
* secure connection when a proxy is specified, GSHTTPURLHandle will * secure connection when a proxy is specified, GSHTTPURLHandle will
* attempt to open an SSL Tunnel through the proxy. * attempt to open an SSL Tunnel through the proxy.
* </p> * </p>
* <p>
* Requests to the remote server may be forced to be bound to a
* particular local IP address by using the key
* &quot;GSHTTPPropertyLocalHostKey&quot; which must contain the
* IP address of a network interface on the local host.
* </p>
*/ */
@implementation GSHTTPURLHandle @implementation GSHTTPURLHandle
@ -450,6 +456,7 @@ static void debugWrite(NSData *data)
NSNotificationCenter *nc; NSNotificationCenter *nc;
NSString *host = nil; NSString *host = nil;
NSString *port = nil; NSString *port = nil;
NSString *s;
/* /*
* Don't start a load if one is in progress. * Don't start a load if one is in progress.
@ -471,6 +478,20 @@ static void debugWrite(NSData *data)
[sock closeFile]; [sock closeFile];
DESTROY(sock); DESTROY(sock);
} }
/*
* If we have a local address specified, tell the file handle to bind to it.
*/
s = [request objectForKey: GSHTTPPropertyLocalHostKey];
if ([s length] > 0)
{
s = [NSString stringWithFormat: @"bind-%@", s];
}
else
{
s = @"tcp"; // Bind to any.
}
if ([[request objectForKey: GSHTTPPropertyProxyHostKey] length] == 0) if ([[request objectForKey: GSHTTPPropertyProxyHostKey] length] == 0)
{ {
NSNumber *p; NSNumber *p;
@ -493,17 +514,15 @@ static void debugWrite(NSData *data)
@"https not supported ... needs SSL bundle"]; @"https not supported ... needs SSL bundle"];
return; return;
} }
sock = [sslClass sock = [sslClass fileHandleAsClientInBackgroundAtAddress: host
fileHandleAsClientInBackgroundAtAddress: host
service: port service: port
protocol: @"tcp"]; protocol: s];
} }
else else
{ {
sock = [NSFileHandle sock = [NSFileHandle fileHandleAsClientInBackgroundAtAddress: host
fileHandleAsClientInBackgroundAtAddress: host
service: port service: port
protocol: @"tcp"]; protocol: s];
} }
} }
else else
@ -522,19 +541,17 @@ static void debugWrite(NSData *data)
} }
host = [request objectForKey: GSHTTPPropertyProxyHostKey]; host = [request objectForKey: GSHTTPPropertyProxyHostKey];
port = [request objectForKey: GSHTTPPropertyProxyPortKey]; port = [request objectForKey: GSHTTPPropertyProxyPortKey];
sock = [sslClass sock = [sslClass fileHandleAsClientInBackgroundAtAddress: host
fileHandleAsClientInBackgroundAtAddress: host
service: port service: port
protocol: @"tcp"]; protocol: s];
} }
else else
{ {
host = [request objectForKey: GSHTTPPropertyProxyHostKey]; host = [request objectForKey: GSHTTPPropertyProxyHostKey];
port = [request objectForKey: GSHTTPPropertyProxyPortKey]; port = [request objectForKey: GSHTTPPropertyProxyPortKey];
sock = [NSFileHandle sock = [NSFileHandle fileHandleAsClientInBackgroundAtAddress: host
fileHandleAsClientInBackgroundAtAddress: host
service: port service: port
protocol: @"tcp"]; protocol: s];
} }
} }
if (sock == nil) if (sock == nil)

View file

@ -428,7 +428,10 @@ NSString * const NSFileHandleOperationException
* is <em>not</em> made via a socks server.<br /> * is <em>not</em> made via a socks server.<br />
* Otherwise, the text '...' must be the name of the host on which the * Otherwise, the text '...' must be the name of the host on which the
* socks5 server is running, with an optional port number separated * socks5 server is running, with an optional port number separated
* from the host name by a colon. * from the host name by a colon.<br />
* Alternatively a prefix of the form 'bind-' forllowed by an IP address
* may be used (for non-socks connections) to ensure that the connection
* is made from the specified address.
* </item> * </item>
* <item> * <item>
* If modes is nil or empty, uses NSDefaultRunLoopMode. * If modes is nil or empty, uses NSDefaultRunLoopMode.

View file

@ -64,6 +64,9 @@ NSString * const NSHTTPPropertyErrorPageDataKey
NSString * const GSHTTPPropertyMethodKey NSString * const GSHTTPPropertyMethodKey
= @"GSHTTPPropertyMethodKey"; = @"GSHTTPPropertyMethodKey";
NSString * const GSHTTPPropertyLocalHostKey
= @"GSHTTPPropertyLocalHostKey";
NSString * const GSHTTPPropertyProxyHostKey NSString * const GSHTTPPropertyProxyHostKey
= @"GSHTTPPropertyProxyHostKey"; = @"GSHTTPPropertyProxyHostKey";