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