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