mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 00:41:02 +00:00
Stream debug and event handling improvements
This commit is contained in:
parent
3bc0a58531
commit
46e7064393
5 changed files with 108 additions and 52 deletions
16
ChangeLog
16
ChangeLog
|
@ -1,8 +1,20 @@
|
|||
2024-01-08 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
2024-01-30 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/GSFileHandle.m:
|
||||
* Source/GSPrivate.h:
|
||||
* Source/GSSocketStream.m:
|
||||
* Source/GSStream.m:
|
||||
* Source/unix/GSRunLoopCtxt.m:
|
||||
Make GSTcpTune options available to streams as well as file handles.
|
||||
Improve debug logging for streasm operations.
|
||||
Schedule streams in run loop on conclusion of TLS handshake (so we get
|
||||
events telling us to start again after a blocked write).
|
||||
|
||||
2024-01-29 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSOperation.m: patch for issue #366 by Larry Campbell.
|
||||
|
||||
2024-01-08 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
2024-01-28 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSJSONSerialization.m: Fix for issue #365 ... don't try to
|
||||
create a string ending with the first half of a unicode surrogate pair.
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#import "Foundation/NSHost.h"
|
||||
#import "Foundation/NSByteOrder.h"
|
||||
#import "Foundation/NSProcessInfo.h"
|
||||
#import "Foundation/NSStream.h"
|
||||
#import "Foundation/NSUserDefaults.h"
|
||||
#import "GSPrivate.h"
|
||||
#import "GSNetwork.h"
|
||||
|
@ -100,21 +101,14 @@ static GSFileHandle *fh_stdin = nil;
|
|||
static GSFileHandle *fh_stdout = nil;
|
||||
static GSFileHandle *fh_stderr = nil;
|
||||
|
||||
@interface GSTcpTune : NSObject
|
||||
- (int) delay;
|
||||
- (int) recvSize;
|
||||
- (int) sendSize: (int)bytesToSend;
|
||||
- (void) tune: (void*)handle;
|
||||
@end
|
||||
|
||||
@implementation GSTcpTune
|
||||
|
||||
static int tuneDelay = 0;
|
||||
static int tuneLinger = -1;
|
||||
static int tuneReceive = 0;
|
||||
static BOOL tuneSendAll = NO;
|
||||
static int tuneRBuf = 0;
|
||||
static int tuneSBuf = 0;
|
||||
static int tuneRcvBuf = 0;
|
||||
static int tuneSndBuf = 0;
|
||||
|
||||
+ (void) defaultsChanged: (NSNotification*)n
|
||||
{
|
||||
|
@ -134,8 +128,8 @@ static int tuneSBuf = 0;
|
|||
{
|
||||
tuneLinger = [str intValue];
|
||||
}
|
||||
tuneRBuf = (int)[defs integerForKey: @"GSTcpRcvBuf"];
|
||||
tuneSBuf = (int)[defs integerForKey: @"GSTcpSndBuf"];
|
||||
tuneRcvBuf = (int)[defs integerForKey: @"GSTcpRcvBuf"];
|
||||
tuneSndBuf = (int)[defs integerForKey: @"GSTcpSndBuf"];
|
||||
tuneReceive = (int)[defs integerForKey: @"GSTcpReceive"];
|
||||
tuneSendAll = [defs boolForKey: @"GSTcpSendAll"];
|
||||
tuneDelay = [defs boolForKey: @"GSTcpDelay"];
|
||||
|
@ -161,33 +155,33 @@ static int tuneSBuf = 0;
|
|||
}
|
||||
}
|
||||
|
||||
- (int) delay
|
||||
+ (int) delay
|
||||
{
|
||||
return tuneDelay; // Milliseconds to delay close
|
||||
}
|
||||
|
||||
- (int) recvSize
|
||||
+ (int) recvSize
|
||||
{
|
||||
if (tuneReceive > 0)
|
||||
{
|
||||
return tuneReceive; // Return receive buffer size
|
||||
}
|
||||
if (tuneRBuf > 0)
|
||||
if (tuneRcvBuf > 0)
|
||||
{
|
||||
return tuneRBuf; // Return socket receive buffer size
|
||||
return tuneRcvBuf; // Return socket receive buffer size
|
||||
}
|
||||
return READ_SIZE; // Return hard-coded default
|
||||
}
|
||||
|
||||
- (int) sendSize: (int)bytesToSend
|
||||
+ (int) sendSize: (int)bytesToSend
|
||||
{
|
||||
if (YES == tuneSendAll)
|
||||
{
|
||||
return bytesToSend; // Try to send all in one go
|
||||
}
|
||||
if (tuneSBuf > 0 && tuneSBuf <= bytesToSend)
|
||||
if (tuneSndBuf > 0 && tuneSndBuf <= bytesToSend)
|
||||
{
|
||||
return tuneSBuf; // Limit to socket send buffer
|
||||
return tuneSndBuf; // Limit to socket send buffer
|
||||
}
|
||||
if (NETBUF_SIZE <= bytesToSend)
|
||||
{
|
||||
|
@ -196,10 +190,25 @@ static int tuneSBuf = 0;
|
|||
return bytesToSend;
|
||||
}
|
||||
|
||||
- (void) tune: (void*)handle
|
||||
+ (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.
|
||||
|
@ -208,10 +217,17 @@ static int tuneSBuf = 0;
|
|||
if (setsockopt(desc, SOL_SOCKET, SO_KEEPALIVE, (char *)&value, sizeof(value))
|
||||
< 0)
|
||||
{
|
||||
NSDebugMLLog(@"GSTcpTune", @"setsockopt keepalive failed");
|
||||
NSDebugMLLog(@"GSTcpTune", @"setsockopt keepalive failed for %d", desc);
|
||||
}
|
||||
|
||||
if (tuneLinger >= 0)
|
||||
|
||||
#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;
|
||||
|
||||
|
@ -219,40 +235,55 @@ static int tuneSBuf = 0;
|
|||
l.l_linger = tuneLinger;
|
||||
if (setsockopt(desc, SOL_SOCKET, SO_LINGER, (char *)&l, sizeof(l)) < 0)
|
||||
{
|
||||
NSLog(@"Failed to set GSTcpLinger %d: %@",
|
||||
tuneLinger, [NSError _last]);
|
||||
NSLog(@"Failed to set GSTcpLinger for %d to %d: %@",
|
||||
desc, value, [NSError _last]);
|
||||
}
|
||||
else
|
||||
{
|
||||
NSDebugMLLog(@"GSTcpTune", @"Set GSTcpLinger for %d to %d",
|
||||
desc, value);
|
||||
}
|
||||
}
|
||||
|
||||
if (tuneRBuf > 0)
|
||||
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 *)&tuneRBuf, sizeof(tuneRBuf)) < 0)
|
||||
(char *)&value, sizeof(value)) < 0)
|
||||
{
|
||||
NSLog(@"Failed to set GSTcpRcvBuf %d: %@", tuneRBuf, [NSError _last]);
|
||||
NSLog(@"Failed to set GSTcpRcvBuf for %d to %d: %@",
|
||||
desc, value, [NSError _last]);
|
||||
}
|
||||
else
|
||||
{
|
||||
NSDebugMLLog(@"GSTcpTune", @"Set GSTcpRcvBuf %d", tuneRBuf);
|
||||
NSDebugMLLog(@"GSTcpTune", @"Set GSTcpRcvBuf for %d to %d",
|
||||
desc, value);
|
||||
}
|
||||
}
|
||||
if (tuneSBuf > 0)
|
||||
|
||||
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 *)&tuneSBuf, sizeof(tuneSBuf)) < 0)
|
||||
(char *)&value, sizeof(value)) < 0)
|
||||
{
|
||||
NSLog(@"Failed to set GSTcpSndBuf %d: %@", tuneSBuf, [NSError _last]);
|
||||
NSLog(@"Failed to set GSTcpSndBuf for %d to %d: %@",
|
||||
desc, value, [NSError _last]);
|
||||
}
|
||||
else
|
||||
{
|
||||
NSDebugMLLog(@"GSTcpTune", @"Set GSTcpSndBuf %d", tuneSBuf);
|
||||
NSDebugMLLog(@"GSTcpTune", @"Set GSTcpSndBuf for %d to %d",
|
||||
desc, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
// Key to info dictionary for operation mode.
|
||||
|
@ -265,14 +296,9 @@ static NSString* NotificationKey = @"NSFileHandleNotificationKey";
|
|||
|
||||
@implementation GSFileHandle
|
||||
|
||||
static GSTcpTune *tune = nil;
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (nil == tune)
|
||||
{
|
||||
tune = [GSTcpTune new];
|
||||
}
|
||||
[GSTcpTune class];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -949,7 +975,7 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
|
|||
return nil;
|
||||
}
|
||||
|
||||
[tune tune: (void*)(intptr_t)net];
|
||||
[GSTcpTune tune: (void*)(intptr_t)net with: nil];
|
||||
|
||||
if (lhost != nil)
|
||||
{
|
||||
|
@ -1431,7 +1457,7 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
|
|||
|
||||
- (NSData*) availableData
|
||||
{
|
||||
int rmax = [tune recvSize];
|
||||
int rmax = [GSTcpTune recvSize];
|
||||
char buf[rmax];
|
||||
NSMutableData* d;
|
||||
int len;
|
||||
|
@ -1501,7 +1527,7 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
|
|||
|
||||
- (NSData*) readDataToEndOfFile
|
||||
{
|
||||
int rmax = [tune recvSize];
|
||||
int rmax = [GSTcpTune recvSize];
|
||||
char buf[rmax];
|
||||
NSMutableData* d;
|
||||
int len;
|
||||
|
@ -1529,7 +1555,7 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
|
|||
{
|
||||
NSMutableData *d;
|
||||
int got;
|
||||
int rmax = [tune recvSize];
|
||||
int rmax = [GSTcpTune recvSize];
|
||||
char buf[rmax];
|
||||
|
||||
[self checkRead];
|
||||
|
@ -1577,7 +1603,7 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
|
|||
{
|
||||
int toWrite = len - pos;
|
||||
|
||||
toWrite = [tune sendSize: toWrite];
|
||||
toWrite = [GSTcpTune sendSize: toWrite];
|
||||
rval = [self write: (char*)ptr+pos length: toWrite];
|
||||
if (rval < 0)
|
||||
{
|
||||
|
@ -1807,7 +1833,7 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
|
|||
#endif
|
||||
if (YES == isSocket)
|
||||
{
|
||||
int milli = [tune delay];
|
||||
int milli = [GSTcpTune delay];
|
||||
|
||||
shutdown(descriptor, SHUT_WR);
|
||||
if (milli > 0)
|
||||
|
@ -2168,7 +2194,7 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
|
|||
struct sockaddr sin;
|
||||
unsigned int size = sizeof(sin);
|
||||
|
||||
[tune tune: (void*)(intptr_t)desc];
|
||||
[GSTcpTune tune: (void*)(intptr_t)desc with: nil];
|
||||
|
||||
h = [[[self class] alloc] initWithFileDescriptor: desc
|
||||
closeOnDealloc: YES];
|
||||
|
@ -2192,7 +2218,7 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
|
|||
NSMutableData *item;
|
||||
int length;
|
||||
int received = 0;
|
||||
int rmax = [tune recvSize];
|
||||
int rmax = [GSTcpTune recvSize];
|
||||
char buf[rmax];
|
||||
|
||||
item = [readInfo objectForKey: NSFileHandleNotificationDataItem];
|
||||
|
|
|
@ -546,6 +546,15 @@ GSPrivateUnloadModule(FILE *errorStream,
|
|||
- (void) setFrame: (id)aFrame;
|
||||
@end
|
||||
|
||||
/* For tuning socket connections
|
||||
*/
|
||||
@interface GSTcpTune : NSObject
|
||||
+ (int) delay;
|
||||
+ (int) recvSize;
|
||||
+ (int) sendSize: (int)bytesToSend;
|
||||
+ (void) tune: (void*)handle with: (id)opts;
|
||||
@end
|
||||
|
||||
BOOL
|
||||
GSPrivateIsCollectable(const void *ptr) GS_ATTRIB_PRIVATE;
|
||||
|
||||
|
|
|
@ -451,14 +451,14 @@ GSTLSPush(gnutls_transport_ptr_t handle, const void *buffer, size_t len)
|
|||
{
|
||||
e = [[[tls ostream] streamError] code];
|
||||
NSDebugFLLog(@"NSStream",
|
||||
@"GSTLSPush write for %p error %d (%s)",
|
||||
@"GSTLSPush write for %@ error %d (%s)",
|
||||
[tls ostream], e, strerror(e));
|
||||
}
|
||||
else
|
||||
{
|
||||
e = EAGAIN; // Tell GNUTLS this would block.
|
||||
NSDebugFLLog(@"NSStream",
|
||||
@"GSTLSPush write for %p of %lu would block",
|
||||
@"GSTLSPush write for %@ of %lu would block",
|
||||
[tls ostream], (unsigned long)len);
|
||||
}
|
||||
#if HAVE_GNUTLS_TRANSPORT_SET_ERRNO
|
||||
|
@ -470,12 +470,12 @@ GSTLSPush(gnutls_transport_ptr_t handle, const void *buffer, size_t len)
|
|||
}
|
||||
if (len != result)
|
||||
{
|
||||
NSDebugFLLog(@"NSStream", @"GSTLSPush write for %p of %ld (tried %lu)",
|
||||
NSDebugFLLog(@"NSStream", @"GSTLSPush write for %@ of %ld (tried %lu)",
|
||||
[tls ostream], (long)result, (unsigned long)len);
|
||||
}
|
||||
else
|
||||
{
|
||||
NSDebugFLLog(@"NSStream", @"GSTLSPush write for %p of %ld success",
|
||||
NSDebugFLLog(@"NSStream", @"GSTLSPush write for %@ of %ld success",
|
||||
[tls ostream], (long)result);
|
||||
}
|
||||
return result;
|
||||
|
@ -768,6 +768,7 @@ static NSArray *keys = nil;
|
|||
{
|
||||
[istream _resetEvents: NSStreamEventOpenCompleted];
|
||||
[istream _sendEvent: NSStreamEventOpenCompleted];
|
||||
[istream _schedule];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -780,6 +781,7 @@ static NSArray *keys = nil;
|
|||
| NSStreamEventHasSpaceAvailable];
|
||||
[ostream _sendEvent: NSStreamEventOpenCompleted];
|
||||
[ostream _sendEvent: NSStreamEventHasSpaceAvailable];
|
||||
[ostream _schedule];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1853,6 +1855,7 @@ setNonBlocking(SOCKET fd)
|
|||
}
|
||||
else
|
||||
{
|
||||
[GSTcpTune tune: (void*)(intptr_t)s with: self];
|
||||
[self _setSock: s];
|
||||
[_sibling _setSock: s];
|
||||
}
|
||||
|
@ -2374,6 +2377,7 @@ setNonBlocking(SOCKET fd)
|
|||
}
|
||||
else
|
||||
{
|
||||
[GSTcpTune tune: (void*)(intptr_t)s with: self];
|
||||
[self _setSock: s];
|
||||
[_sibling _setSock: s];
|
||||
}
|
||||
|
@ -2779,6 +2783,7 @@ setNonBlocking(SOCKET fd)
|
|||
}
|
||||
else
|
||||
{
|
||||
[GSTcpTune tune: (void*)(intptr_t)s with: self];
|
||||
[(GSSocketStream*)self _setSock: s];
|
||||
}
|
||||
|
||||
|
|
|
@ -255,6 +255,7 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt)
|
|||
unsigned count;
|
||||
unsigned int i;
|
||||
BOOL immediate = NO;
|
||||
BOOL debug = GSDebugSet(@"NSRunLoop");
|
||||
|
||||
i = GSIArrayCount(watchers);
|
||||
|
||||
|
@ -319,18 +320,21 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt)
|
|||
fd = (int)(intptr_t)info->data;
|
||||
setPollfd(fd, POLLPRI, self);
|
||||
NSMapInsert(_efdMap, (void*)(intptr_t)fd, info);
|
||||
if (debug) NSLog(@"listening for EDESC %d", fd);
|
||||
break;
|
||||
|
||||
case ET_RDESC:
|
||||
fd = (int)(intptr_t)info->data;
|
||||
setPollfd(fd, POLLIN, self);
|
||||
NSMapInsert(_rfdMap, (void*)(intptr_t)fd, info);
|
||||
if (debug) NSLog(@"listening for RDESC %d", fd);
|
||||
break;
|
||||
|
||||
case ET_WDESC:
|
||||
fd = (int)(intptr_t)info->data;
|
||||
setPollfd(fd, POLLOUT, self);
|
||||
NSMapInsert(_wfdMap, (void*)(intptr_t)fd, info);
|
||||
if (debug) NSLog(@"listening for WDESC %d", fd);
|
||||
break;
|
||||
|
||||
case ET_TRIGGER:
|
||||
|
@ -353,7 +357,7 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt)
|
|||
port_fd_array = malloc(sizeof(NSInteger)*port_fd_size);
|
||||
[port getFds: port_fd_array count: &port_fd_count];
|
||||
}
|
||||
NSDebugMLLog(@"NSRunLoop",
|
||||
if (debug) NSLog(
|
||||
@"listening to %"PRIdPTR" port handles\n", port_fd_count);
|
||||
while (port_fd_count--)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue