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