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