1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.channel.socket.nio;
17
18 import io.netty.channel.ChannelException;
19 import io.netty.channel.ChannelMetadata;
20 import io.netty.channel.ChannelOption;
21 import io.netty.channel.ChannelOutboundBuffer;
22 import io.netty.channel.nio.AbstractNioMessageChannel;
23 import io.netty.channel.socket.DefaultServerSocketChannelConfig;
24 import io.netty.channel.socket.InternetProtocolFamily;
25 import io.netty.channel.socket.ServerSocketChannelConfig;
26 import io.netty.channel.socket.SocketProtocolFamily;
27 import io.netty.util.internal.SocketUtils;
28 import io.netty.util.internal.logging.InternalLogger;
29 import io.netty.util.internal.logging.InternalLoggerFactory;
30
31 import java.io.IOException;
32 import java.lang.reflect.Method;
33 import java.net.InetSocketAddress;
34 import java.net.ServerSocket;
35 import java.net.SocketAddress;
36 import java.nio.channels.SelectionKey;
37 import java.nio.channels.ServerSocketChannel;
38 import java.nio.channels.SocketChannel;
39 import java.nio.channels.spi.SelectorProvider;
40 import java.util.List;
41 import java.util.Map;
42
43
44
45
46
47 public class NioServerSocketChannel extends AbstractNioMessageChannel
48 implements io.netty.channel.socket.ServerSocketChannel {
49
50 private static final ChannelMetadata METADATA = new ChannelMetadata(false, 16);
51 private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider();
52
53 private static final InternalLogger logger = InternalLoggerFactory.getInstance(NioServerSocketChannel.class);
54
55 private static final Method OPEN_SERVER_SOCKET_CHANNEL_WITH_FAMILY =
56 SelectorProviderUtil.findOpenMethod("openServerSocketChannel");
57
58 private static ServerSocketChannel newChannel(SelectorProvider provider, SocketProtocolFamily family) {
59 try {
60 ServerSocketChannel channel =
61 SelectorProviderUtil.newChannel(OPEN_SERVER_SOCKET_CHANNEL_WITH_FAMILY, provider, family);
62 return channel == null ? provider.openServerSocketChannel() : channel;
63 } catch (IOException e) {
64 throw new ChannelException("Failed to open a socket.", e);
65 }
66 }
67
68 private final ServerSocketChannelConfig config;
69
70
71
72
73 public NioServerSocketChannel() {
74 this(DEFAULT_SELECTOR_PROVIDER);
75 }
76
77
78
79
80 public NioServerSocketChannel(SelectorProvider provider) {
81 this(provider, (SocketProtocolFamily) null);
82 }
83
84
85
86
87
88
89 @Deprecated
90 public NioServerSocketChannel(SelectorProvider provider, InternetProtocolFamily family) {
91 this(provider, family == null ? null : family.toSocketProtocolFamily());
92 }
93
94
95
96
97 public NioServerSocketChannel(SelectorProvider provider, SocketProtocolFamily family) {
98 this(newChannel(provider, family));
99 }
100
101
102
103
104 public NioServerSocketChannel(ServerSocketChannel channel) {
105 super(null, channel, SelectionKey.OP_ACCEPT);
106 config = new NioServerSocketChannelConfig(this, javaChannel().socket());
107 }
108
109 @Override
110 public InetSocketAddress localAddress() {
111 return (InetSocketAddress) super.localAddress();
112 }
113
114 @Override
115 public ChannelMetadata metadata() {
116 return METADATA;
117 }
118
119 @Override
120 public ServerSocketChannelConfig config() {
121 return config;
122 }
123
124 @Override
125 public boolean isActive() {
126
127
128 return isOpen() && javaChannel().socket().isBound();
129 }
130
131 @Override
132 public InetSocketAddress remoteAddress() {
133 return null;
134 }
135
136 @Override
137 protected ServerSocketChannel javaChannel() {
138 return (ServerSocketChannel) super.javaChannel();
139 }
140
141 @Override
142 protected SocketAddress localAddress0() {
143 return SocketUtils.localSocketAddress(javaChannel().socket());
144 }
145
146 @Override
147 protected void doBind(SocketAddress localAddress) throws Exception {
148 javaChannel().bind(localAddress, config.getBacklog());
149 }
150
151 @Override
152 protected void doClose() throws Exception {
153 javaChannel().close();
154 }
155
156 @Override
157 protected int doReadMessages(List<Object> buf) throws Exception {
158 SocketChannel ch = SocketUtils.accept(javaChannel());
159
160 try {
161 if (ch != null) {
162 buf.add(new NioSocketChannel(this, ch));
163 return 1;
164 }
165 } catch (Throwable t) {
166 logger.warn("Failed to create a new channel from an accepted socket.", t);
167
168 try {
169 ch.close();
170 } catch (Throwable t2) {
171 logger.warn("Failed to close a socket.", t2);
172 }
173 }
174
175 return 0;
176 }
177
178
179 @Override
180 protected boolean doConnect(
181 SocketAddress remoteAddress, SocketAddress localAddress) throws Exception {
182 throw new UnsupportedOperationException();
183 }
184
185 @Override
186 protected void doFinishConnect() throws Exception {
187 throw new UnsupportedOperationException();
188 }
189
190 @Override
191 protected SocketAddress remoteAddress0() {
192 return null;
193 }
194
195 @Override
196 protected void doDisconnect() throws Exception {
197 throw new UnsupportedOperationException();
198 }
199
200 @Override
201 protected boolean doWriteMessage(Object msg, ChannelOutboundBuffer in) throws Exception {
202 throw new UnsupportedOperationException();
203 }
204
205 @Override
206 protected final Object filterOutboundMessage(Object msg) throws Exception {
207 throw new UnsupportedOperationException();
208 }
209
210 private final class NioServerSocketChannelConfig extends DefaultServerSocketChannelConfig {
211 private NioServerSocketChannelConfig(NioServerSocketChannel channel, ServerSocket javaSocket) {
212 super(channel, javaSocket);
213 }
214
215 @Override
216 protected void autoReadCleared() {
217 clearReadPending();
218 }
219
220 @Override
221 public <T> boolean setOption(ChannelOption<T> option, T value) {
222 if (option instanceof NioChannelOption) {
223 return NioChannelOption.setOption(jdkChannel(), (NioChannelOption<T>) option, value);
224 }
225 return super.setOption(option, value);
226 }
227
228 @Override
229 public <T> T getOption(ChannelOption<T> option) {
230 if (option instanceof NioChannelOption) {
231 return NioChannelOption.getOption(jdkChannel(), (NioChannelOption<T>) option);
232 }
233 return super.getOption(option);
234 }
235
236 @Override
237 public Map<ChannelOption<?>, Object> getOptions() {
238 return getOptions(super.getOptions(), NioChannelOption.getOptions(jdkChannel()));
239 }
240
241 private ServerSocketChannel jdkChannel() {
242 return ((NioServerSocketChannel) channel).javaChannel();
243 }
244 }
245
246
247 @Override
248 protected boolean closeOnReadError(Throwable cause) {
249 return super.closeOnReadError(cause);
250 }
251 }