Added ITFoundation launch at login, but it doesn'ty work. Other small fixes for netwo...
[MenuTunes.git] / NetworkController.m
1 /*
2  *      MenuTunes
3  *  NetworkController
4  *    Rendezvous network controller
5  *
6  *  Original Author : Kent Sutherland <ksuther@ithinksw.com>
7  *   Responsibility : Kent Sutherland <ksuther@ithinksw.com>
8  *
9  *  Copyright (c) 2003 iThink Software.
10  *  All Rights Reserved
11  *
12  */
13
14 #import "NetworkController.h"
15 #import "MainController.h"
16 #import "NetworkObject.h"
17 #import "PreferencesController.h"
18 #import <ITFoundation/ITDebug.h>
19 #import <ITFoundation/ITFoundation.h>
20
21 static NetworkController *sharedController;
22
23 @implementation NetworkController
24
25 + (NetworkController *)sharedController
26 {
27     return sharedController;
28 }
29
30 - (id)init
31 {
32     if ( (self = [super init]) ) {
33         sharedController = self;
34         browser = [[NSNetServiceBrowser alloc] init];
35         [browser setDelegate:self];
36         rootObject = [[NetworkObject alloc] init];
37         serverPort = [[NSSocketPort alloc] initWithTCPPort:SERVER_PORT];
38     }
39     return self;
40 }
41
42 - (void)dealloc
43 {
44     [self disconnect];
45     if (serverOn) {
46         [serverConnection release];
47     }
48     [serverPass release];
49     [clientPass release];
50     [serverPort release];
51     [rootObject release];
52     [clientProxy release];
53     [remoteServices release];
54     [browser release];
55     [service stop];
56     [service release];
57     [super dealloc];
58 }
59
60 - (void)startRemoteServerSearch
61 {
62     [browser searchForServicesOfType:@"_mttp._tcp." inDomain:@""];
63     [remoteServices release];
64     remoteServices = [[NSMutableArray alloc] init];
65 }
66
67 - (void)stopRemoteServerSearch
68 {
69     [browser stop];
70 }
71
72 - (void)setServerStatus:(BOOL)status
73 {
74     if (!serverOn && status) {
75         NSString *name = [[NSUserDefaults standardUserDefaults] stringForKey:@"sharedPlayerName"];
76         unsigned char buffer;
77         NSData *fullPass;
78         //Turn on
79         NS_DURING
80             serverConnection = [[NSConnection alloc] initWithReceivePort:serverPort
81                                                      sendPort:serverPort];
82             [serverConnection setRootObject:rootObject];
83             [rootObject makeValid];
84             [serverConnection registerName:@"ITMTPlayerHost"];
85         NS_HANDLER
86             [serverConnection setRootObject:nil];
87             [serverConnection release];
88             [serverPort release];
89             ITDebugLog(@"Error starting server!");
90             return;
91         NS_ENDHANDLER
92         ITDebugLog(@"Started server.");
93         if (!name) {
94             name = @"MenuTunes Shared Player";
95         }
96         service = [[NSNetService alloc] initWithDomain:@""
97                                         type:@"_mttp._tcp."
98                                         name:name
99                                         port:SERVER_PORT];
100         fullPass = [[NSUserDefaults standardUserDefaults] dataForKey:@"sharedPlayerPassword"];
101         if ([fullPass length]) {
102             [fullPass getBytes:&buffer range:NSMakeRange(6, 4)];
103             [serverPass release];
104             serverPass = [[NSData alloc] initWithBytes:&buffer length:strlen(&buffer)];
105         } else {
106             serverPass = nil;
107         }
108         [service publish];
109         serverOn = YES;
110         ITDebugLog(@"Server service published.");
111     } else if (serverOn && !status && [serverConnection isValid]) {
112         //Turn off
113         [service stop];
114         [service release];
115         [rootObject invalidate];
116         [serverConnection registerName:nil];
117         [serverConnection invalidate];
118         //[serverConnection setRootObject:nil];
119         //[[serverConnection sendPort] autorelease];
120         [serverConnection release];
121         ITDebugLog(@"Stopped server.");
122         serverOn = NO;
123     }
124 }
125
126 - (int)connectToHost:(NSString *)host
127 {
128     NSData *fullPass = [[NSUserDefaults standardUserDefaults] dataForKey:@"connectPassword"];
129     unsigned char buffer;
130     ITDebugLog(@"Connecting to host: %@", host);
131     [remoteHost release];
132     remoteHost = [host copy];
133     if (fullPass) {
134         [fullPass getBytes:&buffer range:NSMakeRange(6, 4)];
135         [clientPass release];
136         clientPass = [[NSData alloc] initWithBytes:&buffer length:strlen(&buffer)];
137     } else {
138         clientPass = nil;
139     }
140     NS_DURING
141         clientPort = [[NSSocketPort alloc] initRemoteWithTCPPort:SERVER_PORT
142                                            host:host];
143         clientConnection = [[NSConnection connectionWithReceivePort:nil sendPort:clientPort] retain];
144         [clientConnection setReplyTimeout:5];
145         clientProxy = [[clientConnection rootProxy] retain];
146         connectedToServer = YES;
147     NS_HANDLER
148         [clientConnection release];
149         [clientPort release];
150         ITDebugLog(@"Connection to host failed: %@", host);
151         return 0;
152     NS_ENDHANDLER
153     
154     if (!clientProxy) {
155         ITDebugLog(@"Null proxy! Couldn't connect!");
156         [self disconnect];
157         return NO;
158     }
159     
160     if ([clientProxy requiresPassword]) {
161         ITDebugLog(@"Server requires password.");
162         //Check to see if a password is set in defaults
163         if ([[NSUserDefaults standardUserDefaults] dataForKey:@"connectPassword"] == nil) {
164             ITDebugLog(@"Asking for password.");
165             if (![[PreferencesController sharedPrefs] showPasswordPanel]) {
166                 ITDebugLog(@"Giving up connection attempt.");
167                 [self disconnect];
168                 return -1;
169             }
170         }
171         
172         //Send the password
173         ITDebugLog(@"Sending password.");
174         while (![clientProxy sendPassword:[[NSUserDefaults standardUserDefaults] dataForKey:@"connectPassword"]]) {
175             ITDebugLog(@"Invalid password!");
176             if (![[PreferencesController sharedPrefs] showInvalidPasswordPanel]) {
177                 ITDebugLog(@"Giving up connection attempt.");
178                 [self disconnect];
179                 return -1;
180             }
181         }
182     }
183     
184     ITDebugLog(@"Connected to host: %@", host);
185     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(disconnect) name:NSConnectionDidDieNotification object:clientConnection];
186     return 1;
187 }
188
189 - (BOOL)disconnect
190 {
191     ITDebugLog(@"Disconnecting from host.");
192     connectedToServer = NO;
193     [remoteHost release];
194     remoteHost = nil;
195     [[NSNotificationCenter defaultCenter] removeObserver:self];
196     [clientProxy release];
197     [clientConnection release];
198     return YES;
199 }
200
201 - (BOOL)checkForServerAtHost:(NSString *)host
202 {
203     NSData *fullPass = [[NSUserDefaults standardUserDefaults] dataForKey:@"connectPassword"];
204     unsigned char buffer;
205     NSConnection *testConnection;
206     NSSocketPort *testPort;
207     NetworkObject *tempProxy;
208     BOOL valid;
209     ITDebugLog(@"Checking for shared remote at %@.", host);
210     if (fullPass) {
211         [fullPass getBytes:&buffer range:NSMakeRange(6, 4)];
212         [clientPass release];
213         clientPass = [[NSData alloc] initWithBytes:&buffer length:strlen(&buffer)];
214     } else {
215         clientPass = nil;
216     }
217     
218     NS_DURING
219         testPort = [[NSSocketPort alloc] initRemoteWithTCPPort:SERVER_PORT
220                                          host:host];
221         testConnection = [[NSConnection connectionWithReceivePort:nil sendPort:testPort] retain];
222         [testConnection setReplyTimeout:2];
223         tempProxy = (NetworkObject *)[testConnection rootProxy];
224         [tempProxy serverName];
225         valid = [tempProxy isValid];
226     NS_HANDLER
227         ITDebugLog(@"Connection to host failed: %@", host);
228         [testConnection release];
229         [testPort release];
230         return NO;
231     NS_ENDHANDLER
232     
233     if (!clientProxy) {
234         ITDebugLog(@"Null proxy! Couldn't connect!");
235         [testConnection release];
236         [testPort release];
237         return NO;
238     }
239     [testConnection release];
240     [testPort release];
241     return valid;
242 }
243
244 - (void)resetServerName
245 {
246     if ([self isServerOn]) {
247         [service stop];
248         [service release];
249         service = [[NSNetService alloc] initWithDomain:@""
250                                         type:@"_mttp._tcp."
251                                         name:[[NSUserDefaults standardUserDefaults] stringForKey:@"sharedPlayerName"]
252                                         port:SERVER_PORT];
253     }
254 }
255
256 - (BOOL)isServerOn
257 {
258     return serverOn;
259 }
260
261 - (BOOL)isClientConnected
262 {
263     return clientConnected;
264 }
265
266 - (BOOL)isConnectedToServer
267 {
268     return connectedToServer;
269 }
270
271 - (NSString *)remoteHost
272 {
273     return remoteHost;
274 }
275
276 - (NetworkObject *)networkObject
277 {
278     return clientProxy;
279 }
280
281 - (NSArray *)remoteServices
282 {
283     return remoteServices;
284 }
285
286 - (void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser didFindService:(NSNetService *)aNetService moreComing:(BOOL)moreComing
287 {
288     ITDebugLog(@"Found service named %@.", [aNetService name]);
289     [remoteServices addObject:aNetService];
290     [aNetService setDelegate:self];
291     [aNetService resolve];
292     if (!moreComing) {
293         [[NSNotificationCenter defaultCenter] postNotificationName:@"ITMTFoundNetService" object:nil];
294     }
295 }
296
297 - (void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser didRemoveService:(NSNetService*)aNetService moreComing:(BOOL)moreComing
298 {
299     ITDebugLog(@"Removed service named %@.", [aNetService name]);
300     [remoteServices removeObject:aNetService];
301     if (!moreComing) {
302         [[NSNotificationCenter defaultCenter] postNotificationName:@"ITMTFoundNetService" object:nil];
303     }
304 }
305
306 - (void)netServiceDidResolveAddress:(NSNetService *)sender
307 {
308     ITDebugLog(@"Resolved service named %@.", [sender name]);
309     [[NSNotificationCenter defaultCenter] postNotificationName:@"ITMTFoundNetService" object:nil];
310     [sender stop];
311 }
312
313 - (void)netServiceWillResolve:(NSNetService *)sender
314 {
315     ITDebugLog(@"Resolving service named %@.", [sender name]);
316 }
317
318 - (void)netService:(NSNetService *)sender didNotResolve:(NSDictionary *)errorDict
319 {
320     ITDebugLog(@"Error resolving service %@.", errorDict);
321 }
322
323 @end