X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fthecheat;a=blobdiff_plain;f=CheatListener.m;fp=CheatListener.m;h=40c4eb034938f8e760b49413746bb95cac244b9f;hp=0000000000000000000000000000000000000000;hb=42cf7bbe564d70233a0d73baee613f209eb00eb6;hpb=2d60a59a8ad195dd0af8f90c8d5b74a69ce7f4fa diff --git a/CheatListener.m b/CheatListener.m new file mode 100644 index 0000000..40c4eb0 --- /dev/null +++ b/CheatListener.m @@ -0,0 +1,182 @@ + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Project: The Cheat +// +// File: CheatListener.m +// Created: Wed Sep 24 2003 +// +// Copyright: 2003 Chaz McGarvey. All rights reserved. +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#import "CheatListener.h" + +#import "CheatServer.h" + +#include + + +@implementation CheatListener + + ++ (NSConnection *)listenerWithDelegate:(id)del port:(int)port remote:(BOOL)remote +{ + NSPort *rPort = [NSPort port], *sPort = [NSPort port]; + NSConnection *connection; + NSArray *array; + + connection = [[NSConnection alloc] initWithReceivePort:rPort sendPort:sPort]; + [connection setRootObject:del]; + + array = [NSArray arrayWithObjects:sPort, rPort, [NSNumber numberWithInt:port], [NSNumber numberWithBool:remote], nil]; + [NSThread detachNewThreadSelector:@selector(listenerThread:) toTarget:self withObject:array]; + + return [connection autorelease]; +} + ++ (void)listenerThread:(NSArray *)array +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSConnection *connection = [NSConnection connectionWithReceivePort:[array objectAtIndex:0] sendPort:[array objectAtIndex:1]]; + CheatListener *object = [[self alloc] initWithRootProxy:[connection rootProxy]]; + + [object listenOnPort:[[array objectAtIndex:2] intValue] remote:[[array objectAtIndex:3] boolValue]]; + [object run]; + [object cleanup]; + + [object release]; + [pool release]; +} + + +- (id)initWithRootProxy:(id)proxy +{ + if ( self = [super init] ) + { + rootProxy = proxy; + sockfd = -1; + } + + return self; +} + + +- (void)listenOnPort:(int)port remote:(BOOL)remote +{ + short family = remote? AF_INET : AF_UNIX; + + int yes = 1; // for setsockopt() + + if ( (sockfd = socket( family, SOCK_STREAM, 0 )) == -1 ) + { + NSLog( @"ERROR: failed to start server because socket() failed" ); + [rootProxy listenerError:@"Network Error" message:@"Server couldn't start. Local can't be cheated."]; + return; + } + + if ( family == AF_INET ) + { + struct sockaddr_in addr; + + addr.sin_family = family; + addr.sin_port = htonl( port ); + addr.sin_addr.s_addr = INADDR_ANY; + + if ( setsockopt( sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int) ) == -1 ) + { + NSLog( @"ERROR: failed to start server because setsockopt() failed" ); + [rootProxy listenerError:@"Network Error" message:@"Server couldn't start. Local can't be cheated."]; + return; + } + + if ( bind( sockfd, (struct sockaddr *)(&addr), sizeof(struct sockaddr) ) == -1 ) + { + NSLog( @"ERROR: failed to start server because bind() failed" ); + [rootProxy listenerError:@"Network Error" message:@"The cheat server could not start, probably because the port is already in use. Local can not be cheated."]; + return; + } + } + else + { + struct sockaddr_un addr; + + addr.sun_family = family; + strncpy( addr.sun_path, TCDefaultListenPath, 103 ); + + remove( TCDefaultListenPath ); + + if ( bind( sockfd, (struct sockaddr *)(&addr), sizeof(addr) ) == -1 ) + { + NSLog( @"ERROR: failed to start server because bind() failed" ); + [rootProxy listenerError:@"Network Error" message:@"The cheat server could not start, probably because the path is already in use. Local can not be cheated."]; + return; + } + } + + if ( listen( sockfd, 50 ) == -1 ) + { + NSLog( @"ERROR: failed to start server because listen() failed" ); + [rootProxy listenerError:@"Network Error" message:@"Server couldn't start. Local can't be cheated."]; + return; + } + + listenRemote = remote; + + [rootProxy listenerListeningWithSocket:sockfd]; +} + +- (void)run +{ + int result; + + NSLog( @"LISTENER start" ); + + if ( listenRemote ) + { + struct sockaddr_in addr; + int addrLen; + + for (;;) + { + addrLen = sizeof(addr); + + if ( (result = accept( sockfd, (struct sockaddr *)(&addr), &addrLen )) == -1 ) + { + break; + } + + [rootProxy listenerReceivedNewConnection:result]; + } + } + else + { + struct sockaddr_un addr; + int addrLen; + + for (;;) + { + addrLen = sizeof(addr); + + if ( (result = accept( sockfd, (struct sockaddr *)(&addr), &addrLen )) == -1 ) + { + break; + } + + [rootProxy listenerReceivedNewConnection:result]; + } + } + + NSLog( @"LISTENER close" ); + + [rootProxy listenerDisconnected]; +} + +- (void)cleanup +{ + if ( listenRemote ) + { + remove( TCDefaultListenPath ); + } +} + + +@end \ No newline at end of file