16
16
17
17
package io .rsocket ;
18
18
19
+ import static io .rsocket .keepalive .KeepAliveSupport .ClientKeepAliveSupport ;
20
+ import static io .rsocket .keepalive .KeepAliveSupport .KeepAlive ;
21
+
19
22
import io .netty .buffer .ByteBuf ;
20
23
import io .netty .buffer .ByteBufAllocator ;
21
24
import io .netty .util .ReferenceCountUtil ;
22
25
import io .netty .util .collection .IntObjectHashMap ;
26
+ import io .rsocket .exceptions .ConnectionErrorException ;
23
27
import io .rsocket .exceptions .Exceptions ;
24
28
import io .rsocket .frame .*;
25
29
import io .rsocket .frame .decoder .PayloadDecoder ;
26
30
import io .rsocket .internal .LimitableRequestPublisher ;
27
31
import io .rsocket .internal .UnboundedProcessor ;
28
32
import io .rsocket .internal .UnicastMonoProcessor ;
33
+ import io .rsocket .keepalive .KeepAliveFramesAcceptor ;
34
+ import io .rsocket .keepalive .KeepAliveHandler ;
35
+ import io .rsocket .keepalive .KeepAliveSupport ;
29
36
import java .nio .channels .ClosedChannelException ;
30
37
import java .util .Collections ;
31
38
import java .util .Map ;
36
43
import org .reactivestreams .Processor ;
37
44
import org .reactivestreams .Publisher ;
38
45
import org .reactivestreams .Subscriber ;
39
- import reactor .core .publisher .BaseSubscriber ;
40
- import reactor .core .publisher .Flux ;
41
- import reactor .core .publisher .Mono ;
42
- import reactor .core .publisher .SignalType ;
43
- import reactor .core .publisher .UnicastProcessor ;
46
+ import reactor .core .publisher .*;
44
47
45
48
/** Client Side of a RSocket socket. Sends {@link ByteBuf}s to a {@link RSocketServer} */
46
49
class RSocketClient implements RSocket {
@@ -54,14 +57,18 @@ class RSocketClient implements RSocket {
54
57
private final UnboundedProcessor <ByteBuf > sendProcessor ;
55
58
private final Lifecycle lifecycle = new Lifecycle ();
56
59
private final ByteBufAllocator allocator ;
60
+ private final KeepAliveFramesAcceptor keepAliveFramesAcceptor ;
57
61
58
62
/*client requester*/
59
63
RSocketClient (
60
64
ByteBufAllocator allocator ,
61
65
DuplexConnection connection ,
62
66
PayloadDecoder payloadDecoder ,
63
67
Consumer <Throwable > errorConsumer ,
64
- StreamIdSupplier streamIdSupplier ) {
68
+ StreamIdSupplier streamIdSupplier ,
69
+ int keepAliveTickPeriod ,
70
+ int keepAliveAckTimeout ,
71
+ KeepAliveHandler keepAliveHandler ) {
65
72
this .allocator = allocator ;
66
73
this .connection = connection ;
67
74
this .payloadDecoder = payloadDecoder ;
@@ -74,19 +81,40 @@ class RSocketClient implements RSocket {
74
81
this .sendProcessor = new UnboundedProcessor <>();
75
82
76
83
connection .onClose ().doFinally (signalType -> terminate ()).subscribe (null , errorConsumer );
77
-
78
- sendProcessor
79
- .doOnRequest (
80
- r -> {
81
- for (LimitableRequestPublisher lrp : senders .values ()) {
82
- lrp .increaseInternalLimit (r );
83
- }
84
- })
85
- .transform (connection ::send )
84
+ connection
85
+ .send (sendProcessor )
86
86
.doFinally (this ::handleSendProcessorCancel )
87
87
.subscribe (null , this ::handleSendProcessorError );
88
88
89
89
connection .receive ().subscribe (this ::handleIncomingFrames , errorConsumer );
90
+
91
+ if (keepAliveTickPeriod != 0 && keepAliveHandler != null ) {
92
+ KeepAliveSupport keepAliveSupport =
93
+ new ClientKeepAliveSupport (allocator , keepAliveTickPeriod , keepAliveAckTimeout );
94
+ this .keepAliveFramesAcceptor =
95
+ keepAliveHandler .start (keepAliveSupport , sendProcessor ::onNext , this ::terminate );
96
+ } else {
97
+ keepAliveFramesAcceptor = null ;
98
+ }
99
+ }
100
+
101
+ /*server requester*/
102
+ RSocketClient (
103
+ ByteBufAllocator allocator ,
104
+ DuplexConnection connection ,
105
+ PayloadDecoder payloadDecoder ,
106
+ Consumer <Throwable > errorConsumer ,
107
+ StreamIdSupplier streamIdSupplier ) {
108
+ this (allocator , connection , payloadDecoder , errorConsumer , streamIdSupplier , 0 , 0 , null );
109
+ }
110
+
111
+ private void terminate (KeepAlive keepAlive ) {
112
+ String message =
113
+ String .format ("No keep-alive acks for %d ms" , keepAlive .getTimeout ().toMillis ());
114
+ ConnectionErrorException err = new ConnectionErrorException (message );
115
+ lifecycle .setTerminationError (err );
116
+ errorConsumer .accept (err );
117
+ connection .dispose ();
90
118
}
91
119
92
120
private void handleSendProcessorError (Throwable t ) {
@@ -294,7 +322,7 @@ public void accept(long n) {
294
322
.transform (
295
323
f -> {
296
324
LimitableRequestPublisher <Payload > wrapped =
297
- LimitableRequestPublisher .wrap (f , sendProcessor . available () );
325
+ LimitableRequestPublisher .wrap (f );
298
326
// Need to set this to one for first the frame
299
327
wrapped .request (1 );
300
328
senders .put (streamId , wrapped );
@@ -452,8 +480,9 @@ private void handleStreamZero(FrameType type, ByteBuf frame) {
452
480
case LEASE :
453
481
break ;
454
482
case KEEPALIVE :
455
- // KeepAlive is handled by corresponding connection interceptor,
456
- // just release its frame here
483
+ if (keepAliveFramesAcceptor != null ) {
484
+ keepAliveFramesAcceptor .receive (frame );
485
+ }
457
486
break ;
458
487
default :
459
488
// Ignore unknown frames. Throwing an error will close the socket.
0 commit comments