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 }