1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.bootstrap;
17
18 import io.netty.channel.Channel;
19 import io.netty.channel.ChannelConfig;
20 import io.netty.channel.ChannelHandler;
21 import io.netty.channel.ChannelHandlerContext;
22 import io.netty.channel.ChannelInboundHandlerAdapter;
23 import io.netty.channel.ChannelInitializer;
24 import io.netty.channel.ChannelOption;
25 import io.netty.channel.ChannelPipeline;
26 import io.netty.channel.EventLoopGroup;
27 import io.netty.channel.ServerChannel;
28 import io.netty.util.AttributeKey;
29 import io.netty.util.internal.ObjectUtil;
30 import io.netty.util.internal.logging.InternalLogger;
31 import io.netty.util.internal.logging.InternalLoggerFactory;
32
33 import java.util.Collection;
34 import java.util.LinkedHashMap;
35 import java.util.Map;
36 import java.util.Map.Entry;
37 import java.util.concurrent.ConcurrentHashMap;
38 import java.util.concurrent.TimeUnit;
39
40
41
42
43
44 public class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, ServerChannel> {
45
46 private static final InternalLogger logger = InternalLoggerFactory.getInstance(ServerBootstrap.class);
47
48
49
50 private final Map<ChannelOption<?>, Object> childOptions = new LinkedHashMap<ChannelOption<?>, Object>();
51 private final Map<AttributeKey<?>, Object> childAttrs = new ConcurrentHashMap<AttributeKey<?>, Object>();
52 private final ServerBootstrapConfig config = new ServerBootstrapConfig(this);
53 private volatile EventLoopGroup childGroup;
54 private volatile ChannelHandler childHandler;
55
56 public ServerBootstrap() { }
57
58 private ServerBootstrap(ServerBootstrap bootstrap) {
59 super(bootstrap);
60 childGroup = bootstrap.childGroup;
61 childHandler = bootstrap.childHandler;
62 synchronized (bootstrap.childOptions) {
63 childOptions.putAll(bootstrap.childOptions);
64 }
65 childAttrs.putAll(bootstrap.childAttrs);
66 }
67
68
69
70
71 @Override
72 public ServerBootstrap group(EventLoopGroup group) {
73 return group(group, group);
74 }
75
76
77
78
79
80
81
82
83
84 public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) {
85 super.group(parentGroup);
86 if (this.childGroup != null) {
87 throw new IllegalStateException("childGroup set already");
88 }
89 this.childGroup = ObjectUtil.checkNotNull(childGroup, "childGroup");
90 return this;
91 }
92
93
94
95
96
97
98 public <T> ServerBootstrap childOption(ChannelOption<T> childOption, T value) {
99 ObjectUtil.checkNotNull(childOption, "childOption");
100 synchronized (childOptions) {
101 if (value == null) {
102 childOptions.remove(childOption);
103 } else {
104 childOptions.put(childOption, value);
105 }
106 }
107 return this;
108 }
109
110
111
112
113
114 public <T> ServerBootstrap childAttr(AttributeKey<T> childKey, T value) {
115 ObjectUtil.checkNotNull(childKey, "childKey");
116 if (value == null) {
117 childAttrs.remove(childKey);
118 } else {
119 childAttrs.put(childKey, value);
120 }
121 return this;
122 }
123
124
125
126
127 public ServerBootstrap childHandler(ChannelHandler childHandler) {
128 this.childHandler = ObjectUtil.checkNotNull(childHandler, "childHandler");
129 return this;
130 }
131
132 @Override
133 void init(Channel channel) throws Throwable {
134 setChannelOptions(channel, newOptionsArray(), logger);
135 setAttributes(channel, newAttributesArray());
136
137 ChannelPipeline p = channel.pipeline();
138
139 final EventLoopGroup currentChildGroup = childGroup;
140 final ChannelHandler currentChildHandler = childHandler;
141 final Entry<ChannelOption<?>, Object>[] currentChildOptions = newOptionsArray(childOptions);
142 final Entry<AttributeKey<?>, Object>[] currentChildAttrs = newAttributesArray(childAttrs);
143 final Collection<ChannelInitializerExtension> extensions = getInitializerExtensions();
144
145 p.addLast(new ChannelInitializer<Channel>() {
146 @Override
147 public void initChannel(final Channel ch) {
148 final ChannelPipeline pipeline = ch.pipeline();
149 ChannelHandler handler = config.handler();
150 if (handler != null) {
151 pipeline.addLast(handler);
152 }
153
154 ch.eventLoop().execute(new Runnable() {
155 @Override
156 public void run() {
157 pipeline.addLast(new ServerBootstrapAcceptor(
158 ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs,
159 extensions));
160 }
161 });
162 }
163 });
164 if (!extensions.isEmpty() && channel instanceof ServerChannel) {
165 ServerChannel serverChannel = (ServerChannel) channel;
166 for (ChannelInitializerExtension extension : extensions) {
167 try {
168 extension.postInitializeServerListenerChannel(serverChannel);
169 } catch (Exception e) {
170 logger.warn("Exception thrown from postInitializeServerListenerChannel", e);
171 }
172 }
173 }
174 }
175
176 @Override
177 public ServerBootstrap validate() {
178 super.validate();
179 if (childHandler == null) {
180 throw new IllegalStateException("childHandler not set");
181 }
182 if (childGroup == null) {
183 logger.warn("childGroup is not set. Using parentGroup instead.");
184 childGroup = config.group();
185 }
186 return this;
187 }
188
189 private static class ServerBootstrapAcceptor extends ChannelInboundHandlerAdapter {
190
191 private final EventLoopGroup childGroup;
192 private final ChannelHandler childHandler;
193 private final Entry<ChannelOption<?>, Object>[] childOptions;
194 private final Entry<AttributeKey<?>, Object>[] childAttrs;
195 private final Runnable enableAutoReadTask;
196 private final Collection<ChannelInitializerExtension> extensions;
197
198 ServerBootstrapAcceptor(
199 final Channel channel, EventLoopGroup childGroup, ChannelHandler childHandler,
200 Entry<ChannelOption<?>, Object>[] childOptions, Entry<AttributeKey<?>, Object>[] childAttrs,
201 Collection<ChannelInitializerExtension> extensions) {
202 this.childGroup = childGroup;
203 this.childHandler = childHandler;
204 this.childOptions = childOptions;
205 this.childAttrs = childAttrs;
206 this.extensions = extensions;
207
208
209
210
211
212
213 enableAutoReadTask = new Runnable() {
214 @Override
215 public void run() {
216 channel.config().setAutoRead(true);
217 }
218 };
219 }
220
221 @Override
222 @SuppressWarnings("unchecked")
223 public void channelRead(ChannelHandlerContext ctx, Object msg) {
224 final Channel child = (Channel) msg;
225
226 child.pipeline().addLast(childHandler);
227
228 try {
229 setChannelOptions(child, childOptions, logger);
230 } catch (Throwable cause) {
231 forceClose(child, cause);
232 return;
233 }
234 setAttributes(child, childAttrs);
235
236 if (!extensions.isEmpty()) {
237 for (ChannelInitializerExtension extension : extensions) {
238 try {
239 extension.postInitializeServerChildChannel(child);
240 } catch (Exception e) {
241 logger.warn("Exception thrown from postInitializeServerChildChannel", e);
242 }
243 }
244 }
245
246 try {
247 childGroup.register(child).addListener(future -> {
248 if (!future.isSuccess()) {
249 forceClose(child, future.cause());
250 }
251 });
252 } catch (Throwable t) {
253 forceClose(child, t);
254 }
255 }
256
257 private static void forceClose(Channel child, Throwable t) {
258 child.unsafe().closeForcibly();
259 logger.warn("Failed to register an accepted channel: {}", child, t);
260 }
261
262 @Override
263 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
264 final ChannelConfig config = ctx.channel().config();
265 if (config.isAutoRead()) {
266
267
268 config.setAutoRead(false);
269 ctx.channel().eventLoop().schedule(enableAutoReadTask, 1, TimeUnit.SECONDS);
270 }
271
272
273 ctx.fireExceptionCaught(cause);
274 }
275 }
276
277 @Override
278 @SuppressWarnings("CloneDoesntCallSuperClone")
279 public ServerBootstrap clone() {
280 return new ServerBootstrap(this);
281 }
282
283
284
285
286
287
288
289 @Deprecated
290 public EventLoopGroup childGroup() {
291 return childGroup;
292 }
293
294 final ChannelHandler childHandler() {
295 return childHandler;
296 }
297
298 final Map<ChannelOption<?>, Object> childOptions() {
299 synchronized (childOptions) {
300 return copiedMap(childOptions);
301 }
302 }
303
304 final Map<AttributeKey<?>, Object> childAttrs() {
305 return copiedMap(childAttrs);
306 }
307
308 @Override
309 public final ServerBootstrapConfig config() {
310 return config;
311 }
312 }