3
3
4
4
package com .microsoft .signalr ;
5
5
6
- import java .util .ArrayList ;
7
- import java .util .Collection ;
8
- import java .util .Date ;
9
- import java .util .HashMap ;
10
- import java .util .List ;
11
- import java .util .Map ;
12
- import java .util .Timer ;
13
- import java .util .TimerTask ;
6
+ import java .util .*;
14
7
import java .util .concurrent .*;
15
8
import java .util .concurrent .atomic .AtomicInteger ;
16
9
import java .util .concurrent .atomic .AtomicLong ;
@@ -46,7 +39,7 @@ public class HubConnection {
46
39
private Single <String > accessTokenProvider ;
47
40
private final Map <String , String > headers = new HashMap <>();
48
41
private ConnectionState connectionState = null ;
49
- private final HttpClient httpClient ;
42
+ private HttpClient httpClient ;
50
43
private String stopError ;
51
44
private Timer pingTimer = null ;
52
45
private final AtomicLong nextServerTimeout = new AtomicLong ();
@@ -56,6 +49,7 @@ public class HubConnection {
56
49
private long tickRate = 1000 ;
57
50
private CompletableSubject handshakeResponseSubject ;
58
51
private long handshakeResponseTimeout = 15 *1000 ;
52
+ private TransportEnum transportEnum = TransportEnum .ALL ;
59
53
private final Logger logger = LoggerFactory .getLogger (HubConnection .class );
60
54
61
55
/**
@@ -100,7 +94,7 @@ void setTickRate(long tickRateInMilliseconds) {
100
94
}
101
95
102
96
HubConnection (String url , Transport transport , boolean skipNegotiate , HttpClient httpClient ,
103
- Single <String > accessTokenProvider , long handshakeResponseTimeout , Map <String , String > headers ) {
97
+ Single <String > accessTokenProvider , long handshakeResponseTimeout , Map <String , String > headers , TransportEnum transportEnum ) {
104
98
if (url == null || url .isEmpty ()) {
105
99
throw new IllegalArgumentException ("A valid url is required." );
106
100
}
@@ -122,6 +116,8 @@ void setTickRate(long tickRateInMilliseconds) {
122
116
123
117
if (transport != null ) {
124
118
this .transport = transport ;
119
+ } else if (transportEnum != null ) {
120
+ this .transportEnum = transportEnum ;
125
121
}
126
122
127
123
if (handshakeResponseTimeout > 0 ) {
@@ -301,7 +297,13 @@ public Completable start() {
301
297
negotiate .flatMapCompletable (url -> {
302
298
logger .debug ("Starting HubConnection." );
303
299
if (transport == null ) {
304
- transport = new WebSocketTransport (headers , httpClient );
300
+ switch (transportEnum ) {
301
+ case LONG_POLLING :
302
+ transport = new LongPollingTransport (headers , httpClient , accessTokenProvider );
303
+ break ;
304
+ default :
305
+ transport = new WebSocketTransport (headers , httpClient );
306
+ }
305
307
}
306
308
307
309
transport .setOnReceive (this .callback );
@@ -311,37 +313,20 @@ public Completable start() {
311
313
String handshake = HandshakeProtocol .createHandshakeRequestMessage (
312
314
new HandshakeRequestMessage (protocol .getName (), protocol .getVersion ()));
313
315
316
+ connectionState = new ConnectionState (this );
317
+
314
318
return transport .send (handshake ).andThen (Completable .defer (() -> {
315
319
timeoutHandshakeResponse (handshakeResponseTimeout , TimeUnit .MILLISECONDS );
316
320
return handshakeResponseSubject .andThen (Completable .defer (() -> {
317
321
hubConnectionStateLock .lock ();
318
322
try {
319
- connectionState = new ConnectionState (this );
320
323
hubConnectionState = HubConnectionState .CONNECTED ;
321
324
logger .info ("HubConnection started." );
322
-
323
325
resetServerTimeout ();
324
- this .pingTimer = new Timer ();
325
- this .pingTimer .schedule (new TimerTask () {
326
- @ Override
327
- public void run () {
328
- try {
329
- if (System .currentTimeMillis () > nextServerTimeout .get ()) {
330
- stop ("Server timeout elapsed without receiving a message from the server." );
331
- return ;
332
- }
333
-
334
- if (System .currentTimeMillis () > nextPingActivation .get ()) {
335
- sendHubMessage (PingMessage .getInstance ());
336
- }
337
- } catch (Exception e ) {
338
- logger .warn ("Error sending ping: {}." , e .getMessage ());
339
- // The connection is probably in a bad or closed state now, cleanup the timer so
340
- // it stops triggering
341
- pingTimer .cancel ();
342
- }
343
- }
344
- }, new Date (0 ), tickRate );
326
+ //Don't send pings if we're using long polling.
327
+ if (transportEnum != TransportEnum .LONG_POLLING ) {
328
+ activatePingTimer ();
329
+ }
345
330
} finally {
346
331
hubConnectionStateLock .unlock ();
347
332
}
@@ -356,6 +341,30 @@ public void run() {
356
341
return start ;
357
342
}
358
343
344
+ private void activatePingTimer () {
345
+ this .pingTimer = new Timer ();
346
+ this .pingTimer .schedule (new TimerTask () {
347
+ @ Override
348
+ public void run () {
349
+ try {
350
+ if (System .currentTimeMillis () > nextServerTimeout .get ()) {
351
+ stop ("Server timeout elapsed without receiving a message from the server." );
352
+ return ;
353
+ }
354
+
355
+ if (System .currentTimeMillis () > nextPingActivation .get ()) {
356
+ sendHubMessage (PingMessage .getInstance ());
357
+ }
358
+ } catch (Exception e ) {
359
+ logger .warn ("Error sending ping: {}." , e .getMessage ());
360
+ // The connection is probably in a bad or closed state now, cleanup the timer so
361
+ // it stops triggering
362
+ pingTimer .cancel ();
363
+ }
364
+ }
365
+ }, new Date (0 ), tickRate );
366
+ }
367
+
359
368
private Single <String > startNegotiate (String url , int negotiateAttempts ) {
360
369
if (hubConnectionState != HubConnectionState .DISCONNECTED ) {
361
370
return Single .just (null );
@@ -367,7 +376,10 @@ private Single<String> startNegotiate(String url, int negotiateAttempts) {
367
376
}
368
377
369
378
if (response .getRedirectUrl () == null ) {
370
- if (!response .getAvailableTransports ().contains ("WebSockets" )) {
379
+ Set <String > transports = response .getAvailableTransports ();
380
+ if ((this .transportEnum == TransportEnum .ALL && !(transports .contains ("WebSockets" ) || transports .contains ("LongPolling" ))) ||
381
+ (this .transportEnum == TransportEnum .WEBSOCKETS && !transports .contains ("WebSockets" )) ||
382
+ (this .transportEnum == TransportEnum .LONG_POLLING && !transports .contains ("LongPolling" ))) {
371
383
throw new RuntimeException ("There were no compatible transports on the server." );
372
384
}
373
385
@@ -563,7 +575,7 @@ private void sendHubMessage(HubMessage message) {
563
575
} else {
564
576
logger .debug ("Sending {} message." , message .getMessageType ().name ());
565
577
}
566
- transport .send (serializedMessage );
578
+ transport .send (serializedMessage ). subscribeWith ( CompletableSubject . create ()) ;
567
579
568
580
resetKeepAlive ();
569
581
}
0 commit comments