2 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 // File: AppController.m
6 // Created: Wed Aug 13 2003
8 // Copyright: 2003 Chaz McGarvey. All rights reserved.
9 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11 #import "AppController.h"
13 #include "cheat_shared.h"
15 #import "AboutBoxController.h"
16 #import "PreferenceController.h"
17 #import "NetTrafficController.h"
19 #import "CheatListener.h"
20 #import "CheatServer.h"
22 #import "ServerHolder.h"
25 @implementation AppController
29 NSMutableDictionary
*defaults
= [NSMutableDictionary dictionary
];
32 // change the socket path to reside in the home directory of the current user
33 strncpy( temp
, [NSHomeDirectory() lossyCString
], 103 );
34 strncat( temp
, TCDefaultListenPath
, 103 - strlen(TCDefaultListenPath
) );
35 strncpy( TCDefaultListenPath
, temp
, 103 );
37 [defaults setObject
:[NSNumber numberWithBool
:TCGlobalPlaySounds
] forKey
:TCPlaySoundsPref
];
38 [defaults setObject
:[NSNumber numberWithBool
:TCGlobalWindowsOnTop
] forKey
:TCWindowsOnTopPref
];
39 [defaults setObject
:[NSNumber numberWithBool
:TCGlobalAllowRemote
] forKey
:TCAllowRemotePref
];
40 [defaults setObject
:[NSNumber numberWithInt
:TCGlobalListenPort
] forKey
:TCListenPortPref
];
41 [defaults setObject
:[NSString stringWithFormat
:@
"%@'s Computer", NSFullUserName()] forKey
:TCBroadcastNamePref
];
43 [[NSUserDefaults standardUserDefaults
] registerDefaults
:defaults
];
45 TCGlobalPlaySounds
= [[NSUserDefaults standardUserDefaults
] integerForKey
:TCPlaySoundsPref
];
46 TCGlobalWindowsOnTop
= [[NSUserDefaults standardUserDefaults
] integerForKey
:TCWindowsOnTopPref
];
47 TCGlobalListenPort
= [[NSUserDefaults standardUserDefaults
] integerForKey
:TCListenPortPref
];
48 TCGlobalAllowRemote
= [[NSUserDefaults standardUserDefaults
] boolForKey
:TCAllowRemotePref
];
53 if ( self = [super init
] )
55 servers
= [[NSMutableArray alloc
] init
];
57 [self listenOnPort
:TCGlobalListenPort remote
:TCGlobalAllowRemote
];
58 [self broadcastWithName
:TCGlobalBroadcastName
];
60 // set up the network browser
61 browser
= [[NSNetServiceBrowser alloc
] init
];
62 [browser setDelegate
:self];
63 [browser searchForServicesOfType
:@
"_cheat._tcp." inDomain
:@
"local."];
65 serverList
= [[NSMutableArray alloc
] init
];
67 [self setDelegate
:self];
74 - (void)listenOnPort
:(int)port remote
:(BOOL)remote
80 waitingToListen
= YES
;
81 connectionPort
= port
;
82 connectionRemote
= remote
;
86 connection
= [[CheatListener listenerWithDelegate
:self port
:port remote
:remote
] retain
];
87 connectionPort
= port
;
88 connectionRemote
= remote
;
97 [connection release
], connection
= nil;
102 - (void)broadcastWithName
:(NSString
*)name
104 if ( TCGlobalAllowRemote
)
106 [self stopBroadcast
];
108 service
= [[NSNetService alloc
] initWithDomain
:@
"local." type
:@
"_cheat._tcp." name
:name port
:TCGlobalListenPort
];
109 [service setDelegate
:self];
114 - (void)stopBroadcast
116 [service stop
], service
= nil;
120 - (IBAction
)showAboutBoxWindow
:(id)sender
122 if ( !aboutBoxController
)
124 aboutBoxController
= [[AboutBoxController alloc
] init
];
127 [aboutBoxController showWindow
:self];
130 - (IBAction
)showPreferenceWindow
:(id)sender
132 if ( !preferenceController
)
134 preferenceController
= [[PreferenceController alloc
] initWithDelegate
:self];
137 [preferenceController showWindow
:self];
140 - (IBAction
)showNetTrafficWindow
:(id)sender
142 if ( !netTrafficController
)
144 netTrafficController
= [[NetTrafficController alloc
] initWithDelegate
:self];
147 [netTrafficController showWindow
:self];
151 - (IBAction
)launchHelpFile
:(id)sender
153 //[[NSWorkspace sharedWorkspace] openFile:[[NSBundle mainBundle] pathForResource:@"Read Me" ofType:@"html"] withApplication:@"Safari"];
154 [[NSWorkspace sharedWorkspace
] openURL
:[NSURL fileURLWithPath
:[[NSBundle mainBundle
] pathForResource
:@
"Read Me" ofType
:@
"pdf"]]];
157 - (IBAction
)launchWebsiteMenu
:(id)sender
163 - (NSArray
*)serverList
171 [[NSNotificationCenter defaultCenter
] removeObserver
:self];
174 [self stopBroadcast
];
179 [serverList release
];
185 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
186 %%%%%%%%%%%%%%%%%%%%%% PreferenceControlling
187 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
190 - (void)preferenceAllowRemoteChanged
:(BOOL)allow
192 [self listenOnPort
:TCGlobalListenPort remote
:allow
];
196 [self broadcastWithName
:TCGlobalBroadcastName
];
200 [self stopBroadcast
];
203 [netTrafficController allowRemoteChanged
:allow
];
206 - (void)preferenceListenPortChanged
:(int)port
208 [self listenOnPort
:port remote
:TCGlobalAllowRemote
];
209 [self broadcastWithName
:TCGlobalBroadcastName
];
211 [netTrafficController listenPortChanged
:port
];
214 - (void)preferenceBroadcastNameChanged
:(NSString
*)name
216 [self broadcastWithName
:name
];
218 [netTrafficController broadcastNameChanged
:name
];
222 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
223 %%%%%%%%%%%%%%%%%%%%%% NetTrafficControlling
224 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
227 - (int)netTrafficConnectionCount
229 return [servers count
];
232 - (NSArray
*)netTrafficConnectionList
237 - (void)netTrafficKillConnection
:(int)index
239 NSLog( @
"kill connection" );
241 close( [[servers objectAtIndex
:index
] sockfd
] );
245 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
246 %%%%%%%%%%%%%%%%%%%%%% ListenerDelegate
247 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
250 - (void)listenerListeningWithSocket
:(int)sock
254 TCGlobalListening
= YES
;
255 [[NSNotificationCenter defaultCenter
] postNotificationName
:@
"TCListenerStarted" object
:nil];
258 - (void)listenerDisconnected
260 if ( waitingToListen
)
262 waitingToListen
= NO
;
263 connection
= [[CheatListener listenerWithDelegate
:self port
:connectionPort remote
:connectionRemote
] retain
];
270 TCGlobalListening
= NO
;
271 [[NSNotificationCenter defaultCenter
] postNotificationName
:@
"TCListenerStopped" object
:nil];
274 - (void)listenerError
:(NSString
*)error message
:(NSString
*)message
276 NSRunCriticalAlertPanel( error
, message
, @
"OK", nil, nil );
279 - (void)listenerReceivedNewConnection
:(int)sock
281 [servers addObject
:[ServerHolder holderWithConnection
:[CheatServer serverWithDelegate
:self socket
:sock
] socket
:sock
]];
285 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
286 %%%%%%%%%%%%%%%%%%%%%% ServerDelegate
287 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
290 - (void)server
:(CheatServer
*)server connectedWithSocket
:(int)sock
292 int i
, top
= [servers count
];
294 for ( i
= 0; i
< top
; i
++ )
296 if ( [(ServerHolder
*)[servers objectAtIndex
:i
] sockfd
] == sock
)
298 [(ServerHolder
*)[servers objectAtIndex
:i
] setServer
:server
];
303 [netTrafficController connectionListChanged
];
306 - (void)serverDisconnected
:(CheatServer
*)server
308 int i
, top
= [servers count
];
310 for ( i
= 0; i
< top
; i
++ )
312 if ( [(ServerHolder
*)[servers objectAtIndex
:i
] server
] == server
)
314 [servers removeObjectAtIndex
:i
];
319 [netTrafficController connectionListChanged
];
322 - (void)server
:(CheatServer
*)server changedAddress
:(NSString
*)address
324 int i
, top
= [servers count
];
326 for ( i
= 0; i
< top
; i
++ )
328 if ( [(ServerHolder
*)[servers objectAtIndex
:i
] server
] == server
)
330 [(ServerHolder
*)[servers objectAtIndex
:i
] setAddress
:address
];
335 [netTrafficController connectionListChanged
];
338 - (void)server
:(CheatServer
*)server changedAction
:(NSString
*)action
340 int i
, top
= [servers count
];
342 for ( i
= 0; i
< top
; i
++ )
344 if ( [(ServerHolder
*)[servers objectAtIndex
:i
] server
] == server
)
346 [(ServerHolder
*)[servers objectAtIndex
:i
] setAction
:action
];
351 [netTrafficController connectionListChanged
];
354 - (NSArray
*)serverProcessList
356 return [[NSWorkspace sharedWorkspace
] launchedApplications
];
359 - (pid_t
)serverFirstProcess
361 return (pid_t
)[[[[[NSWorkspace sharedWorkspace
] launchedApplications
] objectAtIndex
:0] objectForKey
:@
"NSApplicationProcessIdentifier"] intValue
];
365 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
366 %%%%%%%%%%%%%%%%%%%%%% NetService Delegate
367 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
370 - (void)netServiceWillPublish
:(NSNetService
*)sender
372 NSLog( @
"service will publish" );
376 - (void)netService
:(NSNetService
*)sender didNotPublish
:(NSDictionary
*)errorDict
378 NSLog( @
"service did not publish" );
380 if ( [[errorDict objectForKey
:@
"NSNetServicesErrorCode"] intValue
] == NSNetServicesCollisionError
)
382 [self broadcastWithName
:[NSString stringWithFormat
:@
"%@ %i", TCGlobalBroadcastName
, TCGlobalAlternateBroadcastNameCount
++]];
386 NSRunCriticalAlertPanel( @
"Network Error", @
"Server couldn't broadcast. Local can't be cheated by remote computers.", @
"OK", nil, nil );
390 - (void)netServiceDidStop
:(NSNetService
*)sender
392 NSLog( @
"service stopped" );
397 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
398 %%%%%%%%%%%%%%%%%%%%%% NSNetServiceBrowser Delegate
399 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
402 - (void)netServiceBrowser
:(NSNetServiceBrowser
*)browser didFindService
:(NSNetService
*)aService moreComing
:(BOOL)more
404 // a server has broadcast; not much use until it's resolved.
405 [aService setDelegate
:self];
409 - (void)netServiceDidResolveAddress
:(NSNetService
*)aService
411 int i
, top
= [serverList count
];
413 // ignore if this is the local server.
414 if ( TCGlobalAllowRemote
&& [[aService name
] isEqualToString
:TCGlobalBroadcastName
] )
419 // ignore if the server name is already in the list.
420 for ( i
= 0; i
< top
; i
++ )
422 if ( [[aService name
] isEqualToString
:[(NSNetService
*)[serverList objectAtIndex
:i
] name
]] )
428 [serverList addObject
:aService
];
429 NSLog( @
"server added: %i", [serverList count
] );
431 [[NSNotificationCenter defaultCenter
] postNotificationName
:@
"TCServerFound" object
:aService
];
434 - (void)netServiceBrowser
:(NSNetServiceBrowser
*)browser didRemoveService
:(NSNetService
*)aService moreComing
:(BOOL)more
436 int i
, top
= [serverList count
];
438 for ( i
= 0; i
< top
; i
++ )
440 if ( [[aService name
] isEqualToString
:[(NSNetService
*)[serverList objectAtIndex
:i
] name
]] )
442 [serverList removeObjectAtIndex
:i
];
443 NSLog( @
"server deleted: %i", [serverList count
] );
448 [[NSNotificationCenter defaultCenter
] postNotificationName
:@
"TCServerLost" object
:aService
];