Improive NSConnection debug, work on NSMessagePort for mingw32

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@21975 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
CaS 2005-11-09 16:30:57 +00:00
parent d1867e1813
commit 2dac0159d0
3 changed files with 233 additions and 190 deletions

View file

@ -674,7 +674,7 @@ static NSLock *cached_proxies_gate = nil;
- (void) dealloc - (void) dealloc
{ {
if (debug_connection) if (debug_connection)
NSLog(@"deallocating 0x%x", (gsaddr)self); NSLog(@"deallocating %@", self);
[super dealloc]; [super dealloc];
} }
@ -686,6 +686,12 @@ static NSLock *cached_proxies_gate = nil;
return GS_GC_UNHIDE(_delegate); return GS_GC_UNHIDE(_delegate);
} }
- (NSString*) description
{
return [NSString stringWithFormat: @"%@ recv: 0x%x send 0x%x",
[super description], (gsaddr)[self receivePort], (gsaddr)[self sendPort]];
}
/** /**
* Sets the NSConnection configuration so that multiple threads may * Sets the NSConnection configuration so that multiple threads may
* use the connection to send requests to the remote connection.<br /> * use the connection to send requests to the remote connection.<br />
@ -806,8 +812,8 @@ static NSLock *cached_proxies_gate = nil;
self = RETAIN(conn); self = RETAIN(conn);
if (debug_connection > 2) if (debug_connection > 2)
{ {
NSLog(@"Found existing connection (0x%x) for \n\t%@\n\t%@", NSLog(@"Found existing connection (%@) for \n\t%@\n\t%@",
(gsaddr)conn, r, s); conn, r, s);
} }
return self; return self;
} }
@ -820,8 +826,8 @@ static NSLock *cached_proxies_gate = nil;
if (debug_connection) if (debug_connection)
{ {
NSLog(@"Initialising new connection with parent 0x%x, 0x%x\n\t%@\n\t%@", NSLog(@"Initialising new connection with parent %@, %@\n\t%@\n\t%@",
(gsaddr)parent, (gsaddr)self, r, s); parent, self, r, s);
} }
M_LOCK(connection_table_gate); M_LOCK(connection_table_gate);
@ -1042,8 +1048,7 @@ static NSLock *cached_proxies_gate = nil;
if (debug_connection) if (debug_connection)
{ {
NSLog(@"Invalidating connection 0x%x\n\t%@\n\t%@", NSLog(@"Invalidating connection %@", self);
(gsaddr)self, _receivePort, _sendPort);
} }
/* /*
* We need to notify any watchers of our death - but if we are already * We need to notify any watchers of our death - but if we are already
@ -1619,7 +1624,7 @@ static NSLock *cached_proxies_gate = nil;
CREATE_AUTORELEASE_POOL(arp); CREATE_AUTORELEASE_POOL(arp);
if (debug_connection) if (debug_connection)
NSLog(@"finalising 0x%x", (gsaddr)self); NSLog(@"finalising %@", self);
[self invalidate]; [self invalidate];
@ -2125,7 +2130,7 @@ static void retEncoder (DOContext *ctxt)
} }
if (debug_connection > 4) if (debug_connection > 4)
{ {
NSLog(@" connection is %x:%x", conn, [NSThread currentThread]); NSLog(@" connection is %@", conn);
} }
if (conn->_authenticateIn == YES if (conn->_authenticateIn == YES
@ -2221,19 +2226,19 @@ static void retEncoder (DOContext *ctxt)
node = GSIMapNodeForKey(conn->_replyMap, (GSIMapKey)sequence); node = GSIMapNodeForKey(conn->_replyMap, (GSIMapKey)sequence);
if (node == 0) if (node == 0)
{ {
NSDebugMLLog(@"NSConnection", @"Ignoring reply RMC %d on %x", NSDebugMLLog(@"NSConnection", @"Ignoring reply RMC %d on %@",
sequence, conn); sequence, conn);
[self _doneInRmc: rmc]; [self _doneInRmc: rmc];
} }
else if (node->value.obj == dummyObject) else if (node->value.obj == dummyObject)
{ {
NSDebugMLLog(@"NSConnection", @"Saving reply RMC %d on %x", NSDebugMLLog(@"NSConnection", @"Saving reply RMC %d on %@",
sequence, conn); sequence, conn);
node->value.obj = rmc; node->value.obj = rmc;
} }
else else
{ {
NSDebugMLLog(@"NSConnection", @"Replace reply RMC %d on %x", NSDebugMLLog(@"NSConnection", @"Replace reply RMC %d on %@",
sequence, conn); sequence, conn);
[self _doneInRmc: node->value.obj]; [self _doneInRmc: node->value.obj];
node->value.obj = rmc; node->value.obj = rmc;
@ -2415,7 +2420,7 @@ static void callEncoder (DOContext *ctxt)
if (debug_connection > 1) if (debug_connection > 1)
{ {
NSLog(@"Handling message from 0x%x", (gsaddr)self); NSLog(@"Handling message from %@", (gsaddr)self);
} }
_reqInCount++; /* Handling an incoming request. */ _reqInCount++; /* Handling an incoming request. */
@ -2434,8 +2439,7 @@ static void callEncoder (DOContext *ctxt)
NS_HANDLER NS_HANDLER
{ {
if (debug_connection > 3) if (debug_connection > 3)
NSLog(@"forwarding exception for (0x%x) - %@", NSLog(@"forwarding exception for (%@) - %@", self, localException);
(gsaddr)self, localException);
/* Send the exception back to the client. */ /* Send the exception back to the client. */
if (_isValid == YES) if (_isValid == YES)
@ -2520,8 +2524,8 @@ static void callEncoder (DOContext *ctxt)
if (prox != nil) if (prox != nil)
{ {
if (debug_connection > 3) if (debug_connection > 3)
NSLog(@"releasing object with target (0x%x) on (0x%x) counter %d", NSLog(@"releasing object with target (0x%x) on (%@) counter %d",
target, (gsaddr)self, ((ProxyStruct*)prox)->_counter); target, self, ((ProxyStruct*)prox)->_counter);
#if 1 #if 1
// FIXME thread safety // FIXME thread safety
if (--(((ProxyStruct*)prox)->_counter) == 0) if (--(((ProxyStruct*)prox)->_counter) == 0)
@ -2533,8 +2537,8 @@ static void callEncoder (DOContext *ctxt)
#endif #endif
} }
else if (debug_connection > 3) else if (debug_connection > 3)
NSLog(@"releasing object with target (0x%x) on (0x%x) - nothing to do", NSLog(@"releasing object with target (0x%x) on (%@) - nothing to do",
target, (gsaddr)self); target, self);
} }
[self _doneInRmc: rmc]; [self _doneInRmc: rmc];
} }
@ -2556,8 +2560,8 @@ static void callEncoder (DOContext *ctxt)
[self _doneInRmc: rmc]; [self _doneInRmc: rmc];
if (debug_connection > 3) if (debug_connection > 3)
NSLog(@"looking to retain local object with target (0x%x) on (0x%x)", NSLog(@"looking to retain local object with target (0x%x) on (%@)",
target, (gsaddr)self); target, self);
M_LOCK(_proxiesGate); M_LOCK(_proxiesGate);
local = [self locateLocalTarget: target]; local = [self locateLocalTarget: target];
@ -2673,8 +2677,8 @@ static void callEncoder (DOContext *ctxt)
NS_DURING NS_DURING
{ {
if (debug_connection > 5) if (debug_connection > 5)
NSLog(@"Waiting for reply sequence %d on %x:%x", NSLog(@"Waiting for reply sequence %d on %@",
sn, self, [NSThread currentThread]); sn, self);
M_LOCK(_queueGate); isLocked = YES; M_LOCK(_queueGate); isLocked = YES;
while (_isValid == YES while (_isValid == YES
&& (node = GSIMapNodeForKey(_replyMap, (GSIMapKey)sn)) != 0 && (node = GSIMapNodeForKey(_replyMap, (GSIMapKey)sn)) != 0
@ -2992,7 +2996,7 @@ static void callEncoder (DOContext *ctxt)
} }
if (debug_connection > 5) if (debug_connection > 5)
NSLog(@"Sending %@ on %x", stringFromMsgType(msgid), self); NSLog(@"Sending %@ on %@", stringFromMsgType(msgid), self);
limit = [dateClass dateWithTimeIntervalSinceNow: _requestTimeout]; limit = [dateClass dateWithTimeIntervalSinceNow: _requestTimeout];
sent = [_sendPort sendBeforeDate: limit sent = [_sendPort sendBeforeDate: limit
@ -3086,7 +3090,7 @@ static void callEncoder (DOContext *ctxt)
if (debug_connection > 2) if (debug_connection > 2)
NSLog(@"add local object (0x%x) target (0x%x) " NSLog(@"add local object (0x%x) target (0x%x) "
@"to connection (0x%x)", (gsaddr)object, target, (gsaddr) self); @"to connection (%@)", (gsaddr)object, target, self);
M_UNLOCK(_proxiesGate); M_UNLOCK(_proxiesGate);
} }
@ -3181,8 +3185,7 @@ static void callEncoder (DOContext *ctxt)
if (debug_connection > 2) if (debug_connection > 2)
NSLog(@"removed local object (0x%x) target (0x%x) " NSLog(@"removed local object (0x%x) target (0x%x) "
@"from connection (0x%x) (ref %d)", @"from connection (%@) (ref %d)", (gsaddr)anObj, target, self, val);
(gsaddr)anObj, target, (gsaddr)self, val);
} }
M_UNLOCK(_proxiesGate); M_UNLOCK(_proxiesGate);
} }
@ -3210,8 +3213,8 @@ static void callEncoder (DOContext *ctxt)
{ {
[op encodeValueOfObjCType: @encode(unsigned) at: &target]; [op encodeValueOfObjCType: @encode(unsigned) at: &target];
if (debug_connection > 3) if (debug_connection > 3)
NSLog(@"sending release for target (0x%x) on (0x%x)", NSLog(@"sending release for target (0x%x) on (%@)",
target, (gsaddr)self); target, self);
} }
[self _sendOutRmc: op type: PROXY_RELEASE]; [self _sendOutRmc: op type: PROXY_RELEASE];
@ -3550,7 +3553,7 @@ static void callEncoder (DOContext *ctxt)
if (debug_connection) if (debug_connection)
{ {
NSLog(@"Received port invalidation notification for " NSLog(@"Received port invalidation notification for "
@"connection 0x%x\n\t%@", (gsaddr)self, port); @"connection %@\n\t%@", self, port);
} }
/* We shouldn't be getting any port invalidation notifications, /* We shouldn't be getting any port invalidation notifications,

View file

@ -179,7 +179,7 @@ static void clean_up_names(void)
h = CreateFileW( h = CreateFileW(
UNISTR(p), UNISTR(p),
GENERIC_WRITE, GENERIC_WRITE,
FILE_SHARE_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
(LPSECURITY_ATTRIBUTES)0, (LPSECURITY_ATTRIBUTES)0,
OPEN_EXISTING, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL,

View file

@ -106,24 +106,18 @@ typedef struct {
BOOL listener; BOOL listener;
NSMutableData *wData; /* Data object being written. */ NSMutableData *wData; /* Data object being written. */
unsigned wLength; /* Amount written so far. */ DWORD wLength; /* Amount written so far. */
NSMutableArray *wMsgs; /* Message in progress. */ NSMutableArray *wMsgs; /* Message in progress. */
NSMutableData *rData; /* Buffer for incoming data */ NSMutableData *rData; /* Buffer for incoming data */
gsu32 rLength; /* Amount read so far. */ DWORD rLength; /* Amount read so far. */
gsu32 rWant; /* Amount desired. */ DWORD rWant; /* Amount desired. */
NSMessagePort *rPort; /* Port of message being read. */ NSMessagePort *rPort; /* Port of message being read. */
NSMutableArray *rItems; /* Message in progress. */ NSMutableArray *rItems; /* Message in progress. */
GSPortItemType rType; /* Type of data being read. */
gsu32 rId; /* Id of incoming message. */ gsu32 rId; /* Id of incoming message. */
unsigned nItems; /* Number of items to be read. */ unsigned nItems; /* Number of items to be read. */
} internal; } internal;
#define PORT(X) ((internal*)((NSMessagePort*)X)->_internal) #define PORT(X) ((internal*)((NSMessagePort*)X)->_internal)
/*
* Largest chunk of data possible in DO
*/
static gsu32 maxDataLength = 10 * 1024 * 1024;
@implementation NSMessagePort @implementation NSMessagePort
static NSRecursiveLock *messagePortLock = nil; static NSRecursiveLock *messagePortLock = nil;
@ -194,7 +188,9 @@ static unsigned wordAlign;
toRunLoop: (NSRunLoop*)aLoop toRunLoop: (NSRunLoop*)aLoop
forMode: (NSString*)aMode forMode: (NSString*)aMode
{ {
[aLoop addEvent: (void*)(gsaddr)PORT(self)->handle NSDebugMLLog(@"NSMessagePort", @"%@ add to 0x%x in mode %@",
self, aLoop, aMode);
[aLoop addEvent: (void*)(gsaddr)PORT(self)->event
type: ET_HANDLE type: ET_HANDLE
watcher: (id<RunLoopEvents>)self watcher: (id<RunLoopEvents>)self
forMode: aMode]; forMode: aMode];
@ -338,7 +334,7 @@ static unsigned wordAlign;
NSMessagePort *p; NSMessagePort *p;
M_LOCK(messagePortLock); M_LOCK(messagePortLock);
p = RETAIN((NSMessagePort*)NSMapGet(recvPorts, (void*)name)); p = RETAIN((NSMessagePort*)NSMapGet(sendPorts, (void*)name));
if (p == nil) if (p == nil)
{ {
internal *this; internal *this;
@ -361,10 +357,10 @@ static unsigned wordAlign;
this->handle = CreateFileW( this->handle = CreateFileW(
UNISTR(path), UNISTR(path),
GENERIC_WRITE, GENERIC_WRITE,
FILE_SHARE_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
(LPSECURITY_ATTRIBUTES)0, (LPSECURITY_ATTRIBUTES)0,
OPEN_EXISTING, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
(HANDLE)0); (HANDLE)0);
if (this->handle == INVALID_HANDLE_VALUE) if (this->handle == INVALID_HANDLE_VALUE)
{ {
@ -465,7 +461,6 @@ static unsigned wordAlign;
if (this->rWant > 0) if (this->rWant > 0)
{ {
/* /*
* Have we read something? * Have we read something?
*/ */
@ -474,8 +469,62 @@ static unsigned wordAlign;
&this->ov, &this->ov,
&this->size, &this->size,
TRUE) == 0) TRUE) == 0)
{
errno = GetLastError();
/*
* Our overlapped read attempt should fail ... because mailslots
* insist we read an entire message in one go, and we asked it
* to read zero bytes. The error we are expecting is
* ERROR_INSUFFICIENT_BUFFER ... indicating that there is a
* message to be read ... so we can ask for its size and read it
* synchronously.
*/
if (errno == ERROR_INSUFFICIENT_BUFFER)
{
if (GetMailslotInfo(
this->handle,
0,
&this->rWant,
0,
0) == 0)
{
NSLog(@"unable to get info from mailslot '%@' - %s",
this->name, GSLastErrorStr(errno));
[self invalidate];
return;
}
else
{
[this->rData setLength: this->rWant];
if (ReadFile(this->handle,
[this->rData mutableBytes], // Store results here
this->rWant,
&this->size,
NULL) == 0)
{
NSLog(@"unable to read from mailslot '%@' - %s",
this->name, GSLastErrorStr(errno));
[self invalidate];
return;
}
if (this->size != this->rWant)
{
NSLog(@"only read %d of %d bytes from mailslot '%@' - %s",
this->size, this->rWant, this->name,
GSLastErrorStr(errno));
[self invalidate];
return;
}
this->rLength += this->size;
this->size = 0;
}
}
else
{ {
NSLog(@"GetOverlappedResult failed ...%s", GSLastErrorStr(errno)); NSLog(@"GetOverlappedResult failed ...%s", GSLastErrorStr(errno));
this->rLength = 0;
this->rWant = 1;
}
} }
else else
{ {
@ -488,105 +537,49 @@ static unsigned wordAlign;
*/ */
if (this->rLength == this->rWant) if (this->rLength == this->rWant)
{ {
switch (this->rType) unsigned char *buf = [this->rData mutableBytes];
{ GSPortItemType rType;
case GSP_ITEM: GSPortItemHeader *pih;
{ unsigned off = 0;
GSPortItemHeader *h;
unsigned l; unsigned l;
/* while (off + sizeof(GSPortItemHeader) < this->rLength)
* We have read an item header - set up to read the
* remainder of the item.
*/
h = (GSPortItemHeader*)[this->rData bytes];
this->rType = GSSwapBigI32ToHost(h->type);
l = GSSwapBigI32ToHost(h->length);
if (this->rType == GSP_HEAD)
{ {
if (l + sizeof(GSPortItemHeader) > this->rWant) pih = (GSPortItemHeader*)(buf + off);
off += sizeof(GSPortItemHeader);
rType = GSSwapBigI32ToHost(pih->type);
l = GSSwapBigI32ToHost(pih->length);
if (l + off > this->rLength)
{ {
// There is more to read ... do it. NSLog(@"%@ - unreasonable length (%u) for data", self, l);
this->rWant = l + sizeof(GSPortItemHeader);
this->rType = GSP_HEAD;
}
else
{
goto gsp_head;
}
}
else if (this->rType == GSP_PORT)
{
if (l != 24)
{
NSLog(@"%@ - unreasonable length (%u) for port",
self, l);
[self invalidate];
break; break;
} }
this->rWant = l; if (rType != GSP_HEAD && [this->rItems count] == 0)
[this->rData setLength: this->rWant]; {
NSLog(@"%@ - initial part of message had bad type");
break;
} }
else if (this->rType == GSP_DATA)
{
if (l == 0)
{
NSData *d;
/* if (rType == GSP_HEAD)
* For a zero-length data chunk, we create an empty
* data object and add it to the current message.
*/
d = [NSMutableData new];
[this->rItems addObject: d];
RELEASE(d);
if (this->nItems == [this->rItems count])
{ {
shouldDispatch = YES;
}
}
else
{
if (l > maxDataLength)
{
NSLog(@"%@ - unreasonable length (%u) for data",
self, l);
[self invalidate];
break;
}
this->rWant = l;
[this->rData setLength: this->rWant];
}
}
else
{
NSLog(@"%@ - bad data received on port handle", self);
[self invalidate];
return;
}
}
break;
case GSP_HEAD:
gsp_head:
{
unsigned char *b = [this->rData mutableBytes];
GSPortItemHeader *pih;
GSPortMsgHeader *pmh; GSPortMsgHeader *pmh;
NSString *n; NSString *n;
NSMessagePort *p; NSMessagePort *p;
unsigned l;
NSMutableData *d; NSMutableData *d;
pih = (GSPortItemHeader*)b; if (l < sizeof(GSPortMsgHeader))
l = GSSwapBigI32ToHost(pih->length); {
pmh = (GSPortMsgHeader*)(b + sizeof(GSPortItemHeader)); NSLog(@"%@ - bad length for header", self);
break;
}
pmh = (GSPortMsgHeader*)(buf + off);
off += sizeof(GSPortMsgHeader);
l -= sizeof(GSPortMsgHeader);
this->rId = GSSwapBigI32ToHost(pmh->mId); this->rId = GSSwapBigI32ToHost(pmh->mId);
this->nItems = GSSwapBigI32ToHost(pmh->nItems); this->nItems = GSSwapBigI32ToHost(pmh->nItems);
if (this->nItems == 0) if (this->nItems == 0)
{ {
NSLog(@"%@ - unable to decode remote port", self); NSLog(@"%@ - unable to decode item count", self);
[self invalidate];
break; break;
} }
n = [[NSString alloc] initWithBytes: pmh->port n = [[NSString alloc] initWithBytes: pmh->port
@ -598,45 +591,49 @@ static unsigned wordAlign;
if (p == nil) if (p == nil)
{ {
NSLog(@"%@ - unable to decode remote port", self); NSLog(@"%@ - unable to decode remote port", self);
[self invalidate];
break; break;
} }
ASSIGN(this->rPort, p); ASSIGN(this->rPort, p);
this->rItems this->rItems
= [NSMutableArray allocWithZone: NSDefaultMallocZone()]; = [NSMutableArray allocWithZone: NSDefaultMallocZone()];
this->rItems = [this->rItems initWithCapacity: this->nItems]; this->rItems = [this->rItems initWithCapacity: this->nItems];
b = (unsigned char*)&pmh[1]; d = [[NSMutableData alloc] initWithBytes: buf + off
l -= sizeof(GSPortMsgHeader); length: l];
d = [[NSMutableData alloc] initWithBytes: b length: l];
[this->rItems addObject: d]; [this->rItems addObject: d];
RELEASE(d); RELEASE(d);
if (this->nItems == [this->rItems count]) if (this->nItems == [this->rItems count])
{ {
shouldDispatch = YES; shouldDispatch = YES;
}
}
break; break;
}
case GSP_DATA: off += l;
}
else if (rType == GSP_DATA)
{ {
NSMutableData *d; NSMutableData *d;
d = [this->rData mutableCopy]; d = [[NSMutableData alloc] initWithBytes: buf + off
length: l];
[this->rItems addObject: d]; [this->rItems addObject: d];
RELEASE(d); RELEASE(d);
if (this->nItems == [this->rItems count]) if (this->nItems == [this->rItems count])
{ {
shouldDispatch = YES; shouldDispatch = YES;
}
}
break; break;
}
case GSP_PORT: off += l;
}
else if (rType == GSP_PORT)
{ {
NSMessagePort *p; NSMessagePort *p;
NSString *n; NSString *n;
n = [[NSString alloc] initWithBytes: [this->rData bytes] if (l != 24)
{
NSLog(@"%@ - bad length for port item", self);
break;
}
n = [[NSString alloc] initWithBytes: buf + off
length: 24 length: 24
encoding: NSASCIIStringEncoding]; encoding: NSASCIIStringEncoding];
NSDebugFLLog(@"NSMessagePort", @"Decoded port as '%@'", n); NSDebugFLLog(@"NSMessagePort", @"Decoded port as '%@'", n);
@ -645,33 +642,45 @@ static unsigned wordAlign;
if (p == nil) if (p == nil)
{ {
NSLog(@"%@ - unable to decode remote port", self); NSLog(@"%@ - unable to decode remote port", self);
[self invalidate];
break; break;
} }
[this->rItems addObject: p]; [this->rItems addObject: p];
if (this->nItems == [this->rItems count]) if (this->nItems == [this->rItems count])
{ {
shouldDispatch = YES; shouldDispatch = YES;
}
}
break; break;
} }
} }
off += l;
} }
this->rWant = 1; // Queue a read
this->rLength = 0;
}
else
{
NSLog(@"Unexpected STATE");
}
}
else
{
this->rWant = 1; // Queue a read
this->rLength = 0;
}
if (shouldDispatch == YES) if (shouldDispatch == YES)
{ {
NSPortMessage *pm; NSPortMessage *pm;
pm = [NSPortMessage allocWithZone: NSDefaultMallocZone()]; pm = [NSPortMessage allocWithZone: NSDefaultMallocZone()];
pm = [pm initWithSendPort: this->rPort pm = [pm initWithSendPort: self
receivePort: self receivePort: this->rPort
components: this->rItems]; components: this->rItems];
[pm setMsgid: this->rId]; [pm setMsgid: this->rId];
this->rId = 0; this->rId = 0;
DESTROY(this->rPort); DESTROY(this->rPort);
DESTROY(this->rItems); DESTROY(this->rItems);
NSDebugMLLog(@"GSTcpHandle", @"got message %@ on 0x%x", pm, self); NSDebugMLLog(@"NSMessagePort", @"got message %@ on 0x%x", pm, self);
M_UNLOCK(this->lock); M_UNLOCK(this->lock);
NS_DURING NS_DURING
{ {
@ -688,20 +697,6 @@ static unsigned wordAlign;
RELEASE(pm); RELEASE(pm);
} }
if ([self isValid] == YES && this->rWant == 0)
{
this->rType = GSP_ITEM;
if (this->nItems > 0)
{
this->rWant = sizeof(GSPortItemHeader); // Want an item
}
else
{
this->rWant = HDR; // Want an item with a port message header
}
[this->rData setLength: this->rWant];
}
/* /*
* Got something ... is it all we want? If not, ask to read more. * Got something ... is it all we want? If not, ask to read more.
*/ */
@ -712,6 +707,10 @@ static unsigned wordAlign;
this->ov.Offset = 0; this->ov.Offset = 0;
this->ov.OffsetHigh = 0; this->ov.OffsetHigh = 0;
this->ov.hEvent = this->event; this->ov.hEvent = this->event;
if ([this->rData length] < (this->rWant - this->rLength))
{
[this->rData setLength: this->rWant - this->rLength];
}
rc = ReadFile(this->handle, rc = ReadFile(this->handle,
[this->rData mutableBytes], // Store results here [this->rData mutableBytes], // Store results here
this->rWant - this->rLength, this->rWant - this->rLength,
@ -722,7 +721,15 @@ static unsigned wordAlign;
{ {
[self receivedEventRead]; // Read completed synchronously [self receivedEventRead]; // Read completed synchronously
} }
else if ((errno = GetLastError()) != ERROR_IO_PENDING) else if ((errno = GetLastError()) == ERROR_IO_PENDING)
{
; // OK ...
}
else if (errno == ERROR_INSUFFICIENT_BUFFER)
{
[self receivedEventRead]; // Need to determine message size
}
else
{ {
NSLog(@"unable to read from mailslot '%@' - %s", NSLog(@"unable to read from mailslot '%@' - %s",
this->name, GSLastErrorStr(errno)); this->name, GSLastErrorStr(errno));
@ -743,27 +750,44 @@ static unsigned wordAlign;
M_LOCK(this->lock); M_LOCK(this->lock);
if (this->wData != nil)
{
/*
* Have we read something?
*/
if (GetOverlappedResult(
this->handle,
&this->ov,
&this->size,
TRUE) == 0)
{
NSLog(@"GetOverlappedResult failed ...%s", GSLastErrorStr(errno));
}
else
{
this->wLength += this->size; this->wLength += this->size;
this->size = 0; this->size = 0;
}
}
/* /*
* Handle start of next data item if we havce completed one, * Handle start of next data item if we have completed one,
* or if we are called without a write in progress. * or if we are called without a write in progress.
*/ */
if (this->wData == nil || this->wLength == [this->wData length]) if (this->wData == nil || this->wLength == [this->wData length])
{
if (this->wData != nil)
{ {
unsigned idx; unsigned idx;
if (this->wData == nil) NSDebugMLLog(@"NSMessagePort",
{
idx = NSNotFound;
}
else
{
NSDebugMLLog(@"GSTcpHandle",
@"completed 0x%x on 0x%x", this->wData, self); @"completed 0x%x on 0x%x", this->wData, self);
idx = [this->wMsgs indexOfObjectIdenticalTo: this->wData]; idx = [this->wMsgs indexOfObjectIdenticalTo: this->wData];
} if (idx != NSNotFound)
{
[this->wMsgs removeObjectAtIndex: idx]; [this->wMsgs removeObjectAtIndex: idx];
}
}
if ([this->wMsgs count] > 0) if ([this->wMsgs count] > 0)
{ {
this->wData = [this->wMsgs objectAtIndex: 0]; this->wData = [this->wMsgs objectAtIndex: 0];
@ -777,19 +801,33 @@ static unsigned wordAlign;
if (this->wData != nil) if (this->wData != nil)
{ {
int rc;
this->ov.Offset = 0; this->ov.Offset = 0;
this->ov.OffsetHigh = 0; this->ov.OffsetHigh = 0;
this->ov.hEvent = this->event; this->ov.hEvent = this->event;
if (WriteFile(this->handle, rc = WriteFile(this->handle,
[this->wData bytes], // Output from here [this->wData bytes], // Output from here
[this->wData length] - this->wLength, [this->wData length] - this->wLength,
&this->size, // Store number of bytes written &this->size, // Store number of bytes written
&this->ov) == 0 && (errno = GetLastError()) != ERROR_HANDLE_EOF) &this->ov);
if (rc > 0)
{
NSDebugMLLog(@"NSMessagePort", @"Write of %d performs %d",
[this->wData length] - this->wLength, this->size);
[self receivedEventWrite]; // Completed synchronously
}
else if ((errno = GetLastError()) != ERROR_IO_PENDING)
{ {
NSLog(@"unable to write to mailslot '%@' - %s", NSLog(@"unable to write to mailslot '%@' - %s",
this->name, GSLastErrorStr(errno)); this->name, GSLastErrorStr(errno));
[self invalidate]; [self invalidate];
} }
else
{
NSDebugMLLog(@"NSMessagePort", @"Write of %d queued",
[this->wData length] - this->wLength);
}
} }
M_UNLOCK(this->lock); M_UNLOCK(this->lock);
} }
@ -829,7 +867,9 @@ static unsigned wordAlign;
fromRunLoop: (NSRunLoop*)aLoop fromRunLoop: (NSRunLoop*)aLoop
forMode: (NSString*)aMode forMode: (NSString*)aMode
{ {
[aLoop removeEvent: (void*)(gsaddr)PORT(self)->handle NSDebugMLLog(@"NSMessagePort", @"%@ remove from 0x%x in mode %@",
self, aLoop, aMode);
[aLoop removeEvent: (void*)(gsaddr)PORT(self)->event
type: ET_HANDLE type: ET_HANDLE
forMode: aMode forMode: aMode
all: NO]; all: NO];
@ -845,7 +885,7 @@ static unsigned wordAlign;
*/ */
- (unsigned int) reservedSpaceLength - (unsigned int) reservedSpaceLength
{ {
return sizeof(GSPortItemHeader) + sizeof(GSPortMsgHeader) + 24; return sizeof(GSPortItemHeader) + sizeof(GSPortMsgHeader);
} }
- (BOOL) sendBeforeDate: (NSDate*)when - (BOOL) sendBeforeDate: (NSDate*)when
@ -902,7 +942,7 @@ static unsigned wordAlign;
h = [components objectAtIndex: 0]; h = [components objectAtIndex: 0];
pih = (GSPortItemHeader*)[h mutableBytes]; pih = (GSPortItemHeader*)[h mutableBytes];
pih->type = GSSwapHostI32ToBig(GSP_HEAD); pih->type = GSSwapHostI32ToBig(GSP_HEAD);
l = [h length] - sizeof(GSPortMsgHeader); l = [h length] - sizeof(GSPortItemHeader);
pih->length = GSSwapHostI32ToBig(l); pih->length = GSSwapHostI32ToBig(l);
pmh = (GSPortMsgHeader*)&pih[1]; pmh = (GSPortMsgHeader*)&pih[1];
pmh->mId = GSSwapHostI32ToBig(msgId); pmh->mId = GSSwapHostI32ToBig(msgId);
@ -918,8 +958,7 @@ static unsigned wordAlign;
if ([o isKindOfClass: [NSData class]] == YES) if ([o isKindOfClass: [NSData class]] == YES)
{ {
l += [[components objectAtIndex: i] length]; l += sizeof(GSPortItemHeader) + [o length];
l += sizeof(GSPortItemHeader);
} }
else else
{ {
@ -982,12 +1021,13 @@ static unsigned wordAlign;
loop = [NSRunLoop currentRunLoop]; loop = [NSRunLoop currentRunLoop];
RETAIN(self); RETAIN(self);
AUTORELEASE(RETAIN(components));
[loop addEvent: (void*)(gsaddr)this->handle [loop addEvent: (void*)(gsaddr)this->event
type: ET_HANDLE type: ET_HANDLE
watcher: (id<RunLoopEvents>)self watcher: (id<RunLoopEvents>)self
forMode: NSConnectionReplyMode]; forMode: NSConnectionReplyMode];
[loop addEvent: (void*)(gsaddr)this->handle [loop addEvent: (void*)(gsaddr)this->event
type: ET_HANDLE type: ET_HANDLE
watcher: (id<RunLoopEvents>)self watcher: (id<RunLoopEvents>)self
forMode: NSDefaultRunLoopMode]; forMode: NSDefaultRunLoopMode];
@ -1001,11 +1041,11 @@ static unsigned wordAlign;
M_LOCK(this->lock); M_LOCK(this->lock);
} }
[loop removeEvent: (void*)(gsaddr)this->handle [loop removeEvent: (void*)(gsaddr)this->event
type: ET_HANDLE type: ET_HANDLE
forMode: NSConnectionReplyMode forMode: NSConnectionReplyMode
all: NO]; all: NO];
[loop removeEvent: (void*)(gsaddr)this->handle [loop removeEvent: (void*)(gsaddr)this->event
type: ET_HANDLE type: ET_HANDLE
forMode: NSDefaultRunLoopMode forMode: NSDefaultRunLoopMode
all: NO]; all: NO];