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