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.ChannelFuture;
20  import io.netty.channel.ChannelFutureListener;
21  import io.netty.channel.ChannelPipeline;
22  import io.netty.channel.ChannelPromise;
23  import io.netty.channel.EventLoop;
24  import io.netty.channel.EventLoopGroup;
25  import io.netty.resolver.AddressResolver;
26  import io.netty.resolver.AddressResolverGroup;
27  import io.netty.resolver.DefaultAddressResolverGroup;
28  import io.netty.resolver.NameResolver;
29  import io.netty.util.concurrent.Future;
30  import io.netty.util.concurrent.FutureListener;
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.net.InetAddress;
36  import java.net.InetSocketAddress;
37  import java.net.SocketAddress;
38  import java.util.Collection;
39  
40  
41  
42  
43  
44  
45  
46  
47  public class Bootstrap extends AbstractBootstrap<Bootstrap, Channel> {
48  
49      private static final InternalLogger logger = InternalLoggerFactory.getInstance(Bootstrap.class);
50  
51      private final BootstrapConfig config = new BootstrapConfig(this);
52  
53      private ExternalAddressResolver externalResolver;
54      private volatile boolean disableResolver;
55      private volatile SocketAddress remoteAddress;
56  
57      public Bootstrap() { }
58  
59      private Bootstrap(Bootstrap bootstrap) {
60          super(bootstrap);
61          externalResolver = bootstrap.externalResolver;
62          disableResolver = bootstrap.disableResolver;
63          remoteAddress = bootstrap.remoteAddress;
64      }
65  
66      
67  
68  
69  
70  
71  
72  
73  
74      public Bootstrap resolver(AddressResolverGroup<?> resolver) {
75          externalResolver = resolver == null ? null : new ExternalAddressResolver(resolver);
76          disableResolver = false;
77          return this;
78      }
79  
80      
81  
82  
83  
84      public Bootstrap disableResolver() {
85          externalResolver = null;
86          disableResolver = true;
87          return this;
88      }
89  
90      
91  
92  
93  
94      public Bootstrap remoteAddress(SocketAddress remoteAddress) {
95          this.remoteAddress = remoteAddress;
96          return this;
97      }
98  
99      
100 
101 
102     public Bootstrap remoteAddress(String inetHost, int inetPort) {
103         remoteAddress = InetSocketAddress.createUnresolved(inetHost, inetPort);
104         return this;
105     }
106 
107     
108 
109 
110     public Bootstrap remoteAddress(InetAddress inetHost, int inetPort) {
111         remoteAddress = new InetSocketAddress(inetHost, inetPort);
112         return this;
113     }
114 
115     
116 
117 
118     public ChannelFuture connect() {
119         validate();
120         SocketAddress remoteAddress = this.remoteAddress;
121         if (remoteAddress == null) {
122             throw new IllegalStateException("remoteAddress not set");
123         }
124 
125         return doResolveAndConnect(remoteAddress, config.localAddress());
126     }
127 
128     
129 
130 
131     public ChannelFuture connect(String inetHost, int inetPort) {
132         return connect(InetSocketAddress.createUnresolved(inetHost, inetPort));
133     }
134 
135     
136 
137 
138     public ChannelFuture connect(InetAddress inetHost, int inetPort) {
139         return connect(new InetSocketAddress(inetHost, inetPort));
140     }
141 
142     
143 
144 
145     public ChannelFuture connect(SocketAddress remoteAddress) {
146         ObjectUtil.checkNotNull(remoteAddress, "remoteAddress");
147         validate();
148         return doResolveAndConnect(remoteAddress, config.localAddress());
149     }
150 
151     
152 
153 
154     public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress) {
155         ObjectUtil.checkNotNull(remoteAddress, "remoteAddress");
156         validate();
157         return doResolveAndConnect(remoteAddress, localAddress);
158     }
159 
160     
161 
162 
163     private ChannelFuture doResolveAndConnect(final SocketAddress remoteAddress, final SocketAddress localAddress) {
164         final ChannelFuture regFuture = initAndRegister();
165         final Channel channel = regFuture.channel();
166 
167         if (regFuture.isDone()) {
168             if (!regFuture.isSuccess()) {
169                 return regFuture;
170             }
171             return doResolveAndConnect0(channel, remoteAddress, localAddress, channel.newPromise());
172         } else {
173             
174             final PendingRegistrationPromise promise = new PendingRegistrationPromise(channel);
175             regFuture.addListener(new ChannelFutureListener() {
176                 @Override
177                 public void operationComplete(ChannelFuture future) throws Exception {
178                     
179                     
180                     Throwable cause = future.cause();
181                     if (cause != null) {
182                         
183                         
184                         promise.setFailure(cause);
185                     } else {
186                         
187                         
188                         promise.registered();
189                         doResolveAndConnect0(channel, remoteAddress, localAddress, promise);
190                     }
191                 }
192             });
193             return promise;
194         }
195     }
196 
197     private ChannelFuture doResolveAndConnect0(final Channel channel, SocketAddress remoteAddress,
198                                                final SocketAddress localAddress, final ChannelPromise promise) {
199         try {
200             if (disableResolver) {
201                 doConnect(remoteAddress, localAddress, promise);
202                 return promise;
203             }
204 
205             final EventLoop eventLoop = channel.eventLoop();
206             AddressResolver<SocketAddress> resolver;
207             try {
208                 resolver = ExternalAddressResolver.getOrDefault(externalResolver).getResolver(eventLoop);
209             } catch (Throwable cause) {
210                 channel.close();
211                 return promise.setFailure(cause);
212             }
213 
214             if (!resolver.isSupported(remoteAddress) || resolver.isResolved(remoteAddress)) {
215                 
216                 doConnect(remoteAddress, localAddress, promise);
217                 return promise;
218             }
219 
220             final Future<SocketAddress> resolveFuture = resolver.resolve(remoteAddress);
221 
222             if (resolveFuture.isDone()) {
223                 final Throwable resolveFailureCause = resolveFuture.cause();
224 
225                 if (resolveFailureCause != null) {
226                     
227                     channel.close();
228                     promise.setFailure(resolveFailureCause);
229                 } else {
230                     
231                     doConnect(resolveFuture.getNow(), localAddress, promise);
232                 }
233                 return promise;
234             }
235 
236             
237             resolveFuture.addListener(new FutureListener<SocketAddress>() {
238                 @Override
239                 public void operationComplete(Future<SocketAddress> future) throws Exception {
240                     if (future.cause() != null) {
241                         channel.close();
242                         promise.setFailure(future.cause());
243                     } else {
244                         doConnect(future.getNow(), localAddress, promise);
245                     }
246                 }
247             });
248         } catch (Throwable cause) {
249             promise.tryFailure(cause);
250         }
251         return promise;
252     }
253 
254     private static void doConnect(
255             final SocketAddress remoteAddress, final SocketAddress localAddress, final ChannelPromise connectPromise) {
256 
257         
258         
259         final Channel channel = connectPromise.channel();
260         channel.eventLoop().execute(new Runnable() {
261             @Override
262             public void run() {
263                 if (localAddress == null) {
264                     channel.connect(remoteAddress, connectPromise);
265                 } else {
266                     channel.connect(remoteAddress, localAddress, connectPromise);
267                 }
268                 connectPromise.addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
269             }
270         });
271     }
272 
273     @Override
274     void init(Channel channel) {
275         ChannelPipeline p = channel.pipeline();
276         p.addLast(config.handler());
277 
278         setChannelOptions(channel, newOptionsArray(), logger);
279         setAttributes(channel, newAttributesArray());
280         Collection<ChannelInitializerExtension> extensions = getInitializerExtensions();
281         if (!extensions.isEmpty()) {
282             for (ChannelInitializerExtension extension : extensions) {
283                 try {
284                     extension.postInitializeClientChannel(channel);
285                 } catch (Exception e) {
286                     logger.warn("Exception thrown from postInitializeClientChannel", e);
287                 }
288             }
289         }
290     }
291 
292     @Override
293     public Bootstrap validate() {
294         super.validate();
295         if (config.handler() == null) {
296             throw new IllegalStateException("handler not set");
297         }
298         return this;
299     }
300 
301     @Override
302     @SuppressWarnings("CloneDoesntCallSuperClone")
303     public Bootstrap clone() {
304         return new Bootstrap(this);
305     }
306 
307     
308 
309 
310 
311 
312     public Bootstrap clone(EventLoopGroup group) {
313         Bootstrap bs = new Bootstrap(this);
314         bs.group = group;
315         return bs;
316     }
317 
318     @Override
319     public final BootstrapConfig config() {
320         return config;
321     }
322 
323     final SocketAddress remoteAddress() {
324         return remoteAddress;
325     }
326 
327     final AddressResolverGroup<?> resolver() {
328         if (disableResolver) {
329             return null;
330         }
331         return ExternalAddressResolver.getOrDefault(externalResolver);
332     }
333 
334     
335 
336     static final class ExternalAddressResolver {
337         final AddressResolverGroup<SocketAddress> resolverGroup;
338 
339         @SuppressWarnings("unchecked")
340         ExternalAddressResolver(AddressResolverGroup<?> resolverGroup) {
341             this.resolverGroup = (AddressResolverGroup<SocketAddress>) resolverGroup;
342         }
343 
344         @SuppressWarnings("unchecked")
345         static AddressResolverGroup<SocketAddress> getOrDefault(ExternalAddressResolver externalResolver) {
346             if (externalResolver == null) {
347                 AddressResolverGroup<?> defaultResolverGroup = DefaultAddressResolverGroup.INSTANCE;
348                 return (AddressResolverGroup<SocketAddress>) defaultResolverGroup;
349             }
350             return externalResolver.resolverGroup;
351         }
352     }
353 }