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
|
// serverbrowser.cpp: eihrul's concurrent resolver, and server browser window
// management
#include "SDL_thread.h"
#include "cube.h"
#import "ServerInfo.h"
@interface ResolverThread: OFThread
{
volatile bool _stop;
}
@property (copy, nonatomic) OFString *query;
@property (nonatomic) int starttime;
@end
@interface ResolverResult: OFObject
@property (readonly, nonatomic) OFString *query;
@property (readonly, nonatomic) ENetAddress address;
- (instancetype)init OF_UNAVAILABLE;
- (instancetype)initWithQuery:(OFString *)query address:(ENetAddress)address;
@end
static OFMutableArray<ResolverThread *> *resolverthreads;
static OFMutableArray<OFString *> *resolverqueries;
static OFMutableArray<ResolverResult *> *resolverresults;
static SDL_sem *resolversem;
static int resolverlimit = 1000;
@implementation ResolverThread
- (id)main
{
while (!_stop) {
SDL_SemWait(resolversem);
@synchronized(ResolverThread.class) {
if (resolverqueries.count == 0)
continue;
_query = resolverqueries.lastObject;
[resolverqueries removeLastObject];
_starttime = lastmillis;
}
ENetAddress address = { ENET_HOST_ANY, CUBE_SERVINFO_PORT };
enet_address_set_host(&address, _query.UTF8String);
@synchronized(ResolverThread.class) {
[resolverresults addObject:[[ResolverResult alloc]
initWithQuery:_query
address:address]];
_query = NULL;
_starttime = 0;
}
}
return nil;
}
- (void)stop
{
_stop = true;
}
@end
@implementation ResolverResult
- (instancetype)initWithQuery:(OFString *)query address:(ENetAddress)address
{
self = [super init];
_query = query;
_address = address;
return self;
}
@end
void
resolverinit(int threads, int limit)
{
resolverthreads = [[OFMutableArray alloc] init];
resolverqueries = [[OFMutableArray alloc] init];
resolverresults = [[OFMutableArray alloc] init];
resolverlimit = limit;
resolversem = SDL_CreateSemaphore(0);
while (threads > 0) {
ResolverThread *rt = [[ResolverThread alloc] init];
rt.name = @"resolverthread";
[resolverthreads addObject:rt];
[rt start];
--threads;
}
}
void
resolverstop(size_t i, bool restart)
{
@synchronized(ResolverThread.class) {
ResolverThread *rt = resolverthreads[i];
[rt stop];
if (restart) {
rt = [[ResolverThread alloc] init];
rt.name = @"resolverthread";
resolverthreads[i] = rt;
[rt start];
} else
[resolverthreads removeObjectAtIndex:i];
|
|
<
|
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
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
|
// serverbrowser.cpp: eihrul's concurrent resolver, and server browser window
// management
#include "SDL_thread.h"
#include "cube.h"
#import "ResolverResult.h"
#import "ResolverThread.h"
#import "ServerInfo.h"
static OFMutableArray<ResolverThread *> *resolverthreads;
OFMutableArray<OFString *> *resolverqueries;
OFMutableArray<ResolverResult *> *resolverresults;
SDL_sem *resolversem;
static int resolverlimit = 1000;
void
resolverinit(int threads, int limit)
{
resolverthreads = [[OFMutableArray alloc] init];
resolverqueries = [[OFMutableArray alloc] init];
resolverresults = [[OFMutableArray alloc] init];
resolverlimit = limit;
resolversem = SDL_CreateSemaphore(0);
while (threads > 0) {
ResolverThread *rt = [ResolverThread thread];
rt.name = @"resolverthread";
[resolverthreads addObject:rt];
[rt start];
--threads;
}
}
void
resolverstop(size_t i, bool restart)
{
@synchronized(ResolverThread.class) {
ResolverThread *rt = resolverthreads[i];
[rt stop];
if (restart) {
rt = [ResolverThread thread];
rt.name = @"resolverthread";
resolverthreads[i] = rt;
[rt start];
} else
[resolverthreads removeObjectAtIndex:i];
|
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
|
for (ServerInfo *si in servers)
if ([si.name isEqual:servername])
return;
if (servers == nil)
servers = [[OFMutableArray alloc] init];
[servers addObject:[[ServerInfo alloc] initWithName:servername]];
}
void
pingservers()
{
ENetBuffer buf;
uchar ping[MAXTRANS];
|
|
|
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
for (ServerInfo *si in servers)
if ([si.name isEqual:servername])
return;
if (servers == nil)
servers = [[OFMutableArray alloc] init];
[servers addObject:[ServerInfo infoWithName:servername]];
}
void
pingservers()
{
ENetBuffer buf;
uchar ping[MAXTRANS];
|
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
|
[servers sort];
__block int maxmenu = 16;
[servers enumerateObjectsUsingBlock:^(
ServerInfo *si, size_t i, bool *stop) {
if (si.address.host != ENET_HOST_ANY && si.ping != 9999) {
if (si.protocol != PROTOCOL_VERSION)
si.full = [[OFString alloc]
initWithFormat:
@"%@ [different cube protocol]",
si.name];
else
si.full = [[OFString alloc]
initWithFormat:@"%d\t%d\t%@, %@: %@ %@",
si.ping, si.numplayers,
si.map.length > 0 ? si.map : @"[unknown]",
modestr(si.mode), si.name, si.sdesc];
} else
si.full = [[OFString alloc]
initWithFormat:
(si.address.host != ENET_HOST_ANY
? @"%@ [waiting for server response]"
: @"%@ [unknown host]\t"),
si.name];
// cut off too long server descriptions
if (si.full.length > 50)
|
|
|
|
|
|
|
|
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
|
[servers sort];
__block int maxmenu = 16;
[servers enumerateObjectsUsingBlock:^(
ServerInfo *si, size_t i, bool *stop) {
if (si.address.host != ENET_HOST_ANY && si.ping != 9999) {
if (si.protocol != PROTOCOL_VERSION)
si.full = [OFString
stringWithFormat:
@"%@ [different cube protocol]",
si.name];
else
si.full = [OFString
stringWithFormat:@"%d\t%d\t%@, %@: %@ %@",
si.ping, si.numplayers,
si.map.length > 0 ? si.map : @"[unknown]",
modestr(si.mode), si.name, si.sdesc];
} else
si.full = [OFString
stringWithFormat:
(si.address.host != ENET_HOST_ANY
? @"%@ [waiting for server response]"
: @"%@ [unknown host]\t"),
si.name];
// cut off too long server descriptions
if (si.full.length > 50)
|