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.ChannelFuture;
21 import io.netty.channel.ChannelFutureListener;
22 import io.netty.channel.ChannelHandler;
23 import io.netty.channel.ChannelHandlerContext;
24 import io.netty.channel.ChannelInboundHandlerAdapter;
25 import io.netty.channel.ChannelInitializer;
26 import io.netty.channel.ChannelOption;
27 import io.netty.channel.ChannelPipeline;
28 import io.netty.channel.EventLoopGroup;
29 import io.netty.channel.ServerChannel;
30 import io.netty.util.AttributeKey;
31 import io.netty.util.internal.ObjectUtil;
32 import io.netty.util.internal.logging.InternalLogger;
33 import io.netty.util.internal.logging.InternalLoggerFactory;
34
35 import java.util.Collection;
36 import java.util.LinkedHashMap;
37 import java.util.Map;
38 import java.util.Map.Entry;
39 import java.util.concurrent.ConcurrentHashMap;
40 import java.util.concurrent.TimeUnit;
41
42
43
44
45
46 public class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, ServerChannel> {
47
48 private static final InternalLogger logger = InternalLoggerFactory.getInstance(ServerBootstrap.class);
49
50
51
52 private final Map<ChannelOption<?>, Object> childOptions = new LinkedHashMap<ChannelOption<?>, Object>();
53 private final Map<AttributeKey<?>, Object> childAttrs = new ConcurrentHashMap<AttributeKey<?>, Object>();
54 private final ServerBootstrapConfig config = new ServerBootstrapConfig(this);
55 private volatile EventLoopGroup childGroup;
56 private volatile ChannelHandler childHandler;
57
58 public ServerBootstrap() { }
59
60 private ServerBootstrap(ServerBootstrap bootstrap) {
61 super(bootstrap);
62 childGroup = bootstrap.childGroup;
63 childHandler = bootstrap.childHandler;
64 synchronized (bootstrap.childOptions) {
65 childOptions.putAll(bootstrap.childOptions);
66 }
67 childAttrs.putAll(bootstrap.childAttrs);
68 }
69
70
71
72
73 @Override
74 public ServerBootstrap group(EventLoopGroup group) {
75 return group(group, group);
76 }
77
78
79
80
81
82
83
84
85
86 public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) {
87 super.group(parentGroup);
88 if (this.childGroup != null) {
89 throw new IllegalStateException("childGroup set already");
90 }
91 this.childGroup = ObjectUtil.checkNotNull(childGroup, "childGroup");
92 return this;
93 }
94
95
96
97
98
99
100 public <T> ServerBootstrap childOption(ChannelOption<T> childOption, T value) {
101 ObjectUtil.checkNotNull(childOption, "childOption");
102 synchronized (childOptions) {
103 if (value == null) {
104 childOptions.remove(childOption);
105 } else {
106 childOptions.put(childOption, value);
107 }
108 }
109 return this;
110 }
111
112
113
114
115
116 public <T> ServerBootstrap childAttr(AttributeKey<T> childKey, T value) {
117 ObjectUtil.checkNotNull(childKey, "childKey");
118 if (value == null) {
119 childAttrs.remove(childKey);
120 } else {
121 childAttrs.put(childKey, value);
122 }
123 return this;
124 }
125
126
127
128
129 public ServerBootstrap childHandler(ChannelHandler childHandler) {
130 this.childHandler = ObjectUtil.checkNotNull(childHandler, "childHandler");
131 return this;
132 }
133
134 @Override
135 void init(Channel channel) {
136 setChannelOptions(channel, newOptionsArray(), logger);
137 setAttributes(channel, newAttributesArray());
138
139 ChannelPipeline p = channel.pipeline();
140
141 final EventLoopGroup currentChildGroup = childGroup;
142 final ChannelHandler currentChildHandler = childHandler;
143 final Entry<ChannelOption<?>, Object>[] currentChildOptions = newOptionsArray(childOptions);
144 final Entry<AttributeKey<?>, Object>[] currentChildAttrs = newAttributesArray(childAttrs);
145 final Collection<ChannelInitializerExtension> extensions = getInitializerExtensions();
146
147 p.addLast(new ChannelInitializer<Channel>() {
148 @Override
149 public void initChannel(final Channel ch) {
150 final ChannelPipeline pipeline = ch.pipeline();
151 ChannelHandler handler = config.handler();
152 if (handler != null) {
153 pipeline.addLast(handler);
154 }
155
156 ch.eventLoop().execute(new Runnable() {
157 @Override
158 public void run() {
159 pipeline.addLast(new ServerBootstrapAcceptor(
160 ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs,
161 extensions));
162 }
163 });
164 }
165 });
166 if (!extensions.isEmpty() && channel instanceof ServerChannel) {
167 ServerChannel serverChannel = (ServerChannel) channel;
168 for (ChannelInitializerExtension extension : extensions) {
169 try {
170 extension.postInitializeServerListenerChannel(serverChannel);
171 } catch (Exception e) {
172 logger.warn("Exception thrown from postInitializeServerListenerChannel", e);
173 }
174 }
175 }
176 }
177
178 @Override
179 public ServerBootstrap validate() {
180 super.validate();
181 if (childHandler == null) {
182 throw new IllegalStateException("childHandler not set");
183 }
184 if (childGroup == null) {
185 logger.warn("childGroup is not set. Using parentGroup instead.");
186 childGroup = config.group();
187 }
188 return this;
189 }
190
191 private static class ServerBootstrapAcceptor extends ChannelInboundHandlerAdapter {
192
193 private final EventLoopGroup childGroup;
194 private final ChannelHandler childHandler;
195 private final Entry<ChannelOption<?>, Object>[] childOptions;
196 private final Entry<AttributeKey<?>, Object>[] childAttrs;
197 private final Runnable enableAutoReadTask;
198 private final Collection<ChannelInitializerExtension> extensions;
199
200 ServerBootstrapAcceptor(
201 final Channel channel, EventLoopGroup childGroup, ChannelHandler childHandler,
202 Entry<ChannelOption<?>, Object>[] childOptions, Entry<AttributeKey<?>, Object>[] childAttrs,
203 Collection<ChannelInitializerExtension> extensions) {
204 this.childGroup = childGroup;
205 this.childHandler = childHandler;
206 this.childOptions = childOptions;
207 this.childAttrs = childAttrs;
208 this.extensions = extensions;
209
210
211
212
213
214
215 enableAutoReadTask = new Runnable() {
216 @Override
217 public void run() {
218 channel.config().setAutoRead(true);
219 }
220 };
221 }
222
223 @Override
224 @SuppressWarnings("unchecked")
225 public void channelRead(ChannelHandlerContext ctx, Object msg) {
226 final Channel child = (Channel) msg;
227
228 child.pipeline().addLast(childHandler);
229
230 setChannelOptions(child, childOptions, logger);
231 setAttributes(child, childAttrs);
232
233 if (!extensions.isEmpty()) {
234 for (ChannelInitializerExtension extension : extensions) {
235 try {
236 extension.postInitializeServerChildChannel(child);
237 } catch (Exception e) {
238 logger.warn("Exception thrown from postInitializeServerChildChannel", e);
239 }
240 }
241 }
242
243 try {
244 childGroup.register(child).addListener(new ChannelFutureListener() {
245 @Override
246 public void operationComplete(ChannelFuture future) throws Exception {
247 if (!future.isSuccess()) {
248 forceClose(child, future.cause());
249 }
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 }