1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty5.channel.socket.nio;
17
18 import io.netty5.channel.Channel;
19 import io.netty5.channel.ChannelException;
20 import io.netty5.channel.ChannelMetadata;
21 import io.netty5.channel.ChannelOption;
22 import io.netty5.channel.ChannelOutboundBuffer;
23 import io.netty5.channel.ChannelShutdownDirection;
24 import io.netty5.channel.EventLoop;
25 import io.netty5.channel.EventLoopGroup;
26 import io.netty5.channel.ServerChannelRecvBufferAllocator;
27 import io.netty5.channel.nio.AbstractNioMessageChannel;
28 import io.netty5.channel.socket.SocketProtocolFamily;
29 import io.netty5.util.NetUtil;
30 import io.netty5.util.internal.SocketUtils;
31 import io.netty5.util.internal.logging.InternalLogger;
32 import io.netty5.util.internal.logging.InternalLoggerFactory;
33
34 import java.io.IOException;
35 import java.lang.reflect.Method;
36 import java.net.ProtocolFamily;
37 import java.net.SocketAddress;
38 import java.net.SocketOption;
39 import java.nio.channels.SelectionKey;
40 import java.nio.channels.ServerSocketChannel;
41 import java.nio.channels.SocketChannel;
42 import java.nio.channels.spi.SelectorProvider;
43 import java.util.List;
44
45 import static io.netty5.channel.ChannelOption.SO_BACKLOG;
46 import static io.netty5.channel.socket.nio.NioChannelUtil.isDomainSocket;
47 import static io.netty5.channel.socket.nio.NioChannelUtil.toDomainSocketAddress;
48 import static io.netty5.channel.socket.nio.NioChannelUtil.toJdkFamily;
49 import static io.netty5.channel.socket.nio.NioChannelUtil.toUnixDomainSocketAddress;
50 import static io.netty5.util.internal.ObjectUtil.checkPositiveOrZero;
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 public class NioServerSocketChannel extends AbstractNioMessageChannel<Channel, SocketAddress, SocketAddress>
73 implements io.netty5.channel.socket.ServerSocketChannel {
74
75 private static final ChannelMetadata METADATA = new ChannelMetadata(false, 16);
76 private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider();
77
78 private static final InternalLogger logger = InternalLoggerFactory.getInstance(NioServerSocketChannel.class);
79
80 private static final Method OPEN_SERVER_SOCKET_CHANNEL_WITH_FAMILY =
81 NioChannelUtil.findOpenMethod("openServerSocketChannel");
82
83 private static ServerSocketChannel newChannel(SelectorProvider provider, ProtocolFamily family) {
84 try {
85 ServerSocketChannel channel =
86 NioChannelUtil.newChannel(OPEN_SERVER_SOCKET_CHANNEL_WITH_FAMILY, provider, family);
87 return channel == null ? provider.openServerSocketChannel() : channel;
88 } catch (IOException e) {
89 throw new ChannelException("Failed to open a socket.", e);
90 }
91 }
92
93 private final ProtocolFamily family;
94
95 private final EventLoopGroup childEventLoopGroup;
96
97 private volatile int backlog = NetUtil.SOMAXCONN;
98
99 private volatile boolean bound;
100
101
102
103
104 public NioServerSocketChannel(EventLoop eventLoop, EventLoopGroup childEventLoopGroup) {
105 this(eventLoop, childEventLoopGroup, DEFAULT_SELECTOR_PROVIDER);
106 }
107
108
109
110
111 public NioServerSocketChannel(EventLoop eventLoop, EventLoopGroup childEventLoopGroup, SelectorProvider provider) {
112 this(eventLoop, childEventLoopGroup, provider, null);
113 }
114
115
116
117
118 public NioServerSocketChannel(EventLoop eventLoop, EventLoopGroup childEventLoopGroup,
119 SelectorProvider provider, ProtocolFamily protocolFamily) {
120 this(eventLoop, childEventLoopGroup, newChannel(provider, toJdkFamily(protocolFamily)), protocolFamily);
121 }
122
123
124
125
126 public NioServerSocketChannel(
127 EventLoop eventLoop, EventLoopGroup childEventLoopGroup, ServerSocketChannel channel) {
128 this(eventLoop, childEventLoopGroup, channel, null);
129 }
130
131
132
133
134 public NioServerSocketChannel(
135 EventLoop eventLoop, EventLoopGroup childEventLoopGroup,
136 ServerSocketChannel channel, ProtocolFamily family) {
137 super(null, eventLoop, METADATA, new ServerChannelRecvBufferAllocator(),
138 channel, SelectionKey.OP_ACCEPT);
139 this.family = toJdkFamily(family);
140 this.childEventLoopGroup = validateEventLoopGroup(
141 childEventLoopGroup, "childEventLoopGroup", NioSocketChannel.class);
142 }
143
144 @Override
145 public EventLoopGroup childEventLoopGroup() {
146 return childEventLoopGroup;
147 }
148
149 @Override
150 public boolean isActive() {
151
152
153 return isOpen() && bound;
154 }
155
156 @SuppressWarnings("unchecked")
157 @Override
158 protected <T> T getExtendedOption(ChannelOption<T> option) {
159 if (option == SO_BACKLOG) {
160 return (T) Integer.valueOf(getBacklog());
161 }
162 SocketOption<T> socketOption = NioChannelOption.toSocketOption(option);
163 if (socketOption != null) {
164 return NioChannelOption.getOption(javaChannel(), socketOption);
165 }
166 return super.getExtendedOption(option);
167 }
168
169 @Override
170 protected <T> void setExtendedOption(ChannelOption<T> option, T value) {
171 if (option == SO_BACKLOG) {
172 setBacklog((Integer) value);
173 } else {
174 SocketOption<T> socketOption = NioChannelOption.toSocketOption(option);
175 if (socketOption != null) {
176 NioChannelOption.setOption(javaChannel(), socketOption, value);
177 } else {
178 super.setExtendedOption(option, value);
179 }
180 }
181 }
182
183 @Override
184 protected boolean isExtendedOptionSupported(ChannelOption<?> option) {
185 if (option == SO_BACKLOG) {
186 return true;
187 }
188 SocketOption<?> socketOption = NioChannelOption.toSocketOption(option);
189 if (socketOption != null) {
190 return NioChannelOption.isOptionSupported(javaChannel(), socketOption);
191 }
192 return super.isExtendedOptionSupported(option);
193 }
194
195 private int getBacklog() {
196 return backlog;
197 }
198
199 private void setBacklog(int backlog) {
200 checkPositiveOrZero(backlog, "backlog");
201 this.backlog = backlog;
202 }
203
204 @Override
205 protected ServerSocketChannel javaChannel() {
206 return (ServerSocketChannel) super.javaChannel();
207 }
208
209 @Override
210 protected SocketAddress localAddress0() {
211 try {
212 SocketAddress address = javaChannel().getLocalAddress();
213 if (isDomainSocket(family)) {
214 address = toDomainSocketAddress(address);
215 }
216 return address;
217 } catch (IOException e) {
218
219 return null;
220 }
221 }
222
223 @Override
224 protected void doShutdown(ChannelShutdownDirection direction) throws Exception {
225 throw new UnsupportedOperationException();
226 }
227
228 @Override
229 public boolean isShutdown(ChannelShutdownDirection direction) {
230 return !isActive();
231 }
232
233 @Override
234 protected void doBind(SocketAddress localAddress) throws Exception {
235 if (isDomainSocket(family)) {
236 localAddress = toUnixDomainSocketAddress(localAddress);
237 }
238 javaChannel().bind(localAddress, getBacklog());
239 bound = true;
240 }
241
242 @Override
243 protected int doReadMessages(List<Object> buf) throws Exception {
244 SocketChannel ch = SocketUtils.accept(javaChannel());
245
246 try {
247 if (ch != null) {
248 buf.add(new NioSocketChannel(this, childEventLoopGroup().next(), ch, family));
249 return 1;
250 }
251 } catch (Throwable t) {
252 logger.warn("Failed to create a new channel from an accepted socket.", t);
253
254 try {
255 ch.close();
256 } catch (Throwable t2) {
257 logger.warn("Failed to close a socket.", t2);
258 }
259 }
260
261 return 0;
262 }
263
264
265 @Override
266 protected boolean doConnect(
267 SocketAddress remoteAddress, SocketAddress localAddress) {
268 throw new UnsupportedOperationException();
269 }
270
271 @Override
272 protected boolean doFinishConnect(SocketAddress requestedRemoteAddress) {
273 throw new UnsupportedOperationException();
274 }
275
276 @Override
277 protected SocketAddress remoteAddress0() {
278 return null;
279 }
280
281 @Override
282 protected void doDisconnect() {
283 throw new UnsupportedOperationException();
284 }
285
286 @Override
287 protected boolean doWriteMessage(Object msg, ChannelOutboundBuffer in) {
288 throw new UnsupportedOperationException();
289 }
290
291 @Override
292 protected final Object filterOutboundMessage(Object msg) {
293 throw new UnsupportedOperationException();
294 }
295
296 @Override
297 protected void autoReadCleared() {
298 clearReadPending();
299 }
300
301
302 @Override
303 protected boolean closeOnReadError(Throwable cause) {
304 return super.closeOnReadError(cause);
305 }
306 }