|
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | 16 | package io.rsocket.transport.netty; |
17 | | - |
18 | 17 | import static io.netty.buffer.Unpooled.wrappedBuffer; |
19 | 18 | import static io.rsocket.frame.FrameHeaderFlyweight.FRAME_LENGTH_SIZE; |
20 | 19 |
|
|
27 | 26 | import org.reactivestreams.Publisher; |
28 | 27 | import reactor.core.publisher.Flux; |
29 | 28 | import reactor.core.publisher.Mono; |
| 29 | +import reactor.core.publisher.MonoProcessor; |
30 | 30 | import reactor.ipc.netty.NettyContext; |
31 | 31 | import reactor.ipc.netty.NettyInbound; |
32 | 32 | import reactor.ipc.netty.NettyOutbound; |
|
39 | 39 | * back on for frames received. |
40 | 40 | */ |
41 | 41 | public class WebsocketDuplexConnection implements DuplexConnection { |
42 | | - private final NettyInbound in; |
43 | | - private final NettyOutbound out; |
44 | | - private final NettyContext context; |
45 | | - |
46 | | - public WebsocketDuplexConnection(NettyInbound in, NettyOutbound out, NettyContext context) { |
47 | | - this.in = in; |
48 | | - this.out = out; |
49 | | - this.context = context; |
50 | | - } |
51 | | - |
52 | | - @Override |
53 | | - public Mono<Void> send(Publisher<Frame> frames) { |
54 | | - return Flux.from(frames).concatMap(this::sendOne).then(); |
55 | | - } |
56 | | - |
57 | | - @Override |
58 | | - public Mono<Void> sendOne(Frame frame) { |
59 | | - return out.sendObject(new BinaryWebSocketFrame(frame.content().skipBytes(FRAME_LENGTH_SIZE))) |
60 | | - .then(); |
61 | | - } |
62 | | - |
63 | | - @Override |
64 | | - public Flux<Frame> receive() { |
65 | | - return in.receive() |
66 | | - .map( |
67 | | - buf -> { |
68 | | - CompositeByteBuf composite = context.channel().alloc().compositeBuffer(); |
69 | | - ByteBuf length = wrappedBuffer(new byte[FRAME_LENGTH_SIZE]); |
70 | | - FrameHeaderFlyweight.encodeLength(length, 0, buf.readableBytes()); |
71 | | - composite.addComponents(true, length, buf.retain()); |
72 | | - return Frame.from(composite); |
73 | | - }); |
74 | | - } |
75 | | - |
76 | | - @Override |
77 | | - public Mono<Void> close() { |
78 | | - return Mono.fromRunnable( |
79 | | - () -> { |
80 | | - if (!context.isDisposed()) { |
81 | | - context.channel().close(); |
82 | | - } |
83 | | - }); |
84 | | - } |
85 | | - |
86 | | - @Override |
87 | | - public Mono<Void> onClose() { |
88 | | - return context.onClose(); |
89 | | - } |
90 | | - |
91 | | - @Override |
92 | | - public double availability() { |
93 | | - return context.isDisposed() ? 0.0 : 1.0; |
94 | | - } |
| 42 | + private final NettyInbound in; |
| 43 | + private final NettyOutbound out; |
| 44 | + private final NettyContext context; |
| 45 | + private final MonoProcessor<Void> onClose; |
| 46 | + |
| 47 | + public WebsocketDuplexConnection(NettyInbound in, NettyOutbound out, NettyContext context) { |
| 48 | + this.in = in; |
| 49 | + this.out = out; |
| 50 | + this.context = context; |
| 51 | + this.onClose = MonoProcessor.create(); |
| 52 | + |
| 53 | + context.onClose(onClose::onComplete); |
| 54 | + this.onClose |
| 55 | + .doFinally( |
| 56 | + s -> { |
| 57 | + this.context.dispose(); |
| 58 | + this.context.channel().close(); |
| 59 | + }) |
| 60 | + .subscribe(); |
| 61 | + } |
| 62 | + |
| 63 | + @Override |
| 64 | + public Mono<Void> send(Publisher<Frame> frames) { |
| 65 | + return Flux.from(frames).concatMap(this::sendOne).then(); |
| 66 | + } |
| 67 | + |
| 68 | + @Override |
| 69 | + public Mono<Void> sendOne(Frame frame) { |
| 70 | + return out.sendObject(new BinaryWebSocketFrame(frame.content().skipBytes(FRAME_LENGTH_SIZE))) |
| 71 | + .then(); |
| 72 | + } |
| 73 | + |
| 74 | + @Override |
| 75 | + public Flux<Frame> receive() { |
| 76 | + return in.receive() |
| 77 | + .map( |
| 78 | + buf -> { |
| 79 | + CompositeByteBuf composite = context.channel().alloc().compositeBuffer(); |
| 80 | + ByteBuf length = wrappedBuffer(new byte[FRAME_LENGTH_SIZE]); |
| 81 | + FrameHeaderFlyweight.encodeLength(length, 0, buf.readableBytes()); |
| 82 | + composite.addComponents(true, length, buf.retain()); |
| 83 | + return Frame.from(composite); |
| 84 | + }); |
| 85 | + } |
| 86 | + |
| 87 | + @Override |
| 88 | + public Mono<Void> close() { |
| 89 | + return Mono.fromRunnable(onClose::onComplete); |
| 90 | + } |
| 91 | + |
| 92 | + @Override |
| 93 | + public Mono<Void> onClose() { |
| 94 | + return onClose; |
| 95 | + } |
| 96 | + |
| 97 | + @Override |
| 98 | + public double availability() { |
| 99 | + return onClose.isTerminated() ? 0.0 : 1.0; |
| 100 | + } |
95 | 101 | } |
0 commit comments