From eacd1dbd463ab75a72105fef473ca3ec31175fe3 Mon Sep 17 00:00:00 2001 From: richard Date: Thu, 29 Oct 1998 12:50:23 +0000 Subject: [PATCH] Name server updates. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@3144 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 11 + Headers/gnustep/base/NSPortNameServer.h | 47 ++ Source/GNUmakefile | 2 + Source/NSPortNameServer.m | 765 ++++++++++++++++++++++++ Source/TcpPort.m | 43 +- Source/UnixFileHandle.m | 492 ++++++++------- 6 files changed, 1126 insertions(+), 234 deletions(-) create mode 100644 Headers/gnustep/base/NSPortNameServer.h create mode 100644 Source/NSPortNameServer.m diff --git a/ChangeLog b/ChangeLog index 02752a655..31f0746b9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +Thu Oct 29 13:30:00 1998 Richard Frith-Macdonald + + * src/UnixFileHandle.m: Improved handling of error conditions on + background connection operations. Disable SIGPIPE to avoid abort + when we attempt to write to a socket that's closed by the other end. + * src/TCPPort.m: Modified to use NSPortNameServer, also changed to + disable SIGPIPE on initialisation only, not on every write. + * src/include/NSPortNameServer.h: new class. + * src/NSPortNameServer.m: new class. + * src/GNUmakefile: Added NSPortNameServer. + Wed Oct 28 14:30:00 1998 Richard Frith-Macdonald * Tools/gdomap.c: Added command-line options to lookup, register, and diff --git a/Headers/gnustep/base/NSPortNameServer.h b/Headers/gnustep/base/NSPortNameServer.h new file mode 100644 index 000000000..86027a35d --- /dev/null +++ b/Headers/gnustep/base/NSPortNameServer.h @@ -0,0 +1,47 @@ +/* Interface of NSPortNameServer class for Distributed Objects + Copyright (C) 1998 Free Software Foundation, Inc. + + Written by: Richard Frith-Macdonald + Created: October 1998 + + This file is part of the GNUstep Base Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __NSPortNameServer_h_GNUSTEP_BASE_INCLUDE +#define __NSPortNameServer_h_GNUSTEP_BASE_INCLUDE + +#include + +@class NSPort, NSString, NSMutableData, NSFileHandle; + +@interface NSPortNameServer : NSObject +{ + NSFileHandle *handle; /* File handle to talk to gdomap. */ + NSMutableData *data; /* Where to accumulated incoming data. */ + unsigned expecting; /* Length of data we want. */ +} ++ (id) defaultPortNameServer; +- (NSPort*) portForName: (NSString*)name; +- (NSPort*) portForName: (NSString*)name + onHost: (NSString*)host; +- (BOOL) registerPort: (NSPort*)port + forName: (NSString*)name; +- (void) removePortForName: (NSString*)name; +@end + +#endif + diff --git a/Source/GNUmakefile b/Source/GNUmakefile index 7f0be305e..031914452 100644 --- a/Source/GNUmakefile +++ b/Source/GNUmakefile @@ -340,6 +340,7 @@ NSPipe.m \ NSPort.m \ NSPortCoder.m \ NSPortMessage.m \ +NSPortNameServer.m \ NSProcessInfo.m \ NSProtocolChecker.m \ NSProxy.m \ @@ -433,6 +434,7 @@ Foundation/NSPathUtilities.h \ Foundation/NSPort.h \ Foundation/NSPortCoder.h \ Foundation/NSPortMessage.h \ +Foundation/NSPortNameServer.h \ Foundation/NSProcessInfo.h \ Foundation/NSProtocolChecker.h \ Foundation/NSProxy.h \ diff --git a/Source/NSPortNameServer.m b/Source/NSPortNameServer.m new file mode 100644 index 000000000..e37f7915a --- /dev/null +++ b/Source/NSPortNameServer.m @@ -0,0 +1,765 @@ +/* Implementation of NSPortNameServer class for Distributed Objects + Copyright (C) 1998 Free Software Foundation, Inc. + + Written by: Richard Frith-Macdonald + Created: October 1998 + + This file is part of the GNUstep Base Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Protocol definition stuff for talking to gdomap process. + */ +#include "../Tools/gdomap.h" + +/* + * Macros to build text to start name server and to give an error + * message about it - they include installation path information. + */ +#define stringify_it(X) #X +#define make_gdomap_cmd(X) stringify_it(X) "/Tools/"GNUSTEP_TARGET_DIR"/gdomap &" +#define make_gdomap_err(X) "check that " stringify_it(X) "/Tools/"GNUSTEP_TARGET_DIR"/gdomap is running and owned by root." + +/* + * Private methods for internal use only. + */ +@interface NSPortNameServer (Private) +- (void) _close; +- (void) _didConnect: (NSNotification*)notification; +- (void) _didRead: (NSNotification*)notification; +- (void) _didWrite: (NSNotification*)notification; +- (void) _open: (NSString*)host; +- (void) _retry; +@end + +@implementation NSPortNameServer + +static NSTimeInterval writeTimeout = 5.0; +static NSTimeInterval readTimeout = 15.0; +static NSTimeInterval connectTimeout = 20.0; +static NSString *serverPort = @"gdomap"; +static NSString *mode = @"NSPortServerLookupMode"; +static NSArray *modes = nil; +static NSRecursiveLock *serverLock = nil; +static NSPortNameServer *defaultServer = nil; + ++ (id) allocWithZone: (NSZone*)aZone +{ + [NSException raise: NSGenericException + format: @"attempt to create extra port name server"]; + return nil; +} + ++ (void) initialize +{ + if (self == [NSPortNameServer class]) + { + serverLock = [NSRecursiveLock new]; + [serverLock lock]; + if (modes == nil) + { + modes = [[NSArray alloc] initWithObjects: &mode count: 1]; + } + [serverLock unlock]; + } +} + ++ (id) defaultPortNameServer +{ + if (defaultServer == nil) + { + NSPortNameServer *s; + + [serverLock lock]; + if (defaultServer) + { + [serverLock unlock]; + return defaultServer; + } + s = (NSPortNameServer*)NSAllocateObject(self, 0, NSDefaultMallocZone()); + s->data = [NSMutableData new]; + defaultServer = s; + [serverLock unlock]; + } + return defaultServer; +} + +- (void) dealloc +{ + [NSException raise: NSGenericException + format: @"attempt to deallocate default port name server"]; +} + +- (NSPort*) portForName: (NSString*)name +{ + return [self portForName: name onHost: nil]; +} + +- (NSPort*) portForName: (NSString*)name + onHost: (NSString*)host +{ + gdo_req msg; /* Message structure. */ + NSMutableData *dat; /* Hold message here. */ + unsigned len; + NSRunLoop *loop = [NSRunLoop currentRunLoop]; + struct in_addr singleServer; + struct in_addr *svrs = &singleServer; + unsigned numSvrs; + unsigned count; + unsigned portNum = 0; + + if (name == nil) + { + [NSException raise: NSInvalidArgumentException + format: @"attempt to register port with nil name"]; + } + + len = [name cStringLength]; + if (len == 0) + { + [NSException raise: NSInvalidArgumentException + format: @"attempt to register port with no name"]; + } + if (len > GDO_NAME_MAX_LEN) + { + [NSException raise: NSInvalidArgumentException + format: @"name of port is too long (max %d) bytes", + GDO_NAME_MAX_LEN]; + } + + if (host != nil && [host isEqual: @"*"]) + { + NSMutableData *tmp; + unsigned bufsiz; + unsigned length; + + msg.rtype = GDO_SERVERS; /* Get a list of name servers. */ + msg.ptype = GDO_TCP_GDO; /* Port is TCP port for GNU DO */ + msg.nsize = 0; + msg.port = 0; + dat = [NSMutableData dataWithBytes: (void*)&msg length: sizeof(msg)]; + + [serverLock lock]; + NS_DURING + { + [self _open: nil]; + expecting = sizeof(msg); + [handle writeInBackgroundAndNotify: dat + forModes: modes]; + [loop runMode: mode + beforeDate: [NSDate dateWithTimeIntervalSinceNow: writeTimeout]]; + if (expecting) + { + [self _close]; + [NSException raise: NSPortTimeoutException + format: @"timed out writing to gdomap"]; + } + + expecting = sizeof(unsigned); + [data setLength: 0]; + [handle readInBackgroundAndNotifyForModes: modes]; + [loop runMode: mode + beforeDate: [NSDate dateWithTimeIntervalSinceNow: readTimeout]]; + if (expecting) + { + [self _close]; + [NSException raise: NSPortTimeoutException + format: @"timed out reading from gdomap"]; + } + numSvrs = NSSwapBigIntToHost(*(unsigned*)[data bytes]); + if (numSvrs == 0) + { + [self _close]; + [NSException raise: NSInternalInconsistencyException + format: @"failed to get list of name servers on net"]; + } + + /* + * Calculate size of buffer for server internet addresses and + * allocate a buffer to store them in. + */ + bufsiz = numSvrs * sizeof(struct in_addr); + tmp = [NSMutableData dataWithLength: bufsiz]; + svrs = (struct in_addr*)[tmp mutableBytes]; + + /* + * Read the addresses from the name server if necessary + * and copy them to our newly allocated buffer. + * We may already have some/all of the data, in which case + * we don't need to do a read. + */ + length = [data length] - sizeof(unsigned); + if (length > 0) + { + void *bytes = [data mutableBytes]; + + memcpy(bytes, bytes+sizeof(unsigned), length); + [data setLength: length]; + } + else + { + [data setLength: 0]; + } + + if (length < bufsiz) + { + expecting = bufsiz; + [handle readInBackgroundAndNotifyForModes: modes]; + [loop runMode: mode + beforeDate: [NSDate dateWithTimeIntervalSinceNow: + readTimeout]]; + if (expecting) + { + [self _close]; + [NSException raise: NSPortTimeoutException + format: @"timed out reading from gdomap"]; + } + } + + [data getBytes: (void*)svrs length: bufsiz]; + [self _close]; + } + NS_HANDLER + { + /* + * If we had a problem - unlock before continueing. + */ + [serverLock unlock]; + [localException raise]; + } + NS_ENDHANDLER + [serverLock unlock]; + } + else + { + /* + * Query a single nameserver - on the local host. + */ + numSvrs = 1; +#ifndef HAVE_INET_ATON + svrs->s_addr = inet_addr("127.0.0.1"); +#else + inet_aton("127.0.0.1", &svrs->s_addr); +#endif + } + + [serverLock lock]; + NS_DURING + { + for (count = 0; count < numSvrs; count++) + { + NSString *addr; + + msg.rtype = GDO_LOOKUP; /* Find the named port. */ + msg.ptype = GDO_TCP_GDO; /* Port is TCP port for GNU DO */ + msg.port = 0; + msg.nsize = len; + [name getCString: msg.name]; + dat = [NSMutableData dataWithBytes: (void*)&msg length: sizeof(msg)]; + + addr = [NSString stringWithCString: (char*)inet_ntoa(svrs[count])]; + [self _open: addr]; + expecting = sizeof(msg); + [handle writeInBackgroundAndNotify: dat + forModes: modes]; + [loop runMode: mode + beforeDate: [NSDate dateWithTimeIntervalSinceNow: writeTimeout]]; + if (expecting) + { + [self _close]; + } + else + { + expecting = sizeof(unsigned); + [data setLength: 0]; + [handle readInBackgroundAndNotifyForModes: modes]; + [loop runMode: mode + beforeDate: [NSDate dateWithTimeIntervalSinceNow: + readTimeout]]; + [self _close]; + if (expecting == 0) + { + portNum = NSSwapBigIntToHost(*(unsigned*)[data bytes]); + if (portNum != 0) + { + break; + } + } + } + } + } + NS_HANDLER + { + /* + * If we had a problem - unlock before continueing. + */ + [serverLock unlock]; + [localException raise]; + } + NS_ENDHANDLER + [serverLock unlock]; + + if (portNum) + { + struct sockaddr_in sin; + NSPort *p; + unsigned short n; + + memset(&sin, '\0', sizeof(sin)); + sin.sin_family = AF_INET; + + /* + * The returned port is an unsigned int - so we have to + * convert to a short in network byte order (big endian). + */ + n = (unsigned short)portNum; + sin.sin_port = NSSwapHostShortToBig(n); + + /* + * The host addresses are given to us in network byte order + * so we just copy the address into place. + */ + sin.sin_addr.s_addr = svrs[count].s_addr; + + p = [TcpOutPort newForSendingToSockaddr: &sin + withAcceptedSocket: 0 + pollingInPort: nil]; + return [p autorelease]; + } + else + { + return nil; + } +} + +- (BOOL) registerPort: (NSPort*)port + forName: (NSString*)name +{ + gdo_req msg; /* Message structure. */ + NSMutableData *dat; /* Hold message here. */ + unsigned len; + NSRunLoop *loop = [NSRunLoop currentRunLoop]; + + if (name == nil) + { + [NSException raise: NSInvalidArgumentException + format: @"attempt to register port with nil name"]; + } + if (port == nil) + { + [NSException raise: NSInvalidArgumentException + format: @"attempt to register nil port"]; + } + + len = [name cStringLength]; + if (len == 0) + { + [NSException raise: NSInvalidArgumentException + format: @"attempt to register port with no name"]; + } + if (len > GDO_NAME_MAX_LEN) + { + [NSException raise: NSInvalidArgumentException + format: @"name of port is too long (max %d) bytes", + GDO_NAME_MAX_LEN]; + } + + msg.rtype = GDO_REGISTER; /* Register a port. */ + msg.ptype = GDO_TCP_GDO; /* Port is TCP port for GNU DO */ + msg.nsize = len; + [name getCString: msg.name]; + msg.port = NSSwapHostIntToBig((unsigned)[(TcpInPort*)port portNumber]); + dat = [NSMutableData dataWithBytes: (void*)&msg length: sizeof(msg)]; + + /* + * Lock out other threads while doing I/O to gdomap + */ + [serverLock lock]; + + NS_DURING + { + [self _open: nil]; + + /* + * Queue a write request in our own run mode then run until the + * timeout period or until the write completes. + */ + expecting = sizeof(msg); + [handle writeInBackgroundAndNotify: dat + forModes: modes]; + [loop runMode: mode + beforeDate: [NSDate dateWithTimeIntervalSinceNow: writeTimeout]]; + if (expecting) + { + [self _close]; + [NSException raise: NSPortTimeoutException + format: @"timed out writing to gdomap"]; + } + + /* + * Queue a read request in our own run mode then run until the + * timoeut period or until the read completes. + */ + expecting = sizeof(unsigned); + [data setLength: 0]; + [handle readInBackgroundAndNotifyForModes: modes]; + [loop runMode: mode + beforeDate: [NSDate dateWithTimeIntervalSinceNow: readTimeout]]; + if (expecting) + { + [self _close]; + [NSException raise: NSPortTimeoutException + format: @"timed out reading from gdomap"]; + } + + /* + * Finished with server - so close connection. + */ + [self _close]; + + if ([data length] != sizeof(unsigned)) + { + [NSException raise: NSInternalInconsistencyException + format: @"too much data read from gdomap"]; + } + else + { + unsigned result = NSSwapBigIntToHost(*(unsigned*)[data bytes]); + + if (result == 0) + { + NSLog(@"NSPortNameServer unable to register '%@'\n", name); + } + } + } + NS_HANDLER + { + /* + * If we had a problem - unlock before continueing. + */ + [serverLock unlock]; + [localException raise]; + } + NS_ENDHANDLER + [serverLock unlock]; +} + +- (void) removePortForName: (NSString*)name +{ + gdo_req msg; /* Message structure. */ + NSMutableData *dat; /* Hold message here. */ + unsigned len; + NSRunLoop *loop = [NSRunLoop currentRunLoop]; + + if (name == nil) + { + [NSException raise: NSInvalidArgumentException + format: @"attempt to remove port with nil name"]; + } + + len = [name cStringLength]; + if (len == 0) + { + [NSException raise: NSInvalidArgumentException + format: @"attempt to remove port with no name"]; + } + if (len > GDO_NAME_MAX_LEN) + { + [NSException raise: NSInvalidArgumentException + format: @"name of port is too long (max %d) bytes", + GDO_NAME_MAX_LEN]; + } + + msg.rtype = GDO_UNREG; /* Unregister a port. */ + msg.ptype = GDO_TCP_GDO; /* Port is TCP port for GNU DO */ + msg.nsize = len; + [name getCString: msg.name]; + msg.port = 0; + dat = [NSMutableData dataWithBytes: (void*)&msg length: sizeof(msg)]; + + /* + * Lock out other threads while doing I/O to gdomap + */ + [serverLock lock]; + + NS_DURING + { + [self _open: nil]; + + /* + * Queue a write request in our own run mode then run until the + * timeout period or until the write completes. + */ + expecting = sizeof(msg); + [handle writeInBackgroundAndNotify: dat + forModes: modes]; + [loop runMode: mode + beforeDate: [NSDate dateWithTimeIntervalSinceNow: writeTimeout]]; + if (expecting) + { + [self _close]; + [NSException raise: NSPortTimeoutException + format: @"timed out writing to gdomap"]; + } + + /* + * Queue a read request in our own run mode then run until the + * timeout period or until the read completes. + */ + expecting = sizeof(unsigned); + [data setLength: 0]; + [handle readInBackgroundAndNotifyForModes: modes]; + [loop runMode: mode + beforeDate: [NSDate dateWithTimeIntervalSinceNow: readTimeout]]; + if (expecting) + { + [self _close]; + [NSException raise: NSPortTimeoutException + format: @"timed out reading from gdomap"]; + } + + /* + * Finished with server - so close connection. + */ + [self _close]; + + if ([data length] != sizeof(unsigned)) + { + [NSException raise: NSInternalInconsistencyException + format: @"too much data read from gdomap"]; + } + else + { + unsigned result = NSSwapBigIntToHost(*(unsigned*)[data bytes]); + + if (result == 0) + { + NSLog(@"NSPortNameServer unable to unregister '%@'\n", name); + } + } + } + NS_HANDLER + { + /* + * If we had a problem - unlock before continueing. + */ + [serverLock unlock]; + [localException raise]; + } + NS_ENDHANDLER + [serverLock unlock]; +} +@end + +@implementation NSPortNameServer (Private) +- (void) _close +{ + if (handle) + { + [NSNotificationCenter removeObserver: self + name: GSFileHandleConnectCompletionNotification + object: handle]; + [NSNotificationCenter removeObserver: self + name: NSFileHandleReadCompletionNotification + object: handle]; + [NSNotificationCenter removeObserver: self + name: GSFileHandleWriteCompletionNotification + object: handle]; + [handle closeFile]; + [handle release]; + handle = nil; + } +} + +- (void) _didConnect: (NSNotification*)notification +{ + NSDictionary *userInfo = [notification userInfo]; + NSString *e; + + e = [userInfo objectForKey:GSFileHandleNotificationError]; + if (e) + { + NSLog(@"NSPortNameServer failed connect to gdomap - %@", e); + } + else + { + /* + * There should now be nothing for the runloop to do so + * control should return to the method that started the connection. + * Set 'expecting' to zero to show that the connection worked and + * stop watching for connection completion. + */ + expecting = 0; + [NSNotificationCenter removeObserver: self + name: GSFileHandleConnectCompletionNotification + object: handle]; + } +} + +- (void) _didRead: (NSNotification*)notification +{ + NSDictionary *userInfo = [notification userInfo]; + NSData *d; + + d = [userInfo objectForKey:NSFileHandleNotificationDataItem]; + + if (d == nil || [d length] == 0) + { + [self _close]; + [NSException raise: NSGenericException + format: @"NSPortNameServer lost connection to gdomap"]; + } + else + { + [data appendData: d]; + if ([data length] < expecting) + { + /* + * Not enough data read yet - go read some more. + */ + [handle readInBackgroundAndNotifyForModes: modes]; + } + else + { + /* + * There should now be nothing for the runloop to do so + * control should return to the method that started the read. + * Set 'expecting' to zero to show that the data was read. + */ + expecting = 0; + } + } +} + +- (void) _didWrite: (NSNotification*)notification +{ + NSDictionary *userInfo = [notification userInfo]; + NSString *e; + + e = [userInfo objectForKey:GSFileHandleNotificationError]; + if (e) + { + [self _close]; + [NSException raise: NSGenericException + format: @"NSPortNameServer failed write to gdomap - %@", e]; + } + else + { + /* + * There should now be nothing for the runloop to do so + * control should return to the method that started the write. + * Set 'expecting' to zero to show that the data was written. + */ + expecting = 0; + } +} + +- (void) _open: (NSString*)host +{ + NSRunLoop *loop; + NSString *hostname = host; + + if (handle) + { + return; /* Connection already open. */ + } + if (hostname == nil) + { + hostname = @"localhost"; + } + + expecting = 1; + handle = [NSFileHandle fileHandleAsClientInBackgroundAtAddress: host + service: serverPort + protocol: @"tcp" + forModes: modes]; + + if (handle == nil) + { + [NSException raise: NSGenericException + format: @"failed to create file handle to gdomap on %@", + hostname]; + } + + [handle retain]; + [NSNotificationCenter addObserver: self + selector: @selector(_didConnect:) + name: GSFileHandleConnectCompletionNotification + object: handle]; + [NSNotificationCenter addObserver: self + selector: @selector(_didRead:) + name: NSFileHandleReadCompletionNotification + object: handle]; + [NSNotificationCenter addObserver: self + selector: @selector(_didWrite:) + name: GSFileHandleWriteCompletionNotification + object: handle]; + loop = [NSRunLoop currentRunLoop]; + [loop runMode: mode + beforeDate: [NSDate dateWithTimeIntervalSinceNow: connectTimeout]]; + if (expecting) + { + static BOOL retrying = NO; + + [self _close]; + if (retrying == NO) + { + retrying = YES; + NS_DURING + { + [self _retry]; + } + NS_HANDLER + { + retrying = NO; + [localException raise]; + } + NS_ENDHANDLER + retrying = NO; + } + else + { + NSLog(@"NSPortNameServer failed to connect to gdomap - %s", + make_gdomap_err(GNUSTEP_INSTALL_PREFIX)); + } + } +} + +- (void) _retry +{ + NSLog(@"NSPortNameServer attempting to start gdomap on local host"); + system(make_gdomap_cmd(GNUSTEP_INSTALL_PREFIX)); + sleep(5); + NSLog(@"NSPortNameServer retrying connection attempt to gdomap"); + [self _open: nil]; +} + +@end + diff --git a/Source/TcpPort.m b/Source/TcpPort.m index d9f128130..7820e6639 100644 --- a/Source/TcpPort.m +++ b/Source/TcpPort.m @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -68,6 +69,7 @@ #define NBLK_OPT FNDELAY #endif +#define NSPORTNAMESERVER 1 #define GDOMAP 1 /* 1 = Use name server. */ #define stringify_it(X) #X #define make_gdomap_cmd(X) stringify_it(X) "/Tools/"GNUSTEP_TARGET_DIR"/gdomap &" @@ -317,15 +319,7 @@ tryWrite(int desc, int tim, unsigned char* dat, int len) return(-1); /* Error in select. */ } else if (len > 0) { - void (*ifun)(); - - /* - * Should be able to write this short a message immediately, but - * if the connection is lost we will get a signal we must trap. - */ - ifun = signal(SIGPIPE, (void(*)(int))SIG_IGN); rval = write(desc, &dat[pos], len - pos); - signal(SIGPIPE, ifun); if (rval <= 0) { if (errno != EWOULDBLOCK) { @@ -745,10 +739,17 @@ static NSMapTable* port_number_2_port; + (void) initialize { if (self == [TcpInPort class]) - port_number_2_port = - NSCreateMapTable (NSIntMapKeyCallBacks, - NSNonOwnedPointerMapValueCallBacks, 0); - init_port_socket_2_port (); + { + port_number_2_port = + NSCreateMapTable (NSIntMapKeyCallBacks, + NSNonOwnedPointerMapValueCallBacks, 0); + init_port_socket_2_port (); + /* + * If SIGPIPE is not ignored, we will abort on any attempt to + * write to a pipe/socket that has been closed by the other end! + */ + signal(SIGPIPE, SIG_IGN); + } } /* This is the designated initializer. @@ -919,12 +920,17 @@ static NSMapTable* port_number_2_port; struct sockaddr_in sin; if (p) { +#if NSPORTNAMESERVER + [[NSPortNameServer defaultPortNameServer] registerPort: p + forName: name]; +#else int port = [p portNumber]; if (nameServer([name cString], 0, GDO_REGISTER, &sin, port, 1) == 0) { [p release]; return nil; } +#endif } return p; #else @@ -1390,6 +1396,11 @@ static NSMapTable *out_port_bag = NULL; init_port_socket_2_port (); out_port_bag = NSCreateMapTable (NSNonOwnedPointerMapKeyCallBacks, NSNonOwnedPointerMapValueCallBacks, 0); + /* + * If SIGPIPE is not ignored, we will abort on any attempt to + * write to a pipe/socket that has been closed by the other end! + */ + signal(SIGPIPE, SIG_IGN); } } @@ -1647,6 +1658,13 @@ static NSMapTable *out_port_bag = NULL; onHost: (NSString*)hostname { #ifdef GDOMAP +#if NSPORTNAMESERVER + id c; + + c = [[NSPortNameServer defaultPortNameServer] portForName: name + onHost: hostname]; + return [c retain]; +#else struct sockaddr_in sin[100]; int found; int i; @@ -1661,6 +1679,7 @@ static NSMapTable *out_port_bag = NULL; pollingInPort: nil]; } return c; +#endif #else return [self newForSendingToPortNumber: name_2_port_number ([name cString]) onHost: hostname];; diff --git a/Source/UnixFileHandle.m b/Source/UnixFileHandle.m index 4bc632ffa..47f3407f3 100644 --- a/Source/UnixFileHandle.m +++ b/Source/UnixFileHandle.m @@ -43,6 +43,7 @@ #include #include #include +#include #endif /* WIN32 */ #include @@ -101,7 +102,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) */ if (name) { - NSHost* host = [NSHost hostWithName:name]; + NSHost* host = [NSHost hostWithName: name]; if (host) name = [host address]; @@ -146,12 +147,24 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) } } -+ allocWithZone:(NSZone*)z ++ (void) initialize +{ + if (self == [UnixFileHandle class]) + { + /* + * If SIGPIPE is not ignored, we will abort on any attempt to + * write to a pipe/socket that has been closed by the other end! + */ + signal(SIGPIPE, SIG_IGN); + } +} + ++ (id) allocWithZone: (NSZone*)z { return NSAllocateObject ([self class], 0, z); } -- (void)dealloc +- (void) dealloc { [address release]; [service release]; @@ -186,12 +199,12 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) - (id)init { - return [self initWithNullDevice]; + return [self initWithNullDevice]; } -- (id)initAsClientAtAddress:a - service:s - protocol:p +- (id)initAsClientAtAddress: a + service: s + protocol: p { int net; struct sockaddr_in sin; @@ -217,7 +230,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) return nil; } - self = [self initWithFileDescriptor:net closeOnDealloc:YES]; + self = [self initWithFileDescriptor: net closeOnDealloc: YES]; if (self) { if (connect(net, (struct sockaddr*)&sin, sizeof(sin)) < 0) @@ -234,10 +247,10 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) return self; } -- (id)initAsClientInBackgroundAtAddress:a - service:s - protocol:p - forModes:modes +- (id)initAsClientInBackgroundAtAddress: a + service: s + protocol: p + forModes: modes { int net; struct sockaddr_in sin; @@ -263,7 +276,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) return nil; } - self = [self initWithFileDescriptor:net closeOnDealloc:YES]; + self = [self initWithFileDescriptor: net closeOnDealloc: YES]; if (self) { NSMutableDictionary* info; @@ -277,13 +290,13 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) return nil; } - info = [[NSMutableDictionary dictionaryWithCapacity:4] retain]; - [info setObject:address forKey:NSFileHandleNotificationDataItem]; - [info setObject:GSFileHandleConnectCompletionNotification - forKey:NotificationKey]; + info = [[NSMutableDictionary dictionaryWithCapacity: 4] retain]; + [info setObject: address forKey: NSFileHandleNotificationDataItem]; + [info setObject: GSFileHandleConnectCompletionNotification + forKey: NotificationKey]; if (modes) - [info setObject:modes forKey:NSFileHandleNotificationMonitorModes]; - [writeInfo addObject:info]; + [info setObject: modes forKey: NSFileHandleNotificationMonitorModes]; + [writeInfo addObject: info]; [info release]; [self watchWriteDescriptor]; connectOK = YES; @@ -293,9 +306,9 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) return self; } -- (id)initAsServerAtAddress:a - service:s - protocol:p +- (id)initAsServerAtAddress: a + service: s + protocol: p { int status = 1; int net; @@ -342,7 +355,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) return nil; } - self = [self initWithFileDescriptor:net closeOnDealloc:YES]; + self = [self initWithFileDescriptor: net closeOnDealloc: YES]; if (self) { acceptOK = YES; @@ -353,7 +366,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) return self; } -- (id)initForReadingAtPath:(NSString*)path +- (id)initForReadingAtPath: (NSString*)path { int d = open([path fileSystemRepresentation], O_RDONLY); @@ -364,14 +377,14 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) } else { - self = [self initWithFileDescriptor:d closeOnDealloc:YES]; + self = [self initWithFileDescriptor: d closeOnDealloc: YES]; if (self) writeOK = NO; return self; } } -- (id)initForWritingAtPath:(NSString*)path +- (id)initForWritingAtPath: (NSString*)path { int d = open([path fileSystemRepresentation], O_WRONLY); @@ -382,14 +395,14 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) } else { - self = [self initWithFileDescriptor:d closeOnDealloc:YES]; + self = [self initWithFileDescriptor: d closeOnDealloc: YES]; if (self) readOK = NO; return self; } } -- (id)initForUpdatingAtPath:(NSString*)path +- (id)initForUpdatingAtPath: (NSString*)path { int d = open([path fileSystemRepresentation], O_RDWR); @@ -400,7 +413,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) } else { - return [self initWithFileDescriptor:d closeOnDealloc:YES]; + return [self initWithFileDescriptor: d closeOnDealloc: YES]; } } @@ -413,7 +426,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) } else { - [self initWithFileDescriptor:2 closeOnDealloc:NO]; + [self initWithFileDescriptor: 2 closeOnDealloc: NO]; fh_stderr = self; } self = fh_stderr; @@ -431,7 +444,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) } else { - [self initWithFileDescriptor:0 closeOnDealloc:NO]; + [self initWithFileDescriptor: 0 closeOnDealloc: NO]; fh_stdin = self; } self = fh_stdin; @@ -449,7 +462,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) } else { - [self initWithFileDescriptor:1 closeOnDealloc:NO]; + [self initWithFileDescriptor: 1 closeOnDealloc: NO]; fh_stdout = self; } self = fh_stdout; @@ -460,15 +473,15 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) - (id)initWithNullDevice { - self = [self initWithFileDescriptor:open("/dev/null", O_RDWR) - closeOnDealloc:YES]; + self = [self initWithFileDescriptor: open("/dev/null", O_RDWR) + closeOnDealloc: YES]; if (self) { isNullDevice = YES; } return self; } -- (id)initWithFileDescriptor:(int)desc closeOnDealloc:(BOOL)flag +- (id)initWithFileDescriptor: (int)desc closeOnDealloc: (BOOL)flag { self = [super init]; if (self) @@ -506,14 +519,14 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) return self; } -- (id)initWithNativeHandle:(void*)hdl +- (id)initWithNativeHandle: (void*)hdl { - return [self initWithFileDescriptor:(int)hdl closeOnDealloc:NO]; + return [self initWithFileDescriptor: (int)hdl closeOnDealloc: NO]; } -- (id)initWithNativeHandle:(void*)hdl closeOnDealloc:(BOOL)flag +- (id)initWithNativeHandle: (void*)hdl closeOnDealloc: (BOOL)flag { - return [self initWithFileDescriptor:(int)hdl closeOnDealloc:flag]; + return [self initWithFileDescriptor: (int)hdl closeOnDealloc: flag]; } - (void)checkAccept @@ -525,7 +538,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) } if (readInfo) { - id operation = [readInfo objectForKey:NotificationKey]; + id operation = [readInfo objectForKey: NotificationKey]; if (operation == NSFileHandleConnectionAcceptedNotification) { @@ -549,8 +562,8 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) } if ([writeInfo count] > 0) { - id info = [writeInfo objectAtIndex:0]; - id operation = [info objectForKey:NotificationKey]; + id info = [writeInfo objectAtIndex: 0]; + id operation = [info objectForKey: NotificationKey]; if (operation == GSFileHandleConnectCompletionNotification) { @@ -574,7 +587,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) } if (readInfo) { - id operation = [readInfo objectForKey:NotificationKey]; + id operation = [readInfo objectForKey: NotificationKey]; if (operation == NSFileHandleConnectionAcceptedNotification) { @@ -598,8 +611,8 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) } if ([writeInfo count] > 0) { - id info = [writeInfo objectAtIndex:0]; - id operation = [info objectForKey:NotificationKey]; + id info = [writeInfo objectAtIndex: 0]; + id operation = [info objectForKey: NotificationKey]; if (operation == GSFileHandleConnectCompletionNotification) { @@ -634,12 +647,12 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) [self checkRead]; if (isNonBlocking == YES) [self setNonBlocking: NO]; - d = [NSMutableData dataWithCapacity:0]; + d = [NSMutableData dataWithCapacity: 0]; if (isStandardFile) { while ((len = read(descriptor, buf, sizeof(buf))) > 0) { - [d appendBytes:buf length:len]; + [d appendBytes: buf length: len]; } } else @@ -668,7 +681,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) } if ((len = read(descriptor, buf, count)) > 0) { - [d appendBytes:buf length:len]; + [d appendBytes: buf length: len]; } } } @@ -690,10 +703,10 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) [self checkRead]; if (isNonBlocking == YES) [self setNonBlocking: NO]; - d = [NSMutableData dataWithCapacity:0]; + d = [NSMutableData dataWithCapacity: 0]; while ((len = read(descriptor, buf, sizeof(buf))) > 0) { - [d appendBytes:buf length:len]; + [d appendBytes: buf length: len]; } if (len < 0) { @@ -704,7 +717,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) return d; } -- (NSData*)readDataOfLength:(unsigned int)len +- (NSData*)readDataOfLength: (unsigned int)len { NSMutableData* d; int pos; @@ -721,11 +734,11 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) format: @"unable to read from descriptor - %s", strerror(errno)]; } - [d setLength:pos]; + [d setLength: pos]; return d; } -- (void)writeData:(NSData*)item +- (void)writeData: (NSData*)item { int rval = 0; const void* ptr = [item bytes]; @@ -757,74 +770,74 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) // Asynchronous I/O operations -- (void)acceptConnectionInBackgroundAndNotifyForModes:(NSArray*)modes +- (void)acceptConnectionInBackgroundAndNotifyForModes: (NSArray*)modes { [self checkAccept]; readPos = 0; [readInfo release]; - readInfo = [[NSMutableDictionary dictionaryWithCapacity:4] retain]; - [readInfo setObject:NSFileHandleConnectionAcceptedNotification - forKey:NotificationKey]; - [self watchReadDescriptorForModes:modes]; + readInfo = [[NSMutableDictionary dictionaryWithCapacity: 4] retain]; + [readInfo setObject: NSFileHandleConnectionAcceptedNotification + forKey: NotificationKey]; + [self watchReadDescriptorForModes: modes]; } - (void)acceptConnectionInBackgroundAndNotify { - [self acceptConnectionInBackgroundAndNotifyForModes:nil]; + [self acceptConnectionInBackgroundAndNotifyForModes: nil]; } -- (void)readInBackgroundAndNotifyForModes:(NSArray*)modes +- (void)readInBackgroundAndNotifyForModes: (NSArray*)modes { [self checkRead]; readPos = 0; [readInfo release]; - readInfo = [[NSMutableDictionary dictionaryWithCapacity:4] retain]; - [readInfo setObject:NSFileHandleReadCompletionNotification - forKey:NotificationKey]; - [readInfo setObject:[NSMutableData dataWithCapacity:0] - forKey:NSFileHandleNotificationDataItem]; - [self watchReadDescriptorForModes:modes]; + readInfo = [[NSMutableDictionary dictionaryWithCapacity: 4] retain]; + [readInfo setObject: NSFileHandleReadCompletionNotification + forKey: NotificationKey]; + [readInfo setObject: [NSMutableData dataWithCapacity: 0] + forKey: NSFileHandleNotificationDataItem]; + [self watchReadDescriptorForModes: modes]; } - (void)readInBackgroundAndNotify { - return [self readInBackgroundAndNotifyForModes:nil]; + return [self readInBackgroundAndNotifyForModes: nil]; } -- (void)readToEndOfFileInBackgroundAndNotifyForModes:(NSArray*)modes +- (void)readToEndOfFileInBackgroundAndNotifyForModes: (NSArray*)modes { [self checkRead]; readPos = 0; [readInfo release]; - readInfo = [[NSMutableDictionary dictionaryWithCapacity:4] retain]; - [readInfo setObject:NSFileHandleReadToEndOfFileCompletionNotification - forKey:NotificationKey]; - [readInfo setObject:[NSMutableData dataWithCapacity:0] - forKey:NSFileHandleNotificationDataItem]; - [self watchReadDescriptorForModes:modes]; + readInfo = [[NSMutableDictionary dictionaryWithCapacity: 4] retain]; + [readInfo setObject: NSFileHandleReadToEndOfFileCompletionNotification + forKey: NotificationKey]; + [readInfo setObject: [NSMutableData dataWithCapacity: 0] + forKey: NSFileHandleNotificationDataItem]; + [self watchReadDescriptorForModes: modes]; } - (void)readToEndOfFileInBackgroundAndNotify { - return [self readToEndOfFileInBackgroundAndNotifyForModes:nil]; + return [self readToEndOfFileInBackgroundAndNotifyForModes: nil]; } -- (void)waitForDataInBackgroundAndNotifyForModes:(NSArray*)modes +- (void)waitForDataInBackgroundAndNotifyForModes: (NSArray*)modes { [self checkRead]; readPos = 0; [readInfo release]; - readInfo = [[NSMutableDictionary dictionaryWithCapacity:4] retain]; - [readInfo setObject:NSFileHandleDataAvailableNotification - forKey:NotificationKey]; - [readInfo setObject:[NSMutableData dataWithCapacity:0] - forKey:NSFileHandleNotificationDataItem]; - [self watchReadDescriptorForModes:modes]; + readInfo = [[NSMutableDictionary dictionaryWithCapacity: 4] retain]; + [readInfo setObject: NSFileHandleDataAvailableNotification + forKey: NotificationKey]; + [readInfo setObject: [NSMutableData dataWithCapacity: 0] + forKey: NSFileHandleNotificationDataItem]; + [self watchReadDescriptorForModes: modes]; } - (void)waitForDataInBackgroundAndNotify { - return [self waitForDataInBackgroundAndNotifyForModes:nil]; + return [self waitForDataInBackgroundAndNotifyForModes: nil]; } // Seeking within a file @@ -859,7 +872,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) return (unsigned long long)result; } -- (void)seekToFileOffset:(unsigned long long)pos +- (void)seekToFileOffset: (unsigned long long)pos { off_t result = -1; @@ -903,34 +916,34 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) (void)sync(); } -- (void)truncateFileAtOffset:(unsigned long long)pos +- (void)truncateFileAtOffset: (unsigned long long)pos { if (isStandardFile && descriptor >= 0) (void)ftruncate(descriptor, pos); - [self seekToFileOffset:pos]; + [self seekToFileOffset: pos]; } -- (void)writeInBackgroundAndNotify:(NSData*)item forModes:(NSArray*)modes +- (void)writeInBackgroundAndNotify: (NSData*)item forModes: (NSArray*)modes { NSMutableDictionary* info; [self checkWrite]; - info = [[NSMutableDictionary dictionaryWithCapacity:4] retain]; - [info setObject:item forKey:NSFileHandleNotificationDataItem]; - [info setObject:GSFileHandleWriteCompletionNotification - forKey:NotificationKey]; + info = [[NSMutableDictionary dictionaryWithCapacity: 4] retain]; + [info setObject: item forKey: NSFileHandleNotificationDataItem]; + [info setObject: GSFileHandleWriteCompletionNotification + forKey: NotificationKey]; if (modes) - [info setObject:modes forKey:NSFileHandleNotificationMonitorModes]; + [info setObject: modes forKey: NSFileHandleNotificationMonitorModes]; - [writeInfo addObject:info]; + [writeInfo addObject: info]; [info release]; [self watchWriteDescriptor]; } -- (void)writeInBackgroundAndNotify:(NSData*)item; +- (void)writeInBackgroundAndNotify: (NSData*)item; { - [self writeInBackgroundAndNotify:item forModes:nil]; + [self writeInBackgroundAndNotify: item forModes: nil]; } - (void)postReadNotification @@ -942,39 +955,39 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) [self ignoreReadDescriptor]; readInfo = nil; - modes = (NSArray*)[info objectForKey:NSFileHandleNotificationMonitorModes]; - name = (NSString*)[info objectForKey:NotificationKey]; + modes = (NSArray*)[info objectForKey: NSFileHandleNotificationMonitorModes]; + name = (NSString*)[info objectForKey: NotificationKey]; - n = [NSNotification notificationWithName:name object:self userInfo:info]; + n = [NSNotification notificationWithName: name object: self userInfo: info]; [info release]; /* Retained by the notification. */ - [[NSNotificationQueue defaultQueue] enqueueNotification:n - postingStyle:NSPostASAP - coalesceMask:NSNotificationNoCoalescing - forModes:modes]; + [[NSNotificationQueue defaultQueue] enqueueNotification: n + postingStyle: NSPostASAP + coalesceMask: NSNotificationNoCoalescing + forModes: modes]; } - (void)postWriteNotification { - NSMutableDictionary* info = [writeInfo objectAtIndex:0]; + NSMutableDictionary* info = [writeInfo objectAtIndex: 0]; NSNotification* n; NSArray* modes; NSString* name; [self ignoreWriteDescriptor]; - modes = (NSArray*)[info objectForKey:NSFileHandleNotificationMonitorModes]; - name = (NSString*)[info objectForKey:NotificationKey]; + modes = (NSArray*)[info objectForKey: NSFileHandleNotificationMonitorModes]; + name = (NSString*)[info objectForKey: NotificationKey]; - n = [NSNotification notificationWithName:name object:self userInfo:info]; + n = [NSNotification notificationWithName: name object: self userInfo: info]; writePos = 0; - [writeInfo removeObjectAtIndex:0]; /* Retained by notification. */ + [writeInfo removeObjectAtIndex: 0]; /* Retained by notification. */ - [[NSNotificationQueue defaultQueue] enqueueNotification:n - postingStyle:NSPostASAP - coalesceMask:NSNotificationNoCoalescing - forModes:modes]; + [[NSNotificationQueue defaultQueue] enqueueNotification: n + postingStyle: NSPostASAP + coalesceMask: NSNotificationNoCoalescing + forModes: modes]; [self watchWriteDescriptor]; /* In case of queued writes. */ } @@ -1004,7 +1017,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) modes = nil; if (readInfo) - modes = (NSArray*)[readInfo objectForKey:NSFileHandleNotificationMonitorModes]; + modes = (NSArray*)[readInfo objectForKey: NSFileHandleNotificationMonitorModes]; if (modes && [modes count]) { @@ -1014,7 +1027,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) { [l removeEvent: (void*)descriptor type: ET_RDESC - forMode: [modes objectAtIndex:i] + forMode: [modes objectAtIndex: i] all: YES]; } } @@ -1038,9 +1051,9 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) if ([writeInfo count] > 0) { - NSMutableDictionary* info = [writeInfo objectAtIndex:0]; + NSMutableDictionary* info = [writeInfo objectAtIndex: 0]; - modes=(NSArray*)[info objectForKey:NSFileHandleNotificationMonitorModes]; + modes=(NSArray*)[info objectForKey: NSFileHandleNotificationMonitorModes]; } if (modes && [modes count]) @@ -1051,7 +1064,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) { [l removeEvent: (void*)descriptor type: ET_WDESC - forMode: [modes objectAtIndex:i] + forMode: [modes objectAtIndex: i] all: YES]; } } @@ -1062,7 +1075,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) all: YES]; } -- (void)watchReadDescriptorForModes:(NSArray*)modes; +- (void)watchReadDescriptorForModes: (NSArray*)modes; { NSRunLoop *l; @@ -1080,9 +1093,9 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) [l addEvent: (void*)descriptor type: ET_RDESC watcher: self - forMode: [modes objectAtIndex:i]]; + forMode: [modes objectAtIndex: i]]; } - [readInfo setObject:modes forKey:NSFileHandleNotificationMonitorModes]; + [readInfo setObject: modes forKey: NSFileHandleNotificationMonitorModes]; } else { @@ -1100,14 +1113,14 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) if ([writeInfo count] > 0) { - NSMutableDictionary* info = [writeInfo objectAtIndex:0]; + NSMutableDictionary* info = [writeInfo objectAtIndex: 0]; NSRunLoop* l = [NSRunLoop currentRunLoop]; NSArray* modes = nil; - modes = [info objectForKey:NSFileHandleNotificationMonitorModes]; + modes = [info objectForKey: NSFileHandleNotificationMonitorModes]; - [self setNonBlocking:YES]; + [self setNonBlocking: YES]; if (modes && [modes count]) { int i; @@ -1117,7 +1130,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) [l addEvent: (void*)descriptor type: ET_WDESC watcher: self - forMode: [modes objectAtIndex:i]]; + forMode: [modes objectAtIndex: i]]; } } else @@ -1139,131 +1152,166 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) if (isNonBlocking == NO) [self setNonBlocking: YES]; - if (type == ET_RDESC) { - operation = [readInfo objectForKey:NotificationKey]; - if (operation == NSFileHandleConnectionAcceptedNotification) { - struct sockaddr_in buf; - int desc; - int blen = sizeof(buf); - NSFileHandle* hdl; + if (type == ET_RDESC) + { + operation = [readInfo objectForKey: NotificationKey]; + if (operation == NSFileHandleConnectionAcceptedNotification) + { + struct sockaddr_in buf; + int desc; + int blen = sizeof(buf); + NSFileHandle* hdl; - desc = accept(descriptor, (struct sockaddr*)&buf, &blen); - if (desc < 0) { - NSString* s; + desc = accept(descriptor, (struct sockaddr*)&buf, &blen); + if (desc < 0) + { + NSString *s; - s = [NSString stringWithFormat:@"Accept attempt failed - %s", + s = [NSString stringWithFormat: @"Accept attempt failed - %s", strerror(errno)]; - [readInfo setObject:s forKey:GSFileHandleNotificationError]; - } - else { // Accept attempt completed. - UnixFileHandle *h; - struct sockaddr_in sin; - int size = sizeof(sin); + [readInfo setObject: s forKey: GSFileHandleNotificationError]; + } + else + { // Accept attempt completed. + UnixFileHandle *h; + struct sockaddr_in sin; + int size = sizeof(sin); - h = [[UnixFileHandle alloc] initWithFileDescriptor:desc]; - getpeername(desc, (struct sockaddr*)&sin, &size); - [h setAddr: &sin]; - [readInfo setObject: h forKey: NSFileHandleNotificationFileHandleItem]; - [h release]; - } - [self postReadNotification]; - } - else if (operation == NSFileHandleDataAvailableNotification) { - [self postReadNotification]; - } - else { - NSMutableData* item; - int length; - int received = 0; - char buf[NETBUF_SIZE]; + h = [[UnixFileHandle alloc] initWithFileDescriptor: desc]; + getpeername(desc, (struct sockaddr*)&sin, &size); + [h setAddr: &sin]; + [readInfo setObject: h + forKey: NSFileHandleNotificationFileHandleItem]; + [h release]; + } + [self postReadNotification]; + } + else if (operation == NSFileHandleDataAvailableNotification) + { + [self postReadNotification]; + } + else + { + NSMutableData *item; + int length; + int received = 0; + char buf[NETBUF_SIZE]; - item = [readInfo objectForKey:NSFileHandleNotificationDataItem]; - length = [item length]; + item = [readInfo objectForKey: NSFileHandleNotificationDataItem]; + length = [item length]; - received = read(descriptor, buf, sizeof(buf)); - if (received == 0) { // Read up to end of file. - [self postReadNotification]; - } - else if (received < 0) { - if (errno != EAGAIN) { - NSString* s; + received = read(descriptor, buf, sizeof(buf)); + if (received == 0) + { // Read up to end of file. + [self postReadNotification]; + } + else if (received < 0) + { + if (errno != EAGAIN) + { + NSString *s; - s = [NSString stringWithFormat:@"Read attempt failed - %s", + s = [NSString stringWithFormat: @"Read attempt failed - %s", strerror(errno)]; - [readInfo setObject:s forKey:GSFileHandleNotificationError]; - [self postReadNotification]; + [readInfo setObject: s forKey: GSFileHandleNotificationError]; + [self postReadNotification]; + } + } + else + { + [item appendBytes: buf length: received]; + if (operation == NSFileHandleReadCompletionNotification) + { + // Read a single chunk of data + [self postReadNotification]; + } + } } - } - else { - [item appendBytes:buf length:received]; - if (operation == NSFileHandleReadCompletionNotification) { - // Read a single chunk of data - [self postReadNotification]; - } - } } - } - else if (type == ET_WDESC) { - NSMutableDictionary* info; + else if (type == ET_WDESC) + { + NSMutableDictionary *info; - info = [writeInfo objectAtIndex:0]; - operation = [info objectForKey:NotificationKey]; - if (operation == GSFileHandleWriteCompletionNotification) { - NSData* item; - int length; - const void* ptr; + info = [writeInfo objectAtIndex: 0]; + operation = [info objectForKey: NotificationKey]; + if (operation == GSFileHandleWriteCompletionNotification) + { + NSData *item; + int length; + const void *ptr; - item = [info objectForKey:NSFileHandleNotificationDataItem]; - length = [item length]; - ptr = [item bytes]; - if (writePos < length) { - int written; + item = [info objectForKey: NSFileHandleNotificationDataItem]; + length = [item length]; + ptr = [item bytes]; + if (writePos < length) + { + int written; - written = write(descriptor, (char*)ptr+writePos, length - writePos); - if (written <= 0) { - if (errno != EAGAIN) { - NSString* s; + written = write(descriptor, (char*)ptr+writePos, length-writePos); + if (written <= 0) + { + if (errno != EAGAIN) + { + NSString *s; - s = [NSString stringWithFormat:@"Write attempt failed - %s", - strerror(errno)]; - [info setObject:s forKey:GSFileHandleNotificationError]; - [self postWriteNotification]; - } + s = [NSString stringWithFormat: + @"Write attempt failed - %s", strerror(errno)]; + [info setObject: s forKey: GSFileHandleNotificationError]; + [self postWriteNotification]; + } + } + else + { + writePos += written; + } + } + if (writePos >= length) + { // Write operation completed. + [self postWriteNotification]; + } } - else { - writePos += written; + else + { // Connection attempt completed. + int result; + int len = sizeof(result); + + if (getsockopt(descriptor, SOL_SOCKET, SO_ERROR, + (char*)&result, &len) == 0 && result != 0) + { + NSString *s; + + s = [NSString stringWithFormat: @"Connect attempt failed - %s", + strerror(result)]; + [info setObject: s forKey: GSFileHandleNotificationError]; + } + else + { + readOK = YES; + writeOK = YES; + } + connectOK = NO; + [self postWriteNotification]; } - } - if (writePos >= length) { // Write operation completed. - [self postWriteNotification]; - } } - else { // Connection attempt completed. - connectOK = NO; - readOK = YES; - writeOK = YES; - [self postWriteNotification]; - } - } } - (NSDate*)timedOutEvent: (void*)data type: (RunLoopEventType)type forMode: (NSString*)mode { - return nil; /* Don't restart timed out events */ + return nil; /* Don't restart timed out events */ } - (void) setAddr: (struct sockaddr_in *)sin { - address = [NSString stringWithCString: (char*)inet_ntoa(sin->sin_addr)]; - [address retain]; - service = [NSString stringWithFormat: @"%d", (int)ntohs(sin->sin_port)]; - [service retain]; - protocol = @"tcp"; + address = [NSString stringWithCString: (char*)inet_ntoa(sin->sin_addr)]; + [address retain]; + service = [NSString stringWithFormat: @"%d", (int)ntohs(sin->sin_port)]; + [service retain]; + protocol = @"tcp"; } -- (void)setNonBlocking:(BOOL)flag +- (void)setNonBlocking: (BOOL)flag { int e; @@ -1294,17 +1342,17 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin) - (NSString*) socketAddress { - return address; + return address; } - (NSString*) socketProtocol { - return protocol; + return protocol; } - (NSString*) socketService { - return service; + return service; } @end