21
21
import java .net .InetSocketAddress ;
22
22
import java .nio .ByteBuffer ;
23
23
import java .security .KeyStore ;
24
+ import java .util .HashMap ;
24
25
import java .util .List ;
26
+ import java .util .Map ;
27
+ import java .util .Timer ;
28
+ import java .util .TimerTask ;
25
29
26
30
import javax .net .ssl .KeyManagerFactory ;
27
31
import javax .net .ssl .SSLContext ;
28
32
import javax .net .ssl .SSLParameters ;
29
33
import javax .net .ssl .TrustManagerFactory ;
30
34
31
35
import org .java_websocket .WebSocket ;
36
+ import org .java_websocket .framing .Framedata ;
32
37
import org .java_websocket .handshake .ClientHandshake ;
33
38
import org .java_websocket .server .SSLParametersWebSocketServerFactory ;
34
39
import org .java_websocket .server .WebSocketServer ;
44
49
import msi .gama .headless .runtime .Application ;
45
50
import msi .gama .headless .script .ExperimentationPlanFactory ;
46
51
import msi .gama .util .GamaMapFactory ;
47
- import msi .gama .util .IList ;
48
52
import msi .gama .util .IMap ;
49
53
import msi .gama .util .file .json .Jsoner ;
50
54
import ummisco .gama .dev .utils .DEBUG ;
@@ -82,6 +86,11 @@ public void set_listener(final GamaListener _listener) {
82
86
/** The cmd helper. */
83
87
CommandExecutor cmdHelper ;
84
88
89
+ // variables for the keepalive pings
90
+ public final boolean canPing ; // false if pingInterval is negative
91
+ public final int pingInterval ; // the time interval between two ping requests in ms
92
+ protected Map <WebSocket , Timer > pingTimers ; // map of all connected clients and their associated timers running ping requests
93
+
85
94
/**
86
95
* Instantiates a new gama web socket server.
87
96
*
@@ -94,8 +103,14 @@ public void set_listener(final GamaListener _listener) {
94
103
* @param ssl
95
104
* the ssl
96
105
*/
97
- public GamaWebSocketServer (final int port , final Application a , final GamaListener l , final boolean ssl , final String jksPath , final String spwd , final String kpwd ) {
106
+ public GamaWebSocketServer (final int port , final Application a , final GamaListener l , final boolean ssl , final String jksPath , final String spwd , final String kpwd , final int ping_interval ) {
98
107
super (new InetSocketAddress (port ));
108
+
109
+ canPing = ping_interval >= 0 ;
110
+ pingInterval = ping_interval ;
111
+ pingTimers = new HashMap <WebSocket , Timer >();
112
+
113
+
99
114
if (a .verbose ) { DEBUG .ON (); }
100
115
cmdHelper = new CommandExecutor ();
101
116
if (ssl ) {
@@ -148,7 +163,17 @@ public void onOpen(final WebSocket conn, final ClientHandshake handshake) {
148
163
DEBUG .OUT (conn .getRemoteSocketAddress ().getAddress ().getHostAddress () + " entered the room!" );
149
164
conn .send (Jsoner
150
165
.serialize (new GamaServerMessage (GamaServerMessageType .ConnectionSuccessful , "" + conn .hashCode ())));
151
-
166
+
167
+ if (canPing ) {
168
+ var timer = new Timer ();
169
+ timer .scheduleAtFixedRate (new TimerTask () {
170
+ @ Override
171
+ public void run () {
172
+ conn .sendPing ();
173
+ }
174
+ }, 0 , pingInterval );
175
+ pingTimers .put (conn , timer );
176
+ }
152
177
// String path = URI.create(handshake.getResourceDescriptor()).getPath();
153
178
}
154
179
@@ -159,8 +184,26 @@ public void onOpen(final WebSocket conn, final ClientHandshake handshake) {
159
184
*/
160
185
public Application getDefaultApp () { return app ; }
161
186
187
+ @ Override
188
+ public void onWebsocketPing (WebSocket conn , Framedata f ) {
189
+ // TODO Auto-generated method stub
190
+ super .onWebsocketPing (conn , f );
191
+ }
192
+
193
+ @ Override
194
+ public void onWebsocketPong (WebSocket conn , Framedata f ) {
195
+ // TODO Auto-generated method stub
196
+ super .onWebsocketPong (conn , f );
197
+ }
198
+
162
199
@ Override
163
200
public void onClose (final WebSocket conn , final int code , final String reason , final boolean remote ) {
201
+
202
+ var timer = pingTimers .remove (conn );
203
+ if (timer != null ) {
204
+ timer .cancel ();
205
+ }
206
+
164
207
if (_listener .getLaunched_experiments ().get ("" + conn .hashCode ()) != null ) {
165
208
for (ManualExperimentJob e : _listener .getLaunched_experiments ().get ("" + conn .hashCode ()).values ()) {
166
209
e .controller .directPause ();
@@ -217,13 +260,13 @@ public void onMessage(final WebSocket socket, final String message) {
217
260
final String socket_id = map .get ("socket_id" ) != null ? map .get ("socket_id" ).toString () : ("" + socket .hashCode ());
218
261
if (get_listener ().getExperiment (socket_id , exp_id )!=null && !get_listener ().getExperiment (socket_id , exp_id ).controller .isPaused () ) {
219
262
get_listener ().getExperiment (socket_id , exp_id ).controller .getScope ().getSimulation ().postOneShotAction (scope1 -> {
220
- cmdHelper .process (socket , map );
263
+ cmdHelper .pushCommand (socket , map );
221
264
// System.out.println(map.get("type"));
222
265
return null ;
223
266
});
224
267
}else {
225
268
226
- cmdHelper .process (socket , map );
269
+ cmdHelper .pushCommand (socket , map );
227
270
}
228
271
229
272
} catch (Exception e1 ) {
0 commit comments