1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.channel.local;
17
18 import io.netty.channel.AbstractServerChannel;
19 import io.netty.channel.ChannelConfig;
20 import io.netty.channel.ChannelPipeline;
21 import io.netty.channel.ChannelPromise;
22 import io.netty.channel.DefaultChannelConfig;
23 import io.netty.channel.EventLoop;
24 import io.netty.channel.IoEvent;
25 import io.netty.channel.IoEventLoop;
26 import io.netty.channel.IoEventLoopGroup;
27 import io.netty.channel.IoRegistration;
28 import io.netty.channel.PreferHeapByteBufAllocator;
29 import io.netty.channel.RecvByteBufAllocator;
30 import io.netty.channel.ServerChannel;
31 import io.netty.channel.ServerChannelRecvByteBufAllocator;
32 import io.netty.channel.SingleThreadEventLoop;
33 import io.netty.util.concurrent.SingleThreadEventExecutor;
34
35 import java.net.SocketAddress;
36 import java.util.ArrayDeque;
37 import java.util.Queue;
38
39
40
41
42 public class LocalServerChannel extends AbstractServerChannel {
43
44 private final ChannelConfig config =
45 new DefaultChannelConfig(this, new ServerChannelRecvByteBufAllocator()) { };
46 private final Queue<Object> inboundBuffer = new ArrayDeque<Object>();
47
48 private IoRegistration registration;
49
50 private volatile int state;
51 private volatile LocalAddress localAddress;
52 private volatile boolean acceptInProgress;
53
54 public LocalServerChannel() {
55 config().setAllocator(new PreferHeapByteBufAllocator(config.getAllocator()));
56 }
57
58 @Override
59 public ChannelConfig config() {
60 return config;
61 }
62
63 @Override
64 public LocalAddress localAddress() {
65 return (LocalAddress) super.localAddress();
66 }
67
68 @Override
69 public LocalAddress remoteAddress() {
70 return (LocalAddress) super.remoteAddress();
71 }
72
73 @Override
74 public boolean isOpen() {
75 return state < 2;
76 }
77
78 @Override
79 public boolean isActive() {
80 return state == 1;
81 }
82
83 @Override
84 protected boolean isCompatible(EventLoop loop) {
85 return loop instanceof SingleThreadEventLoop ||
86 (loop instanceof IoEventLoop && ((IoEventLoop) loop).isCompatible(LocalServerUnsafe.class));
87 }
88
89 @Override
90 protected SocketAddress localAddress0() {
91 return localAddress;
92 }
93
94 @Override
95 protected void doRegister(ChannelPromise promise) {
96 EventLoop loop = eventLoop();
97 if (loop instanceof IoEventLoop) {
98 assert registration == null;
99 ((IoEventLoop) loop).register((LocalServerUnsafe) unsafe()).addListener(f -> {
100 if (f.isSuccess()) {
101 registration = (IoRegistration) f.getNow();
102 promise.setSuccess();
103 } else {
104 promise.setFailure(f.cause());
105 }
106 });
107 } else {
108 try {
109 ((LocalServerUnsafe) unsafe()).registered();
110 } catch (Throwable cause) {
111 promise.setFailure(cause);
112 return;
113 }
114 promise.setSuccess();
115 }
116 }
117
118 @Override
119 protected void doBind(SocketAddress localAddress) throws Exception {
120 this.localAddress = LocalChannelRegistry.register(this, this.localAddress, localAddress);
121 state = 1;
122 }
123
124 @Override
125 protected void doClose() throws Exception {
126 if (state <= 1) {
127
128 if (localAddress != null) {
129 LocalChannelRegistry.unregister(localAddress);
130 localAddress = null;
131 }
132 state = 2;
133 }
134
135
136
137 Object m;
138 while ((m = inboundBuffer.poll()) != null) {
139 ((LocalChannel) m).unsafe().closeForcibly();
140 }
141 }
142
143 @Override
144 protected void doDeregister() throws Exception {
145 EventLoop loop = eventLoop();
146 if (loop instanceof IoEventLoop) {
147 IoRegistration registration = this.registration;
148 if (registration != null) {
149 this.registration = null;
150 registration.cancel();
151 }
152 } else {
153 ((LocalServerUnsafe) unsafe()).unregistered();
154 }
155 }
156
157 @Override
158 protected void doBeginRead() throws Exception {
159 if (acceptInProgress) {
160 return;
161 }
162
163 Queue<Object> inboundBuffer = this.inboundBuffer;
164 if (inboundBuffer.isEmpty()) {
165 acceptInProgress = true;
166 return;
167 }
168
169 readInbound();
170 }
171
172 LocalChannel serve(final LocalChannel peer) {
173 final LocalChannel child = newLocalChannel(peer);
174 if (eventLoop().inEventLoop()) {
175 serve0(child);
176 } else {
177 eventLoop().execute(new Runnable() {
178 @Override
179 public void run() {
180 serve0(child);
181 }
182 });
183 }
184 return child;
185 }
186
187 private void readInbound() {
188 RecvByteBufAllocator.Handle handle = unsafe().recvBufAllocHandle();
189 handle.reset(config());
190 ChannelPipeline pipeline = pipeline();
191 do {
192 Object m = inboundBuffer.poll();
193 if (m == null) {
194 break;
195 }
196 handle.incMessagesRead(1);
197 pipeline.fireChannelRead(m);
198 } while (handle.continueReading());
199 handle.readComplete();
200 pipeline.fireChannelReadComplete();
201 }
202
203
204
205
206
207 protected LocalChannel newLocalChannel(LocalChannel peer) {
208 return new LocalChannel(this, peer);
209 }
210
211 private void serve0(final LocalChannel child) {
212 if (!isOpen()) {
213 child.unsafe().closeForcibly();
214 return;
215 }
216 inboundBuffer.add(child);
217 if (acceptInProgress) {
218 acceptInProgress = false;
219
220 readInbound();
221 }
222 }
223
224 @Override
225 protected AbstractUnsafe newUnsafe() {
226 return new LocalServerUnsafe();
227 }
228
229 private class LocalServerUnsafe extends AbstractUnsafe implements LocalIoHandle {
230 private final Runnable shutdownHook = this::closeNow;
231
232 @Override
233 public void close() {
234 close(voidPromise());
235 }
236
237 @Override
238 public void handle(IoRegistration registration, IoEvent event) {
239
240 }
241
242 @Override
243 public void connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) {
244 safeSetFailure(promise, new UnsupportedOperationException());
245 }
246
247 @Override
248 public void registered() {
249 EventLoop loop = eventLoop();
250 if (!(loop instanceof IoEventLoop) && loop instanceof SingleThreadEventExecutor) {
251 ((SingleThreadEventExecutor) eventLoop()).addShutdownHook(shutdownHook);
252 }
253 }
254
255 @Override
256 public void unregistered() {
257 EventLoop loop = eventLoop();
258 if (!(loop instanceof IoEventLoop) && loop instanceof SingleThreadEventExecutor) {
259 ((SingleThreadEventExecutor) eventLoop()).removeShutdownHook(shutdownHook);
260 }
261 }
262
263 @Override
264 public void closeNow() {
265 close(voidPromise());
266 }
267 }
268 }