Fixed a crash when unchecking share this player. Also trying to make the
[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 autorelease]];
82             [serverConnection registerName:@"ITMTPlayerHost"];
83         NS_HANDLER
84             [[serverConnection rootObject] 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         [serverConnection registerName:nil];
114         [serverConnection release];
115         ITDebugLog(@"Stopped server.");
116         serverOn = NO;
117     }
118 }
119
120 - (int)connectToHost:(NSString *)host
121 {
122     NSData *fullPass = [[NSUserDefaults standardUserDefaults] dataForKey:@"connectPassword"];
123     unsigned char buffer;
124     ITDebugLog(@"Connecting to host: %@", host);
125     [remoteHost release];
126     remoteHost = [host copy];
127     if (fullPass) {
128         [fullPass getBytes:&buffer range:NSMakeRange(6, 4)];
129         [clientPass release];
130         clientPass = [[NSData alloc] initWithBytes:&buffer length:strlen(&buffer)];
131     } else {
132         clientPass = nil;
133     }
134     NS_DURING
135         clientPort = [[NSSocketPort alloc] initRemoteWithTCPPort:SERVER_PORT
136                                            host:host];
137         clientConnection = [[NSConnection connectionWithReceivePort:nil sendPort:clientPort] retain];
138         [clientConnection setReplyTimeout:5];
139         clientProxy = [[clientConnection rootProxy] retain];
140         connectedToServer = YES;
141     NS_HANDLER
142         [clientConnection release];
143         [clientPort release];
144         ITDebugLog(@"Connection to host failed: %@", host);
145         return 0;
146     NS_ENDHANDLER
147     
148     if (!clientProxy) {
149         ITDebugLog(@"Null proxy! Couldn't connect!");
150         [self disconnect];
151         return NO;
152     }
153     
154     if ([clientProxy requiresPassword]) {
155         ITDebugLog(@"Server requires password.");
156         //Check to see if a password is set in defaults
157         if ([[NSUserDefaults standardUserDefaults] dataForKey:@"connectPassword"] == nil) {
158             ITDebugLog(@"Asking for password.");
159             if (![[PreferencesController sharedPrefs] showPasswordPanel]) {
160                 ITDebugLog(@"Giving up connection attempt.");
161                 [self disconnect];
162                 return -1;
163             }
164         }
165         
166         //Send the password
167         ITDebugLog(@"Sending password.");
168         while (![clientProxy sendPassword:[[NSUserDefaults standardUserDefaults] dataForKey:@"connectPassword"]]) {
169             ITDebugLog(@"Invalid password!");
170             if (![[PreferencesController sharedPrefs] showInvalidPasswordPanel]) {
171                 ITDebugLog(@"Giving up connection attempt.");
172                 [self disconnect];
173                 return -1;
174             }
175         }
176     }
177     
178     ITDebugLog(@"Connected to host: %@", host);
179     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(disconnect) name:NSConnectionDidDieNotification object:clientConnection];
180     return 1;
181 }
182
183 - (BOOL)disconnect
184 {
185     ITDebugLog(@"Disconnecting from host.");
186     connectedToServer = NO;
187     [remoteHost release];
188     remoteHost = nil;
189     [[NSNotificationCenter defaultCenter] removeObserver:self];
190     [clientProxy release];
191     [clientConnection release];
192     return YES;
193 }
194
195 - (BOOL)checkForServerAtHost:(NSString *)host
196 {
197     NSData *fullPass = [[NSUserDefaults standardUserDefaults] dataForKey:@"connectPassword"];
198     unsigned char buffer;
199     NSConnection *testConnection;
200     NSSocketPort *testPort;
201     NetworkObject *tempProxy;
202     BOOL valid;
203     ITDebugLog(@"Checking for shared remote at %@.", host);
204     if (fullPass) {
205         [fullPass getBytes:&buffer range:NSMakeRange(6, 4)];
206         [clientPass release];
207         clientPass = [[NSData alloc] initWithBytes:&buffer length:strlen(&buffer)];
208     } else {
209         clientPass = nil;
210     }
211     
212     NS_DURING
213         testPort = [[NSSocketPort alloc] initRemoteWithTCPPort:SERVER_PORT
214                                          host:host];
215         testConnection = [[NSConnection connectionWithReceivePort:nil sendPort:testPort] retain];
216         [testConnection setReplyTimeout:2];
217         tempProxy = (NetworkObject *)[testConnection rootProxy];
218         [tempProxy serverName];
219         valid = [tempProxy isValid];
220     NS_HANDLER
221         ITDebugLog(@"Connection to host failed: %@", host);
222         [testConnection release];
223         [testPort release];
224         return NO;
225     NS_ENDHANDLER
226     
227     if (!clientProxy) {
228         ITDebugLog(@"Null proxy! Couldn't connect!");
229         [testConnection release];
230         [testPort release];
231         return NO;
232     }
233     [testConnection release];
234     [testPort release];
235     return valid;
236 }
237
238 - (BOOL)isServerOn
239 {
240     return serverOn;
241 }
242
243 - (BOOL)isClientConnected
244 {
245     return clientConnected;
246 }
247
248 - (BOOL)isConnectedToServer
249 {
250     return connectedToServer;
251 }
252
253 - (NSString *)remoteHost
254 {
255     return remoteHost;
256 }
257
258 - (NetworkObject *)networkObject
259 {
260     return clientProxy;
261 }
262
263 - (NSArray *)remoteServices
264 {
265     return remoteServices;
266 }
267
268 - (void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser didFindService:(NSNetService *)aNetService moreComing:(BOOL)moreComing
269 {
270     ITDebugLog(@"Found service named %@.", [aNetService name]);
271     [remoteServices addObject:aNetService];
272     [aNetService setDelegate:self];
273     [aNetService resolve];
274     if (!moreComing) {
275         [[NSNotificationCenter defaultCenter] postNotificationName:@"ITMTFoundNetService" object:nil];
276     }
277 }
278
279 - (void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser didRemoveService:(NSNetService*)aNetService moreComing:(BOOL)moreComing
280 {
281     ITDebugLog(@"Removed service named %@.", [aNetService name]);
282     [remoteServices removeObject:aNetService];
283     if (!moreComing) {
284         [[NSNotificationCenter defaultCenter] postNotificationName:@"ITMTFoundNetService" object:nil];
285     }
286 }
287
288 - (void)netServiceDidResolveAddress:(NSNetService *)sender
289 {
290     ITDebugLog(@"Resolved service named %@.", [sender name]);
291     [[NSNotificationCenter defaultCenter] postNotificationName:@"ITMTFoundNetService" object:nil];
292     [sender stop];
293 }
294
295 - (void)netServiceWillResolve:(NSNetService *)sender
296 {
297     ITDebugLog(@"Resolving service named %@.", [sender name]);
298 }
299
300 - (void)netService:(NSNetService *)sender didNotResolve:(NSDictionary *)errorDict
301 {
302     ITDebugLog(@"Error resolving service %@.", errorDict);
303 }
304
305 @end