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