@@ -28,59 +28,31 @@ of this software and associated documentation files (the "Software"), to deal
28
28
import bwapi .ClientData .Command ;
29
29
import bwapi .ClientData .GameData ;
30
30
import bwapi .ClientData .Shape ;
31
- import com .sun .jna .LastErrorException ;
32
- import com .sun .jna .Native ;
33
- import com .sun .jna .Pointer ;
34
- import com .sun .jna .platform .linux .Fcntl ;
35
- import com .sun .jna .platform .linux .LibC ;
36
- import com .sun .jna .platform .linux .LibRT ;
37
- import com .sun .jna .platform .win32 .Kernel32 ;
38
- import com .sun .jna .win32 .W32APIOptions ;
39
- import org .newsclub .net .unix .AFUNIXSocket ;
40
- import org .newsclub .net .unix .AFUNIXSocketAddress ;
41
-
42
- import java .io .File ;
43
- import java .io .RandomAccessFile ;
44
- import java .nio .ByteBuffer ;
45
- import java .nio .ByteOrder ;
46
31
47
- import static com . sun . jna . platform . linux . Mman .* ;
32
+ import java . nio . ByteBuffer ;
48
33
49
34
class Client {
50
- interface MappingKernel extends Kernel32 {
51
- MappingKernel INSTANCE = Native .load (MappingKernel .class , W32APIOptions .DEFAULT_OPTIONS );
52
-
53
- HANDLE OpenFileMapping (int desiredAccess , boolean inherit , String name );
54
- }
55
-
56
- interface LibCExt extends LibC {
57
- LibCExt INSTANCE = Native .load (LibCExt .class );
58
-
59
- Pointer mmap (Pointer addr , int length , int prot , int flags , int fd , int offset ) throws LastErrorException ;
60
- }
61
-
62
35
public interface EventHandler {
63
36
void operation (ClientData .Event event );
64
37
}
65
38
66
- private static final int READ_WRITE = 0x1 | 0x2 | 0x4 ;
67
-
68
39
private static final int SUPPORTED_BWAPI_VERSION = 10003 ;
69
40
static final int MAX_COUNT = 19999 ;
70
41
static final int MAX_STRING_SIZE = 1024 ;
71
42
72
43
private ClientData clientData ;
73
44
private ClientData .GameData gameData ;
74
45
private boolean connected = false ;
75
- private RandomAccessFile pipeObjectHandle = null ;
76
- private AFUNIXSocket syncSocket = null ;
77
- private ByteBuffer mapFileHandle = null ;
78
- private ByteBuffer gameTableFileHandle = null ;
46
+ private ByteBuffer mapShm = null ;
47
+ private ByteBuffer gameTableShm = null ;
48
+ private final ClientConnection clientConnector ;
79
49
80
50
private boolean debugConnection = false ;
81
51
82
52
Client (boolean debugConnection ) {
83
53
this .debugConnection = debugConnection ;
54
+ boolean windowsOs = System .getProperty ("os.name" ).toLowerCase ().contains ("win" );
55
+ clientConnector = windowsOs ? new ClientConnectionW32 () : new ClientConnectionPosix ();
84
56
}
85
57
86
58
/**
@@ -89,6 +61,7 @@ public interface EventHandler {
89
61
Client (ByteBuffer buffer ) {
90
62
clientData = new ClientData (buffer );
91
63
gameData = clientData .new GameData (0 );
64
+ clientConnector = null ;
92
65
}
93
66
94
67
ClientData clientData () {
@@ -117,27 +90,9 @@ void disconnect() {
117
90
if (!connected ) {
118
91
return ;
119
92
}
120
-
121
- if (pipeObjectHandle != null ) {
122
- try {
123
- pipeObjectHandle .close ();
124
- } catch (Exception e ) {
125
- e .printStackTrace ();
126
- }
127
- pipeObjectHandle = null ;
128
- }
129
-
130
- if (syncSocket != null ) {
131
- try {
132
- syncSocket .close ();
133
- } catch (Exception e ) {
134
- e .printStackTrace ();
135
- }
136
- syncSocket = null ;
137
- }
138
-
139
- mapFileHandle = null ;
140
- gameTableFileHandle = null ;
93
+ clientConnector .disconnect ();
94
+ mapShm = null ;
95
+ gameTableShm = null ;
141
96
gameData = null ;
142
97
connected = false ;
143
98
}
@@ -152,17 +107,7 @@ boolean connect() {
152
107
int gameTableIndex = -1 ;
153
108
154
109
try {
155
- try {
156
- gameTableFileHandle = Kernel32 .INSTANCE .MapViewOfFile (
157
- MappingKernel .INSTANCE .OpenFileMapping (READ_WRITE , false , "Local\\ bwapi_shared_memory_game_list" ), READ_WRITE , 0 , 0 , GameTable .SIZE )
158
- .getByteBuffer (0 , GameTable .SIZE );
159
- } catch (UnsatisfiedLinkError | NoClassDefFoundError e ) {
160
- int fd = LibRT .INSTANCE .shm_open ("/bwapi_shared_memory_game_list" , Fcntl .O_RDWR , 0 );
161
- if (fd < 0 ) throw new IllegalStateException ("SHM not found" );
162
- gameTableFileHandle = LibCExt .INSTANCE .mmap (Pointer .NULL , GameTable .SIZE , PROT_READ | PROT_WRITE , MAP_SHARED , fd , 0 )
163
- .getByteBuffer (0 , GameTable .SIZE );
164
- gameTableFileHandle .order (ByteOrder .LITTLE_ENDIAN );
165
- }
110
+ gameTableShm = clientConnector .getGameTable ();
166
111
}
167
112
catch (Exception e ) {
168
113
System .err .println ("Game table mapping not found." );
@@ -171,7 +116,7 @@ boolean connect() {
171
116
172
117
GameTable gameTable ;
173
118
try {
174
- gameTable = new GameTable (gameTableFileHandle );
119
+ gameTable = new GameTable (this . gameTableShm );
175
120
}
176
121
catch (Exception e ) {
177
122
System .err .println ("Unable to map Game table." );
@@ -202,28 +147,19 @@ boolean connect() {
202
147
return false ;
203
148
}
204
149
205
- String sharedMemoryName = "Local\\ bwapi_shared_memory_" + serverProcID ;
206
150
try {
207
- try {
208
- mapFileHandle = Kernel32 .INSTANCE .MapViewOfFile (MappingKernel .INSTANCE
209
- .OpenFileMapping (READ_WRITE , false , sharedMemoryName ), READ_WRITE ,
210
- 0 , 0 , GameData .SIZE ).getByteBuffer (0 , GameData .SIZE );
211
- } catch (NoClassDefFoundError e ) {
212
- sharedMemoryName = "/bwapi_shared_memory_" + serverProcID ;
213
- mapFileHandle = LibCExt .INSTANCE .mmap (Pointer .NULL , GameData .SIZE , PROT_READ | PROT_WRITE , MAP_SHARED , LibRT .INSTANCE .shm_open (sharedMemoryName , Fcntl .O_RDWR , 0 ),
214
- 0 ).getByteBuffer (0 , GameData .SIZE );
215
- }
151
+ mapShm = clientConnector .getSharedMemory (serverProcID );
216
152
}
217
153
catch (Exception e ) {
218
- System .err .println ("Unable to open shared memory mapping: " + sharedMemoryName );
154
+ System .err .println ("Unable to open shared memory mapping: " + e . getMessage () );
219
155
if (debugConnection ) {
220
156
e .printStackTrace ();
221
157
}
222
- gameTableFileHandle = null ;
158
+ this . gameTableShm = null ;
223
159
return false ;
224
160
}
225
161
try {
226
- clientData = new ClientData (mapFileHandle );
162
+ clientData = new ClientData (mapShm );
227
163
gameData = clientData .new GameData (0 );
228
164
} catch (Exception e ) {
229
165
System .err .println ("Unable to map game data." );
@@ -233,23 +169,15 @@ boolean connect() {
233
169
return false ;
234
170
}
235
171
236
- final String communicationPipe = "\\ \\ .\\ pipe\\ bwapi_pipe_" + serverProcID ;
237
- final String communicationSocket = "/tmp/bwapi_socket_" + serverProcID ;
172
+
238
173
try {
239
- if (new File (communicationPipe ).exists ()) {
240
- pipeObjectHandle = new RandomAccessFile (communicationPipe , "rw" );
241
- } else {
242
- syncSocket = AFUNIXSocket .newInstance ();
243
- syncSocket .connect (new AFUNIXSocketAddress (new File (communicationSocket )));
244
- }
174
+ clientConnector .connectSharedLock (serverProcID );
245
175
} catch (Exception e ) {
246
- System .err .println ("Unable to open communications pipe or socket: " + communicationPipe + " resp. " + communicationSocket );
176
+ System .err .println (e . getMessage () );
247
177
if (debugConnection ) {
248
178
e .printStackTrace ();
249
179
}
250
- gameTableFileHandle = null ;
251
- pipeObjectHandle = null ;
252
- syncSocket = null ;
180
+ this .gameTableShm = null ;
253
181
return false ;
254
182
}
255
183
System .out .println ("Connected" );
@@ -263,20 +191,14 @@ boolean connect() {
263
191
return false ;
264
192
}
265
193
266
- if (pipeObjectHandle != null ) {
267
- byte code = 1 ;
268
- while (code != 2 ) {
269
- try {
270
- code = pipeObjectHandle .readByte ();
271
- } catch (Exception e ) {
272
- System .err .println ("Unable to read pipe object." );
273
- if (debugConnection ) {
274
- e .printStackTrace ();
275
- }
276
- disconnect ();
277
- return false ;
278
- }
194
+ try {
195
+ clientConnector .waitForServerReady ();
196
+ } catch (Exception e ) {
197
+ if (debugConnection ) {
198
+ e .printStackTrace ();
279
199
}
200
+ disconnect ();
201
+ return false ;
280
202
}
281
203
282
204
System .out .println ("Connection successful" );
@@ -285,58 +207,27 @@ boolean connect() {
285
207
}
286
208
287
209
void update (final EventHandler handler ) {
288
- if (pipeObjectHandle != null ) {
289
- byte code = 1 ;
290
- try {
291
- pipeObjectHandle .writeByte (code );
292
- } catch (Exception e ) {
293
- System .err .println ("failed, disconnecting" );
294
- if (debugConnection ) {
295
- e .printStackTrace ();
296
- }
297
- disconnect ();
298
- return ;
299
- }
300
- while (code != 2 ) {
301
- try {
302
- code = pipeObjectHandle .readByte ();
303
- } catch (Exception e ) {
304
- System .err .println ("failed, disconnecting" );
305
- if (debugConnection ) {
306
- e .printStackTrace ();
307
- }
308
- disconnect ();
309
- return ;
310
- }
311
- }
312
- }
313
- if (syncSocket != null ) {
314
- int code = 1 ;
315
- while (code != 2 ) {
316
- try {
317
- code = syncSocket .getInputStream ().read ();
318
- } catch (Exception e ) {
319
- System .err .println ("failed, disconnecting" );
320
- if (debugConnection ) {
321
- e .printStackTrace ();
322
- }
323
- disconnect ();
324
- return ;
325
- }
210
+ try {
211
+ clientConnector .waitForServerData ();
212
+ } catch (Exception e ) {
213
+ System .err .println ("failed, disconnecting" );
214
+ if (debugConnection ) {
215
+ e .printStackTrace ();
326
216
}
217
+ disconnect ();
218
+ return ;
327
219
}
328
220
for (int i = 0 ; i < gameData .getEventCount (); i ++) {
329
221
handler .operation (gameData .getEvents (i ));
330
222
}
331
223
try {
332
- syncSocket . getOutputStream (). write ( 1 );
224
+ clientConnector . submitClientData ( );
333
225
} catch (Exception e ) {
334
226
System .err .println ("failed, disconnecting" );
335
227
if (debugConnection ) {
336
228
e .printStackTrace ();
337
229
}
338
230
disconnect ();
339
- return ;
340
231
}
341
232
}
342
233
@@ -392,6 +283,7 @@ private void sleep(final int millis) {
392
283
Thread .sleep (millis );
393
284
}
394
285
catch (Exception ignored ) {
286
+ // Not relevant
395
287
}
396
288
}
397
289
}
0 commit comments