mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 00:41:02 +00:00
move tcp tune code to be shared between windows and unix
This commit is contained in:
parent
ca48e4f5d7
commit
2df0df5450
3 changed files with 191 additions and 185 deletions
|
@ -101,191 +101,6 @@ static GSFileHandle *fh_stdin = nil;
|
|||
static GSFileHandle *fh_stdout = nil;
|
||||
static GSFileHandle *fh_stderr = nil;
|
||||
|
||||
@implementation GSTcpTune
|
||||
|
||||
static int tuneDelay = 0;
|
||||
static int tuneLinger = -1;
|
||||
static int tuneReceive = 0;
|
||||
static BOOL tuneSendAll = NO;
|
||||
static int tuneRcvBuf = 0;
|
||||
static int tuneSndBuf = 0;
|
||||
|
||||
+ (void) defaultsChanged: (NSNotification*)n
|
||||
{
|
||||
NSUserDefaults *defs = (NSUserDefaults*)[n object];
|
||||
NSString *str;
|
||||
|
||||
if (nil == defs)
|
||||
{
|
||||
defs = [NSUserDefaults standardUserDefaults];
|
||||
}
|
||||
str = [defs stringForKey: @"GSTcpLinger"];
|
||||
if (nil == str)
|
||||
{
|
||||
tuneLinger = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
tuneLinger = [str intValue];
|
||||
}
|
||||
tuneRcvBuf = (int)[defs integerForKey: @"GSTcpRcvBuf"];
|
||||
tuneSndBuf = (int)[defs integerForKey: @"GSTcpSndBuf"];
|
||||
tuneReceive = (int)[defs integerForKey: @"GSTcpReceive"];
|
||||
tuneSendAll = [defs boolForKey: @"GSTcpSendAll"];
|
||||
tuneDelay = [defs boolForKey: @"GSTcpDelay"];
|
||||
}
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
static BOOL beenHere = NO;
|
||||
|
||||
if (NO == beenHere)
|
||||
{
|
||||
NSNotificationCenter *nc;
|
||||
NSUserDefaults *defs;
|
||||
|
||||
beenHere = YES;
|
||||
nc = [NSNotificationCenter defaultCenter];
|
||||
defs = [NSUserDefaults standardUserDefaults];
|
||||
[nc addObserver: self
|
||||
selector: @selector(defaultsChanged:)
|
||||
name: NSUserDefaultsDidChangeNotification
|
||||
object: defs];
|
||||
[self defaultsChanged: nil];
|
||||
}
|
||||
}
|
||||
|
||||
+ (int) delay
|
||||
{
|
||||
return tuneDelay; // Milliseconds to delay close
|
||||
}
|
||||
|
||||
+ (int) recvSize
|
||||
{
|
||||
if (tuneReceive > 0)
|
||||
{
|
||||
return tuneReceive; // Return receive buffer size
|
||||
}
|
||||
if (tuneRcvBuf > 0)
|
||||
{
|
||||
return tuneRcvBuf; // Return socket receive buffer size
|
||||
}
|
||||
return READ_SIZE; // Return hard-coded default
|
||||
}
|
||||
|
||||
+ (int) sendSize: (int)bytesToSend
|
||||
{
|
||||
if (YES == tuneSendAll)
|
||||
{
|
||||
return bytesToSend; // Try to send all in one go
|
||||
}
|
||||
if (tuneSndBuf > 0 && tuneSndBuf <= bytesToSend)
|
||||
{
|
||||
return tuneSndBuf; // Limit to socket send buffer
|
||||
}
|
||||
if (NETBUF_SIZE <= bytesToSend)
|
||||
{
|
||||
return NETBUF_SIZE; // Limit to hard coded default
|
||||
}
|
||||
return bytesToSend;
|
||||
}
|
||||
|
||||
+ (void) tune: (void*)handle with: (id)opts
|
||||
{
|
||||
int desc = (int)(intptr_t)handle;
|
||||
int value;
|
||||
id o;
|
||||
|
||||
#ifndef BROKEN_SO_REUSEADDR
|
||||
/*
|
||||
* Under decent systems, SO_REUSEADDR means that the port can be reused
|
||||
* immediately that this process exits. Under some it means
|
||||
* that multiple processes can serve the same port simultaneously.
|
||||
* We don't want that broken behavior!
|
||||
*/
|
||||
if (setsockopt(desc, SOL_SOCKET, SO_REUSEADDR, (char*)&value, sizeof(value))
|
||||
< 0)
|
||||
{
|
||||
NSDebugMLLog(@"GSTcpTune", @"setsockopt reuseaddr failed for %d", desc);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Enable tcp-level tracking of whether connection is alive.
|
||||
*/
|
||||
value = 1;
|
||||
if (setsockopt(desc, SOL_SOCKET, SO_KEEPALIVE, (char *)&value, sizeof(value))
|
||||
< 0)
|
||||
{
|
||||
NSDebugMLLog(@"GSTcpTune", @"setsockopt keepalive failed for %d", desc);
|
||||
}
|
||||
|
||||
|
||||
#define OPTS(X) ([opts isKindOfClass: [NSStream class]] \
|
||||
? [(NSStream*)opts propertyForKey: X] \
|
||||
: [(NSDictionary*)opts objectForKey: X])
|
||||
|
||||
o = OPTS(@"GSTcpLinger");
|
||||
value = (o ? [o intValue] : tuneLinger);
|
||||
if (value >= 0)
|
||||
{
|
||||
struct linger l;
|
||||
|
||||
l.l_onoff = 1;
|
||||
l.l_linger = tuneLinger;
|
||||
if (setsockopt(desc, SOL_SOCKET, SO_LINGER, (char *)&l, sizeof(l)) < 0)
|
||||
{
|
||||
NSLog(@"Failed to set GSTcpLinger for %d to %d: %@",
|
||||
desc, value, [NSError _last]);
|
||||
}
|
||||
else
|
||||
{
|
||||
NSDebugMLLog(@"GSTcpTune", @"Set GSTcpLinger for %d to %d",
|
||||
desc, value);
|
||||
}
|
||||
}
|
||||
|
||||
o = OPTS(@"GSTcpRcvBuf");
|
||||
value = (o ? [o intValue] : tuneRcvBuf);
|
||||
if (value > 0)
|
||||
{
|
||||
/* Set the receive buffer for the socket.
|
||||
*/
|
||||
if (setsockopt(desc, SOL_SOCKET, SO_RCVBUF,
|
||||
(char *)&value, sizeof(value)) < 0)
|
||||
{
|
||||
NSLog(@"Failed to set GSTcpRcvBuf for %d to %d: %@",
|
||||
desc, value, [NSError _last]);
|
||||
}
|
||||
else
|
||||
{
|
||||
NSDebugMLLog(@"GSTcpTune", @"Set GSTcpRcvBuf for %d to %d",
|
||||
desc, value);
|
||||
}
|
||||
}
|
||||
|
||||
o = OPTS(@"GSTcpSndBuf");
|
||||
value = (o ? [o intValue] : tuneSndBuf);
|
||||
if (value > 0)
|
||||
{
|
||||
/* Set the send buffer for the socket.
|
||||
*/
|
||||
if (setsockopt(desc, SOL_SOCKET, SO_SNDBUF,
|
||||
(char *)&value, sizeof(value)) < 0)
|
||||
{
|
||||
NSLog(@"Failed to set GSTcpSndBuf for %d to %d: %@",
|
||||
desc, value, [NSError _last]);
|
||||
}
|
||||
else
|
||||
{
|
||||
NSDebugMLLog(@"GSTcpTune", @"Set GSTcpSndBuf for %d to %d",
|
||||
desc, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
// Key to info dictionary for operation mode.
|
||||
static NSString* NotificationKey = @"NSFileHandleNotificationKey";
|
||||
|
||||
|
|
|
@ -72,6 +72,196 @@
|
|||
#define OPTLEN socklen_t
|
||||
#endif // _WIN32
|
||||
|
||||
// Maximum data in single I/O operation
|
||||
#define NETBUF_SIZE (1024 * 16)
|
||||
#define READ_SIZE NETBUF_SIZE*10
|
||||
|
||||
@implementation GSTcpTune
|
||||
|
||||
static int tuneDelay = 0;
|
||||
static int tuneLinger = -1;
|
||||
static int tuneReceive = 0;
|
||||
static BOOL tuneSendAll = NO;
|
||||
static int tuneRcvBuf = 0;
|
||||
static int tuneSndBuf = 0;
|
||||
|
||||
+ (void) defaultsChanged: (NSNotification*)n
|
||||
{
|
||||
NSUserDefaults *defs = (NSUserDefaults*)[n object];
|
||||
NSString *str;
|
||||
|
||||
if (nil == defs)
|
||||
{
|
||||
defs = [NSUserDefaults standardUserDefaults];
|
||||
}
|
||||
str = [defs stringForKey: @"GSTcpLinger"];
|
||||
if (nil == str)
|
||||
{
|
||||
tuneLinger = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
tuneLinger = [str intValue];
|
||||
}
|
||||
tuneRcvBuf = (int)[defs integerForKey: @"GSTcpRcvBuf"];
|
||||
tuneSndBuf = (int)[defs integerForKey: @"GSTcpSndBuf"];
|
||||
tuneReceive = (int)[defs integerForKey: @"GSTcpReceive"];
|
||||
tuneSendAll = [defs boolForKey: @"GSTcpSendAll"];
|
||||
tuneDelay = [defs boolForKey: @"GSTcpDelay"];
|
||||
}
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
static BOOL beenHere = NO;
|
||||
|
||||
if (NO == beenHere)
|
||||
{
|
||||
NSNotificationCenter *nc;
|
||||
NSUserDefaults *defs;
|
||||
|
||||
beenHere = YES;
|
||||
nc = [NSNotificationCenter defaultCenter];
|
||||
defs = [NSUserDefaults standardUserDefaults];
|
||||
[nc addObserver: self
|
||||
selector: @selector(defaultsChanged:)
|
||||
name: NSUserDefaultsDidChangeNotification
|
||||
object: defs];
|
||||
[self defaultsChanged: nil];
|
||||
}
|
||||
}
|
||||
|
||||
+ (int) delay
|
||||
{
|
||||
return tuneDelay; // Milliseconds to delay close
|
||||
}
|
||||
|
||||
+ (int) recvSize
|
||||
{
|
||||
if (tuneReceive > 0)
|
||||
{
|
||||
return tuneReceive; // Return receive buffer size
|
||||
}
|
||||
if (tuneRcvBuf > 0)
|
||||
{
|
||||
return tuneRcvBuf; // Return socket receive buffer size
|
||||
}
|
||||
return READ_SIZE; // Return hard-coded default
|
||||
}
|
||||
|
||||
+ (int) sendSize: (int)bytesToSend
|
||||
{
|
||||
if (YES == tuneSendAll)
|
||||
{
|
||||
return bytesToSend; // Try to send all in one go
|
||||
}
|
||||
if (tuneSndBuf > 0 && tuneSndBuf <= bytesToSend)
|
||||
{
|
||||
return tuneSndBuf; // Limit to socket send buffer
|
||||
}
|
||||
if (NETBUF_SIZE <= bytesToSend)
|
||||
{
|
||||
return NETBUF_SIZE; // Limit to hard coded default
|
||||
}
|
||||
return bytesToSend;
|
||||
}
|
||||
|
||||
+ (void) tune: (void*)handle with: (id)opts
|
||||
{
|
||||
int desc = (int)(intptr_t)handle;
|
||||
int value;
|
||||
id o;
|
||||
|
||||
#ifndef BROKEN_SO_REUSEADDR
|
||||
/*
|
||||
* Under decent systems, SO_REUSEADDR means that the port can be reused
|
||||
* immediately that this process exits. Under some it means
|
||||
* that multiple processes can serve the same port simultaneously.
|
||||
* We don't want that broken behavior!
|
||||
*/
|
||||
if (setsockopt(desc, SOL_SOCKET, SO_REUSEADDR, (char*)&value, sizeof(value))
|
||||
< 0)
|
||||
{
|
||||
NSDebugMLLog(@"GSTcpTune", @"setsockopt reuseaddr failed for %d", desc);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Enable tcp-level tracking of whether connection is alive.
|
||||
*/
|
||||
value = 1;
|
||||
if (setsockopt(desc, SOL_SOCKET, SO_KEEPALIVE, (char *)&value, sizeof(value))
|
||||
< 0)
|
||||
{
|
||||
NSDebugMLLog(@"GSTcpTune", @"setsockopt keepalive failed for %d", desc);
|
||||
}
|
||||
|
||||
|
||||
#define OPTS(X) ([opts isKindOfClass: [NSStream class]] \
|
||||
? [(NSStream*)opts propertyForKey: X] \
|
||||
: [(NSDictionary*)opts objectForKey: X])
|
||||
|
||||
o = OPTS(@"GSTcpLinger");
|
||||
value = (o ? [o intValue] : tuneLinger);
|
||||
if (value >= 0)
|
||||
{
|
||||
struct linger l;
|
||||
|
||||
l.l_onoff = 1;
|
||||
l.l_linger = tuneLinger;
|
||||
if (setsockopt(desc, SOL_SOCKET, SO_LINGER, (char *)&l, sizeof(l)) < 0)
|
||||
{
|
||||
NSLog(@"Failed to set GSTcpLinger for %d to %d: %@",
|
||||
desc, value, [NSError _last]);
|
||||
}
|
||||
else
|
||||
{
|
||||
NSDebugMLLog(@"GSTcpTune", @"Set GSTcpLinger for %d to %d",
|
||||
desc, value);
|
||||
}
|
||||
}
|
||||
|
||||
o = OPTS(@"GSTcpRcvBuf");
|
||||
value = (o ? [o intValue] : tuneRcvBuf);
|
||||
if (value > 0)
|
||||
{
|
||||
/* Set the receive buffer for the socket.
|
||||
*/
|
||||
if (setsockopt(desc, SOL_SOCKET, SO_RCVBUF,
|
||||
(char *)&value, sizeof(value)) < 0)
|
||||
{
|
||||
NSLog(@"Failed to set GSTcpRcvBuf for %d to %d: %@",
|
||||
desc, value, [NSError _last]);
|
||||
}
|
||||
else
|
||||
{
|
||||
NSDebugMLLog(@"GSTcpTune", @"Set GSTcpRcvBuf for %d to %d",
|
||||
desc, value);
|
||||
}
|
||||
}
|
||||
|
||||
o = OPTS(@"GSTcpSndBuf");
|
||||
value = (o ? [o intValue] : tuneSndBuf);
|
||||
if (value > 0)
|
||||
{
|
||||
/* Set the send buffer for the socket.
|
||||
*/
|
||||
if (setsockopt(desc, SOL_SOCKET, SO_SNDBUF,
|
||||
(char *)&value, sizeof(value)) < 0)
|
||||
{
|
||||
NSLog(@"Failed to set GSTcpSndBuf for %d to %d: %@",
|
||||
desc, value, [NSError _last]);
|
||||
}
|
||||
else
|
||||
{
|
||||
NSDebugMLLog(@"GSTcpTune", @"Set GSTcpSndBuf for %d to %d",
|
||||
desc, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
unsigned
|
||||
GSPrivateSockaddrLength(struct sockaddr *addr)
|
||||
{
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#import "Foundation/NSHost.h"
|
||||
#import "Foundation/NSByteOrder.h"
|
||||
#import "Foundation/NSProcessInfo.h"
|
||||
#import "Foundation/NSStream.h"
|
||||
#import "Foundation/NSUserDefaults.h"
|
||||
#import "Foundation/NSDebug.h"
|
||||
|
||||
|
|
Loading…
Reference in a new issue