diff options
Diffstat (limited to 'Liaison/ServerManager.m')
-rw-r--r-- | Liaison/ServerManager.m | 428 |
1 files changed, 428 insertions, 0 deletions
diff --git a/Liaison/ServerManager.m b/Liaison/ServerManager.m new file mode 100644 index 0000000..903c3d5 --- /dev/null +++ b/Liaison/ServerManager.m @@ -0,0 +1,428 @@ +// +// ServerManager.m +// Liaison +// +// Created by Brian Cully on Sun Feb 16 2003. +// Copyright (c) 2003 Brian Cully. All rights reserved. +// +#import "RenIPC.h" +#import "ServerManager.h" + +#import "CopyController.h" +#import "DownloadStatusView.h" +#import "DownloadManager.h" +#import "LiDataTranslator.h" +#import "NIBConnector.h" + +#import <netinet/in.h> +#import <sys/socket.h> +#import <unistd.h> + +@interface ServerManager (NetworkStuff) +- (BOOL)sendCommand: (NSDictionary *)aCmd; +@end + +@interface NSNetService (FileHandleExtensions) +- (NSFileHandle *)fileHandle; +@end + +@implementation ServerManager ++ (NSImage *)fileStoreIcon +{ + NSImage *image; + NSString *iconPath; + + image = [NSImage imageNamed: @"LiBuiltInFunctions RenStoreIcon"]; + if (image == nil) { + iconPath = [[NSBundle bundleForClass: [self class]] pathForResource: @"rendezvous" ofType: @"tiff"]; + image = [[NSImage alloc] initWithContentsOfFile: iconPath]; + [image setName: @"LiBuiltInFunctions RenStoreIcon"]; + } + + return image; +} + +- (id)initWithNetService: (NSNetService *)aService +{ + NSBundle *myBundle; + + self = [super init]; + + [self setService: aService]; + [self setFile: [[self service] fileHandle]]; + if ([self file] == nil) { + [self autorelease]; + return nil; + } + [self setFileStore: [LiFileStore fileStoreWithName: [aService name]]]; + [[self fileStore] setEditable: NO]; + [[self fileStore] setIcon: [[self class] fileStoreIcon]]; + [[self fileStore] setDelegate: self]; + [[self fileStore] addIndexForAttribute: LiGroupsAttribute]; + + theBuffer = [[NSMutableData alloc] init]; + + myBundle = [NSBundle bundleForClass: [self class]]; + + return self; +} + +- (void)dealloc +{ + NSNotificationCenter *defaultCenter; + + [LiLog logAsDebug: @"[ServerManager dealloc]"]; + + defaultCenter = [NSNotificationCenter defaultCenter]; + [defaultCenter removeObserver: self]; + + [self setService: nil]; + [self setFile: nil]; + [self setFileStore: nil]; + [self setBuffer: nil]; + + [super dealloc]; +} + +- (void)startup +{ + NSDictionary *handshake; + NSNotificationCenter *defaultCenter; + + defaultCenter = [NSNotificationCenter defaultCenter]; + [defaultCenter addObserver: self + selector: @selector(browserRead:) + name: NSFileHandleReadCompletionNotification + object: [self file]]; + + handshake = [NSDictionary dictionaryWithObject: @"browser" + forKey: @"type"]; + [self sendCommand: handshake]; + + [[self file] readInBackgroundAndNotify]; +} + +- (void)shutdown +{ + NSNotificationCenter *defaultCenter; + + defaultCenter = [NSNotificationCenter defaultCenter]; + [defaultCenter removeObserver: self + name: NSFileHandleReadCompletionNotification + object: [self file]]; + + [LiFileStore removeStoreWithID: [[self fileStore] storeID]]; + [self setFile: nil]; + [self setFileStore: nil]; + + [defaultCenter postNotificationName: SERVERMANAGERDEATHNOTIFICATION + object: self + userInfo: nil]; +} +@synthesize theBuffer; +@synthesize theFileStore; +@synthesize theFile; +@synthesize theService; +@end + +@implementation ServerManager (Accessors) +- (NSFileHandle *)file +{ + return theFile; +} + +- (void)setFile: (NSFileHandle *)aFile +{ + [aFile retain]; + [theFile release]; + theFile = aFile; +} + +- (NSNetService *)service +{ + return theService; +} + +- (void)setService: (NSNetService *)aService +{ + [aService retain]; + [theService release]; + theService = aService; +} + +- (NSMutableData *)buffer +{ + return theBuffer; +} + +- (void)setBuffer: (NSMutableData *)aBuffer +{ + [aBuffer retain]; + [theBuffer release]; + theBuffer = aBuffer; +} + +- (LiFileStore *)fileStore +{ + return theFileStore; +} + +- (void)setFileStore: (LiFileStore *)aFileStore +{ + [aFileStore retain]; + [theFileStore release]; + theFileStore = aFileStore; +} +@end + +@implementation ServerManager (LiFileStore) +- (BOOL)synchronizeFileStore +{ + return YES; +} + +- (void)synchronizeFileHandle: (LiFileHandle *)aFileHandle + withNewAttributes: (NSMutableDictionary *)someAttributes +{ +} + +- (BOOL)shouldUpdateFileHandle: (LiFileHandle *)aFileHandle +{ + return NO; +} + +- (void)updateFileHandle: (LiFileHandle *)aFileHandle +{ + return; +} + +- (void)openFileHandle: (LiFileHandle *)aFileHandle +{ + NSFileHandle *copySocket; + + [LiLog logAsDebug: @"[ServerManager openFileHandle: %@]", aFileHandle]; + [LiLog indentDebugLog]; + + [LiLog logAsDebug: @"filename: %@", [aFileHandle filename]]; + copySocket = [[self service] fileHandle]; + [[DownloadManager defaultManager] downloadFileHandle: aFileHandle + fromSocket: copySocket + target: self + didFinishSelector: @selector(fileHandleFinishedDownloading:context:errorString:) + withContext: nil]; + [LiLog unindentDebugLog]; +} + +- (void)fileHandleFinishedDownloading: (LiFileHandle *)aFileHandle + context: (void *)someContext + errorString: (NSString *)anError +{ + [LiLog logAsDebug: @"[ServerManager fileHandleFinishedDownloading]"]; + [LiLog indentDebugLog]; + if (anError != nil) { + [LiLog logAsError: @"Couldn't download %@: %@", + [aFileHandle filename], anError]; + } else { + [LiLog logAsDebug: @"File downloaded successfully."]; + } + [LiLog unindentDebugLog]; +} + +- (LiFileHandle *)addURL: (NSURL *)anURL + toFileStore: (LiFileStore *)aFileStore +{ + return nil; +} + +- (NSURL *)urlForFileHandle: (LiFileHandle *)aFileHandle +{ + NSURL *url; + NSString *urlStr; + + urlStr = [NSString stringWithFormat: @"liaison://%@/%@", [[aFileHandle fileStore] name], [aFileHandle fileID]]; + url = [NSURL URLWithString: urlStr]; + return url; +} + +- (NSArray *)defaultValuesForAttribute: (NSString *)anAttribute +{ + return nil; +} + +- (BOOL)addDefaultAttribute: (NSDictionary *)anAttribute toFileStore: (LiFileStore *)aFileStore +{ + return NO; +} + +- (BOOL)changeDefaultValueForAttribute: (NSDictionary *)anAttribute toValue: (id)aValue inFileStore: (LiFileStore *)aFileStore +{ + return NO; +} + +- (BOOL)removeDefaultAttribute: (NSDictionary *)anAttribute fromFileStore: (LiFileStore *)aFileStore +{ + return NO; +} +@end + +@implementation ServerManager (NetworkStuff) +- (BOOL)sendCommand: (NSDictionary *)aCmd +{ + NSData *cmdData; + NSString *errorString; + + errorString = nil; + cmdData = [aCmd encodedData]; + if (cmdData != nil) { + [[self file] writeData: cmdData]; + return YES; + } else + return NO; +} + +- (void)processAddList: (NSArray *)changeList +{ + NSDictionary *fileInfo; + + for (fileInfo in changeList) { + LiFileHandle *file; + + file = [[self fileStore] addFileWithAttributes: fileInfo]; + } + + [[self fileStore] synchronize]; +} + +- (void)processChangeList: (NSArray *)aFileList +{ + NSDictionary *changeDict; + + for (changeDict in aFileList) { + id fileID; + + fileID = [changeDict objectForKey: LiFileHandleAttribute]; + if (fileID != nil) { + LiFileHandle *tmpHandle; + NSEnumerator *attrEnum; + NSString *attribute; + + tmpHandle = [[LiFileHandle alloc] init]; + [tmpHandle setFileStore: [self fileStore]]; + [tmpHandle setFileID: fileID]; + + attrEnum = [changeDict keyEnumerator]; + while ((attribute = [attrEnum nextObject]) != nil) { + if ([attribute compare: LiFileHandleAttribute] != 0) { + [tmpHandle setValue: [changeDict objectForKey: attribute] + forAttribute: attribute]; + } + } + + [tmpHandle release]; + } + } + + [[self fileStore] synchronize]; +} + +- (void)processDeleteList: (NSArray *)aFileList +{ + id fileID; + + for (fileID in aFileList) { + LiFileHandle *tmpFile; + + tmpFile = [[LiFileHandle alloc] init]; + [tmpFile setFileStore: [self fileStore]]; + [tmpFile setFileID: fileID]; + + [[self fileStore] removeFileHandle: tmpFile]; + [tmpFile release]; + } + + [[self fileStore] synchronize]; +} + +- (void)processServerMessage: (NSDictionary *)aMsg +{ + NSString *msgType; + id arg; + + msgType = [aMsg objectForKey: @"type"]; + arg = [aMsg objectForKey: @"arg"]; + if ([msgType isEqualToString: RenHostnameKey]) { + [[self fileStore] setName: arg]; + } else if ([msgType isEqualToString: RenFilesAddedKey]) { + [self processAddList: arg]; + } else if ([msgType isEqualToString: RenFilesChangedKey]) { + [self processChangeList: arg]; + } else if ([msgType isEqualToString: RenFilesRemovedKey]) { + [self processDeleteList: arg]; + } else { + [LiLog logAsError: @"Unknown server message type: '%@'.", msgType]; + } +} + +- (void)processData: (NSData *)someData +{ + NSDictionary *msg; + + [[self buffer] appendData: someData]; + msg = [NSDictionary dictionaryWithEncodedData: [self buffer]]; + if (msg != nil) { + [self setBuffer: [NSMutableData data]]; + [self processServerMessage: msg]; + } +} + +- (void)browserRead: (NSNotification *)aNotification +{ + NSData *data; + NSFileHandle *remoteSocket; + + remoteSocket = [aNotification object]; + data = [[aNotification userInfo] objectForKey: + NSFileHandleNotificationDataItem]; + if ([data length] > 0) + [self processData: data]; + else { + [LiLog logAsDebug: @"browserRead shutdown"]; + [self shutdown]; + } + + [[aNotification object] readInBackgroundAndNotify]; +} +@end + +@implementation NSNetService (FileHandleExtensions) +- (NSFileHandle *)fileHandle +{ + NSArray *serverAddresses; + NSData *data; + NSFileHandle *remoteSocket; + struct sockaddr_in *remoteAddr; + int remotePort, rc; + + serverAddresses = [self addresses]; + if ([serverAddresses count] <= 0) + return nil; + + data = [serverAddresses objectAtIndex: 0]; + remoteAddr = (struct sockaddr_in *)[data bytes]; + + remotePort = socket(AF_INET, SOCK_STREAM, 0); + remoteSocket = [[NSFileHandle alloc] initWithFileDescriptor: remotePort + closeOnDealloc: YES]; + [remoteSocket autorelease]; + + rc = connect(remotePort, + (struct sockaddr *)remoteAddr, + sizeof(*remoteAddr)); + if (rc == -1) { + [LiLog logAsWarning: @"couldn't connect to %@: %s.", [self name], strerror(errno)]; + return nil; + } + + return remoteSocket; +} +@end
\ No newline at end of file |