diff options
Diffstat (limited to 'Liaison/RenManager.m')
-rw-r--r-- | Liaison/RenManager.m | 357 |
1 files changed, 357 insertions, 0 deletions
diff --git a/Liaison/RenManager.m b/Liaison/RenManager.m new file mode 100644 index 0000000..38323d3 --- /dev/null +++ b/Liaison/RenManager.m @@ -0,0 +1,357 @@ +// +// RenManager.m +// Liaison +// +// Created by Brian Cully on Sun Feb 16 2003. +// Copyright (c) 2003 Brian Cully. All rights reserved. +// +#import "RenIPC.h" +#import "RenManager.h" + +#import "ClientManager.h" +#import "ServerManager.h" + +#import <netinet/in.h> +#import <sys/socket.h> + +@implementation RenManager (NetServiceDelegate) +- (void)serverManagerDied: (NSNotification *)aNotification +{ + ServerManager *deadServer; + + [LiLog logAsDebug: @"server manager died."]; + deadServer = [aNotification object]; + [theServersByName removeObjectForKey: [[deadServer service] name]]; +} + +- (void)clientManagerDied: (NSNotification *)aNotification +{ + ClientManager *client; + + client = [aNotification object]; + if (client != nil) { + [LiLog logAsDebug: @"removing client for %@!", [client file]]; + [theClients removeObjectForKey: [client file]]; + [LiLog logAsDebug: @"removed client!"]; + } +} + +- (void)acceptConnection: (NSNotification *)aNotification +{ + ClientManager *client; + NSDictionary *userInfo; + NSFileHandle *socket; + NSNotificationCenter *defaultCenter; + + userInfo = [aNotification userInfo]; + socket = [userInfo objectForKey: + NSFileHandleNotificationFileHandleItem]; + + client = [[ClientManager alloc] initWithFile: socket + andFileStore: [self fileStore]]; + //[socket release]; + + defaultCenter = [NSNotificationCenter defaultCenter]; + [defaultCenter addObserver: self + selector: @selector(clientManagerDied:) + name: CLIENTMANAGERDEATHNOTIFICATION + object: client]; + + [theClients setObject: client forKey: [client file]]; + [client startup]; + [client release]; + + [[self listenSocket] acceptConnectionInBackgroundAndNotify]; +} + +- (void)netServiceWillPublish:(NSNetService *)sender +{ + theShareIsEnabled = YES; + [self setService: sender]; +} + +- (void)netServiceDidStop: (NSNetService *)sender +{ + theShareIsEnabled = NO; + [self setService: nil]; +} + +- (void)netServiceBrowser: (NSNetServiceBrowser *)aNetServiceBrowser + didFindService: (NSNetService *)aNetService + moreComing: (BOOL)moreComing +{ + [aNetService setDelegate: self]; + [aNetService resolve]; +} + +- (void)netServiceBrowserDidStopSearch: (NSNetServiceBrowser *)browser +{ + [LiLog logAsDebug: @"stopping search."]; +} + +- (void)netServiceWillResolve: (NSNetService *)aNetService +{ +} + +- (void)netServiceDidResolveAddress: (NSNetService *)aNetService +{ + ServerManager *server; + + if ([theServersByName objectForKey: [aNetService name]] == nil) { + server = [[ServerManager alloc] initWithNetService: aNetService]; + if (server != nil) { + [theServersByName setObject: server forKey: [aNetService name]]; + [server startup]; + } + } +} + +// XXX - should set group name to IP address and proceed. +- (void)netService: (NSNetService *)aNetService + didNotResolve: (NSDictionary *)someErrors +{ + [LiLog logAsDebug: @"XXX: Couldn't resolve address for %@.", [aNetService name]]; +} + +- (void)netServiceBrowser: (NSNetServiceBrowser *)aNetServiceBrowser + didRemoveService: (NSNetService *)aNetService + moreComing: (BOOL)moreComing +{ + ServerManager *removedServer; + + [LiLog logAsDebug: @"removing service: %@", [aNetService name]]; + removedServer = [theServersByName objectForKey: [aNetService name]]; + [LiLog logAsDebug: @"\tremoved file store: %@", [[removedServer fileStore] storeID]]; + [removedServer shutdown]; +} +@end + +@implementation RenManager +static RenManager *sharedManager = nil; + ++ (RenManager *)sharedManager +{ + if (sharedManager == nil) + sharedManager = [[RenManager alloc] init]; + return sharedManager; +} + +- (id)init +{ + NSNotificationCenter *defaultCenter; + + self = [super init]; + + defaultCenter = [NSNotificationCenter defaultCenter]; + [defaultCenter addObserver: self + selector: @selector(serverManagerDied:) + name: SERVERMANAGERDEATHNOTIFICATION + object: nil]; + + [self setFileStore: nil]; + + theServersByName = [[NSMutableDictionary alloc] init]; + theClients = [[NSMutableDictionary alloc] init]; + + [self setListenSocket: nil]; + [self setListenPort: nil]; + [self setService: nil]; + [self setBrowser: nil]; + + theShareIsEnabled = NO; + + return self; +} + +- (void)dealloc +{ + NSNotificationCenter *defaultCenter; + + defaultCenter = [NSNotificationCenter defaultCenter]; + [defaultCenter removeObserver: self]; + + [self setFileStore: nil]; + + [theServersByName release]; + [theClients release]; + + [self setListenSocket: nil]; + [self setListenPort: nil]; + [self setService: nil]; + [self setBrowser: nil]; + + [super dealloc]; +} + +- (void)startup +{ + NSNetServiceBrowser *browser; + + if ([[Preferences sharedPreferences] networkEnabled]) + [self startSharing]; + + browser = [[NSNetServiceBrowser alloc] init]; + [browser autorelease]; + [browser setDelegate: self]; + [browser searchForServicesOfType: LiRendezvousPortName + inDomain: @""]; + [self setBrowser: browser]; +} + +- (void)startSharing +{ + NSFileHandle *listenSocket; + NSNetService *service; + NSNotificationCenter *defaultCenter; + NSSocketPort *listenPort; + NSString *hostname; + struct sockaddr *addr; + int port; + + if (theShareIsEnabled) + return; + + defaultCenter = [NSNotificationCenter defaultCenter]; + [defaultCenter addObserver: self + selector: @selector(acceptConnection:) + name: NSFileHandleConnectionAcceptedNotification + object: nil]; + + listenPort = [[NSSocketPort alloc] init]; + [listenPort autorelease]; + listen([listenPort socket], 10); + [self setListenPort: listenPort]; + + listenSocket = [[NSFileHandle alloc] initWithFileDescriptor: [listenPort socket] + closeOnDealloc: YES]; + [listenSocket autorelease]; + [listenSocket acceptConnectionInBackgroundAndNotify]; + [self setListenSocket: listenSocket]; + + hostname = [[Preferences sharedPreferences] hostname]; + addr = (struct sockaddr *)[[listenPort address] bytes]; + if (addr->sa_family == AF_INET6) + port = ((struct sockaddr_in6 *)addr)->sin6_port; + else + port = ((struct sockaddr_in *)addr)->sin_port; + + service = [[NSNetService alloc] initWithDomain: @"" + type: LiRendezvousPortName + name: hostname + port: port]; + [service autorelease]; + [service setDelegate: self]; + [service publish]; +} + +- (void)stopSharing +{ + if (theShareIsEnabled) { + NSNotificationCenter *defaultCenter; + NSEnumerator *clientEnum; + id clientKey; + + [[self service] stop]; + [self setListenSocket: nil]; + + defaultCenter = [NSNotificationCenter defaultCenter]; + [defaultCenter removeObserver: self + name: NSFileHandleConnectionAcceptedNotification + object: nil]; + + clientEnum = [theClients keyEnumerator]; + while ((clientKey = [clientEnum nextObject]) != nil) { + ClientManager *client; + + [LiLog logAsDebug: @"shutting down client"]; + client = [theClients objectForKey: clientKey]; + [client shutdown]; + } + [LiLog logAsDebug: @"sharing stopped."]; + } +} + +- (void)updateHostname +{ + if (theShareIsEnabled) { + ClientManager *client; + NSEnumerator *clientEnum; + + clientEnum = [theClients objectEnumerator]; + while ((client = [clientEnum nextObject]) != nil) { + [client setHostname: [[Preferences sharedPreferences] hostname]]; + [client sendHostname]; + } + } +} +@synthesize theBrowser; +@synthesize theServersByName; +@synthesize theService; +@synthesize theListenSocket; +@synthesize theFileStore; +@synthesize theShareIsEnabled; +@synthesize theClients; +@synthesize theListenPort; +@end + +@implementation RenManager (Accessors) +- (NSNetServiceBrowser *)browser +{ + return theBrowser; +} + +- (void)setBrowser: (NSNetServiceBrowser *)aBrowser +{ + [aBrowser retain]; + [theBrowser release]; + theBrowser = aBrowser; +} + +- (NSSocketPort *)listenPort +{ + return theListenPort; +} + +- (void)setListenPort: (NSSocketPort *)aPort +{ + [aPort retain]; + [theListenPort release]; + theListenPort = aPort; +} + +- (NSFileHandle *)listenSocket +{ + return theListenSocket; +} + +- (void)setListenSocket: (NSFileHandle *)aSocket +{ + [aSocket retain]; + [theListenSocket release]; + theListenSocket = aSocket; +} + +- (NSNetService *)service +{ + return theService; +} + +- (void)setService: (NSNetService *)aService +{ + [aService retain]; + [theService release]; + theService = aService; +} + +- (LiFileStore *)fileStore +{ + return theFileStore; +} + +- (void)setFileStore: (LiFileStore *)aFileStore +{ + [aFileStore retain]; + [theFileStore release]; + theFileStore = aFileStore; +} +@end
\ No newline at end of file |