-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathEXServer.m
More file actions
151 lines (142 loc) · 4.38 KB
/
EXServer.m
File metadata and controls
151 lines (142 loc) · 4.38 KB
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
//
// EXServer.m
// Entropy
// (C) 2007-2009 Codesign
// Licensed under LGPL (v3)
//
#import "EXServer.h"
#import "EXObjectProxy.h"
#import "LXSocket.h"
@implementation EXServer
+ (id)server {
return [[[self alloc] init] autorelease];
}
- (id)init {
if (self = [super init]) {
objects = [[NSMutableDictionary alloc] init];
expirationDates = [[NSMutableDictionary alloc] init];
leaseTimer = [NSTimer scheduledTimerWithTimeInterval: LEASETIME target: self selector: @selector(checkObjects) userInfo: nil repeats: YES];
}
return self;
}
- (void)runInThreadWithPort:(unsigned)port {
[NSThread detachNewThreadSelector: @selector(runWithPort:) toTarget: self withObject: [NSNumber numberWithUnsignedInt: port]];
}
- (void)checkObjects {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
@synchronized (objects) {
NSDate* now = [NSDate date];
for (id key in [expirationDates allKeys]) {
NSDate* expiration = [expirationDates objectForKey: key];
if ([expiration compare: now] == NSOrderedAscending) {
NSLog(@"Server - releasing outdated object");
[expirationDates removeObjectForKey: key];
[objects removeObjectForKey: key];
}
}
}
[pool release];
}
- (void)runWithPort:(NSNumber*)port {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
LXSocket* serverSocket = [[LXSocket alloc] init];
if ([serverSocket bindToPort: [port unsignedIntValue]]) {
if ([serverSocket listen: 10]) {
while (YES) {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
@try {
LXSocket* socket = [serverSocket accept];
//NSLog(@"EX server: new connection");
int action = [socket readInt];
id object;
NSValue* key;
switch (action) {
case 1:;
NSString* className = [socket readString];
//NSLog(@"EX server: 1 - %@", className);
object = [[NSClassFromString(className) alloc] init];
key = [NSNumber numberWithLongLong: (((long long) random()) << 32) | (long) object];
@synchronized (objects) {
[objects setObject: object forKey: key];
[expirationDates setObject: [[NSDate date] addTimeInterval: LEASETIME] forKey: key];
}
[object release];
[socket sendObject: key];
break;
case 4:; // renewing lease
key = [socket readObject];
@synchronized (objects) {
object = [objects objectForKey: key];
}
if (object != nil) {
[socket sendInt: 1];
@synchronized (objects) {
[expirationDates setObject: [[NSDate date] addTimeInterval: LEASETIME] forKey: key];
}
NSLog(@"Server - renewed");
} else {
[socket sendInt: 0];
NSLog(@"Server - object doesn't exist any more");
}
break;
case 2:;
key = [socket readObject];
@synchronized (objects) {
object = [objects objectForKey: key];
}
if (object != nil) {
[socket sendInt: 1];
SEL selector = NSSelectorFromString([socket readString]);
NSMethodSignature* signature = [object methodSignatureForSelector: selector];
NSInvocation* invocation = [NSInvocation invocationWithMethodSignature: signature];
[invocation setSelector: selector];
int numberOfArguments = [socket readInt];
for (int i = 2; i < numberOfArguments; i++) {
id argument = [socket readObject];
[invocation setArgument: &argument atIndex: i];
}
[invocation invokeWithTarget: object];
const char* returnType = [signature methodReturnType];
if (!strcmp(returnType, "v")) {
[socket sendInt: 0];
} else {
[socket sendInt: 1];
id result;
[invocation getReturnValue: &result];
[socket sendObject: result];
}
} else {
[socket sendInt: 0];
NSLog(@"Server - object doesn't exist any more");
}
break;
case 3:;
key = [socket readObject];
if (object != nil) {
[socket sendInt: 1];
@synchronized (objects) {
[objects removeObjectForKey: key];
}
} else {
[socket sendInt: 0];
NSLog(@"Server - object doesn't exist any more");
}
break;
}
[socket release];
} @finally {
[pool release];
}
}
}
}
[serverSocket release];
[pool release];
}
- (void)dealloc {
[leaseTimer invalidate];
[objects release];
[expirationDates release];
[super dealloc];
}
@end