-
-
Notifications
You must be signed in to change notification settings - Fork 134
/
TPConnectionsManager.m
331 lines (254 loc) · 9.73 KB
/
TPConnectionsManager.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
//
// TPConnectionsManager.m
// teleport
//
// Created by JuL on 24/02/06.
// Copyright 2006 abyssoft. All rights reserved.
//
#import "TPConnectionsManager.h"
//#import "TPNetworkConnection_Private.h"
#import "TPPreferencesManager.h"
#import "TPMainController.h"
#import "TPHostsManager.h"
#import "TPTCPSecureSocket.h"
#import "TPLocalHost.h"
#import "TPRemoteHost.h"
#import "TPMessage.h"
static NSString * TPMsgProtocolVersionKey = @"proto-version";
static NSString * TPMsgHostDataKey = @"host-data";
static TPConnectionsManager * _connectionsManager = nil;
@class _TPSocketConnection;
@interface TPConnectionsManager (Internal)
+ (TPMessage*)_identificationMessage;
- (void)_socketConnectionFailed:(_TPSocketConnection*)socketConnection;
- (void)_socketConnection:(_TPSocketConnection*)socketConnection succeededWithNetworkConnection:(TPNetworkConnection*)networkConnection;
@end
@interface _TPSocketConnection : NSObject
{
@public
TPTCPSecureSocket * _socket;
TPRemoteHost * _host;
NSDictionary * _infoDict;
TPNetworkConnection * _connection;
id _delegate;
}
- (instancetype) initWithConnectionToHost:(TPRemoteHost*)remoteHost delegate:(id)delegate infoDict:(NSDictionary*)infoDict NS_DESIGNATED_INITIALIZER;
@property (nonatomic, readonly, strong) TPRemoteHost *host;
@property (nonatomic, readonly, copy) NSDictionary *infoDict;
@property (nonatomic, readonly, unsafe_unretained) id delegate;
@end
@implementation _TPSocketConnection
- (instancetype) initWithConnectionToHost:(TPRemoteHost*)remoteHost delegate:(id)delegate infoDict:(NSDictionary*)infoDict
{
self = [super init];
PRINT_ME;
_host = remoteHost;
_infoDict = infoDict;
_delegate = delegate;
_socket = [[TPTCPSecureSocket alloc] initWithDelegate:self];
BOOL enableEncryption = [[TPLocalHost localHost] pairWithHost:remoteHost hasCapability:TPHostEncryptionCapability];
[_socket setEnableEncryption:enableEncryption];
[_socket connectToHost:[remoteHost address] onPort:[remoteHost port]];
[_socket setNoDelay:YES];
return self;
}
- (TPRemoteHost*)host
{
return _host;
}
- (id)delegate
{
return _delegate;
}
- (NSDictionary*)infoDict
{
return _infoDict;
}
- (SecIdentityRef)tcpSecureSocketCopyIdentity:(TPTCPSecureSocket*)tcpSocket
{
return [[TPConnectionsManager manager] tcpSecureSocketCopyIdentity:tcpSocket];
}
- (void)tcpSocketConnectionSucceeded:(TPTCPSocket*)tcpSocket
{
PRINT_ME;
_connection = [[TPNetworkConnection alloc] initWithSocket:tcpSocket];
[_connection setDelegate:self];
[_connection sendMessage:[TPConnectionsManager _identificationMessage]];
}
- (void)tcpSocketSecureConnectionSucceeded:(TPTCPSecureSocket*)tcpSocket
{
SecCertificateRef certRef = [tcpSocket copyPeerCertificate];
[_host setCertificate:certRef];
CFRelease(certRef);
[self tcpSocketConnectionSucceeded:tcpSocket];
}
- (void)tcpSocketConnectionFailed:(TPTCPSocket*)tcpSocket
{
PRINT_ME;
[[TPConnectionsManager manager] _socketConnectionFailed:self];
}
- (void)tcpSocketSecureConnectionFailed:(TPTCPSecureSocket*)tcpSocket
{
PRINT_ME;
[[TPConnectionsManager manager] _socketConnectionFailed:self];
}
- (void)connection:(TPNetworkConnection*)connection receivedMessage:(TPMessage*)message
{
PRINT_ME;
if([message msgType] == TPIdentificationMsgType) {
NSDictionary * infoDict = [message infoDict];
int protocolVersion = [infoDict[TPMsgProtocolVersionKey] intValue];
if(protocolVersion == PROTOCOL_VERSION) {
NSData * hostData = infoDict[TPMsgHostDataKey];
TPRemoteHost * remoteHost = [[TPHostsManager defaultManager] updatedHostFromData:hostData];
[connection setConnectedHost:remoteHost];
[[TPConnectionsManager manager] _socketConnection:self succeededWithNetworkConnection:connection];
}
else {
NSAlert * alert = [NSAlert alertWithMessageText:NSLocalizedString(@"Wrong protocol version", @"Invalid protocol error title") defaultButton:NSLocalizedString(@"OK", nil) alternateButton:nil otherButton:nil informativeTextWithFormat:NSLocalizedString(@"The Mac you tried to control is using teleport protocol v%d, but you're using v%d.", @"Invalid protocol error message"), protocolVersion, PROTOCOL_VERSION];
[(TPMainController*)[NSApp delegate] presentAlert:alert];
[[TPConnectionsManager manager] _socketConnectionFailed:self];
}
}
else {
NSLog(@"received invalid msg type: %ld (expected identification - %ld)", [message msgType], (long)TPIdentificationMsgType);
[[TPConnectionsManager manager] _socketConnectionFailed:self];
}
}
@end
@implementation TPConnectionsManager
+ (TPConnectionsManager*)manager
{
if(_connectionsManager == nil)
_connectionsManager = [[TPConnectionsManager alloc] init];
return _connectionsManager;
}
+ (TPMessage*)_identificationMessage
{
NSDictionary * infoDict = @{TPMsgProtocolVersionKey: @PROTOCOL_VERSION,
TPMsgHostDataKey: [[TPLocalHost localHost] hostData]};
return [TPMessage messageWithType:TPIdentificationMsgType andInfoDict:infoDict];
}
- (instancetype) init
{
self = [super init];
_connections = [[NSMutableSet alloc] init];
_pendingConnections = [[NSMutableDictionary alloc] init];
return self;
}
- (void)connectToHost:(TPRemoteHost*)host withDelegate:(id)delegate infoDict:(NSDictionary*)infoDict
{
PRINT_ME;
_TPSocketConnection * connection = _pendingConnections[[host identifier]];
if(connection == nil) {
connection = [[_TPSocketConnection alloc] initWithConnectionToHost:host delegate:delegate infoDict:infoDict];
_pendingConnections[[host identifier]] = connection;
}
}
- (BOOL)startListeningWithDelegate:(id)delegate onPort:(int*)port
{
if(_listenSocket != nil)
return YES;
_listenDelegate = delegate;
BOOL enableEncryption = [[TPLocalHost localHost] hasCapability:TPHostEncryptionCapability];
_listenSocket = [[TPTCPSecureSocket alloc] initWithDelegate:self];
[_listenSocket setEnableEncryption:enableEncryption];
return [_listenSocket listenOnPort:port tries:50];
}
- (void)stopListening
{
[_listenSocket close];
_listenSocket = nil;
}
#pragma mark -
#pragma mark Socket connection
- (void)_socketConnectionFailed:(_TPSocketConnection*)socketConnection
{
id delegate = [socketConnection delegate];
TPRemoteHost * host = [socketConnection host];
if(delegate && [delegate respondsToSelector:@selector(connectionToServerFailed:infoDict:)])
[delegate connectionToServerFailed:host infoDict:[socketConnection infoDict]];
[_pendingConnections removeObjectForKey:[host identifier]];
}
- (void)_socketConnection:(_TPSocketConnection*)socketConnection succeededWithNetworkConnection:(TPNetworkConnection*)networkConnection
{
id delegate = [socketConnection delegate];
TPRemoteHost * host = [socketConnection host];
if(delegate && [delegate respondsToSelector:@selector(connectionToServerSucceeded:infoDict:)])
[delegate connectionToServerSucceeded:networkConnection infoDict:[socketConnection infoDict]];
[_pendingConnections removeObjectForKey:[host identifier]];
}
#pragma mark -
#pragma mark Wake on LAN
- (BOOL)wakeUpHost:(TPRemoteHost*)host
{
if([host hasValidMACAddress]) {
DebugLog(@"trying to wake up host %@", host);
return [TPTCPSocket wakeUpHostWithMACAddress:[host MACAddress]];
}
else
return NO;
}
#pragma mark -
#pragma mark Listen socket delegate
- (void)tcpSocket:(TPTCPSocket*)listenSocket connectionAccepted:(TPTCPSocket*)childSocket
{
DebugLog(@"connection accepted from %@ on %@", listenSocket, childSocket);
[childSocket setNoDelay:YES];
TPNetworkConnection * connection = [[TPNetworkConnection alloc] initWithSocket:childSocket];
[connection setDelegate:self];
[connection sendMessage:[TPConnectionsManager _identificationMessage]];
[_connections addObject:connection];
}
- (BOOL)tcpSecureSocketShouldEnableEncryption:(TPTCPSecureSocket*)tcpSocket
{
NSString * remoteAddress = [tcpSocket remoteAddress];
TPRemoteHost * remoteHost = [[TPHostsManager defaultManager] hostWithAddress:remoteAddress];
if(remoteHost == nil) {
BOOL encryptionActive = [[TPPreferencesManager sharedPreferencesManager] boolForPref:ENABLED_ENCRYPTION];
NSLog(@"could not determine which host has IP %@, will%s use encryption as it is configured so locally", remoteAddress, encryptionActive ? "" : " NOT");
return encryptionActive; // encrypted by default, if encryption is enabled locally
}
else {
return [[TPLocalHost localHost] pairWithHost:remoteHost hasCapability:TPHostEncryptionCapability];
}
}
- (void)tcpSocket:(TPTCPSecureSocket*)listenSocket secureConnectionAccepted:(TPTCPSecureSocket*)childSocket
{
[self tcpSocket:listenSocket connectionAccepted:childSocket];
}
- (SecIdentityRef)tcpSecureSocketCopyIdentity:(TPTCPSecureSocket*)tcpSocket
{
SecIdentityRef identity = [[TPLocalHost localHost] identity];
if(identity == NULL) {
return NULL;
}
else {
return (SecIdentityRef)CFRetain(identity);
}
}
- (void)connection:(TPNetworkConnection*)connection receivedMessage:(TPMessage*)message
{
if([message msgType] == TPIdentificationMsgType) {
NSDictionary * infoDict = [message infoDict];
int protocolVersion = [infoDict[TPMsgProtocolVersionKey] intValue];
if(protocolVersion == PROTOCOL_VERSION) {
NSData * hostData = infoDict[TPMsgHostDataKey];
TPRemoteHost * remoteHost = [[TPHostsManager defaultManager] updatedHostFromData:hostData];
[connection setConnectedHost:remoteHost];
[[TPHostsManager defaultManager] addClientHost:remoteHost];
if(_listenDelegate && [_listenDelegate respondsToSelector:@selector(connectionFromClientAccepted:)])
[_listenDelegate connectionFromClientAccepted:connection];
}
else
NSLog(@"received message with invalid protocol (%d vs %d)", protocolVersion, PROTOCOL_VERSION);
}
else {
NSLog(@"received invalid msg type: %ld (excepted identification - %ld)", [message msgType], (long)TPIdentificationMsgType);
}
}
- (void)connectionDisconnected:(TPNetworkConnection *)connection
{
[_connections removeObject:connection];
}
@end