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(future -> {
176
177
178 Throwable cause = future.cause();
179 if (cause != null) {
180
181
182 promise.setFailure(cause);
183 } else {
184
185
186 promise.registered();
187 doResolveAndConnect0(channel, remoteAddress, localAddress, promise);
188 }
189 });
190 return promise;
191 }
192 }
193
194 private ChannelFuture doResolveAndConnect0(final Channel channel, SocketAddress remoteAddress,
195 final SocketAddress localAddress, final ChannelPromise promise) {
196 try {
197 if (disableResolver) {
198 doConnect(remoteAddress, localAddress, promise);
199 return promise;
200 }
201
202 final EventLoop eventLoop = channel.eventLoop();
203 AddressResolver<SocketAddress> resolver;
204 try {
205 resolver = ExternalAddressResolver.getOrDefault(externalResolver).getResolver(eventLoop);
206 } catch (Throwable cause) {
207 channel.close();
208 return promise.setFailure(cause);
209 }
210
211 if (!resolver.isSupported(remoteAddress) || resolver.isResolved(remoteAddress)) {
212
213 doConnect(remoteAddress, localAddress, promise);
214 return promise;
215 }
216
217 final Future<SocketAddress> resolveFuture = resolver.resolve(remoteAddress);
218
219 if (resolveFuture.isDone()) {
220 final Throwable resolveFailureCause = resolveFuture.cause();
221
222 if (resolveFailureCause != null) {
223
224 channel.close();
225 promise.setFailure(resolveFailureCause);
226 } else {
227
228 doConnect(resolveFuture.getNow(), localAddress, promise);
229 }
230 return promise;
231 }
232
233
234 resolveFuture.addListener((FutureListener<SocketAddress>) future -> {
235 if (future.cause() != null) {
236 channel.close();
237 promise.setFailure(future.cause());
238 } else {
239 doConnect(future.getNow(), localAddress, promise);
240 }
241 });
242 } catch (Throwable cause) {
243 promise.tryFailure(cause);
244 }
245 return promise;
246 }
247
248 private static void doConnect(
249 final SocketAddress remoteAddress, final SocketAddress localAddress, final ChannelPromise connectPromise) {
250
251
252
253 final Channel channel = connectPromise.channel();
254 channel.eventLoop().execute(new Runnable() {
255 @Override
256 public void run() {
257 if (localAddress == null) {
258 channel.connect(remoteAddress, connectPromise);
259 } else {
260 channel.connect(remoteAddress, localAddress, connectPromise);
261 }
262 connectPromise.addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
263 }
264 });
265 }
266
267 @Override
268 void init(Channel channel) throws Throwable {
269 ChannelPipeline p = channel.pipeline();
270 p.addLast(config.handler());
271
272 setChannelOptions(channel, newOptionsArray(), logger);
273
274 setAttributes(channel, newAttributesArray());
275 Collection<ChannelInitializerExtension> extensions = getInitializerExtensions();
276 if (!extensions.isEmpty()) {
277 for (ChannelInitializerExtension extension : extensions) {
278 try {
279 extension.postInitializeClientChannel(channel);
280 } catch (Exception e) {
281 logger.warn("Exception thrown from postInitializeClientChannel", e);
282 }
283 }
284 }
285 }
286
287 @Override
288 public Bootstrap validate() {
289 super.validate();
290 if (config.handler() == null) {
291 throw new IllegalStateException("handler not set");
292 }
293 return this;
294 }
295
296 @Override
297 @SuppressWarnings("CloneDoesntCallSuperClone")
298 public Bootstrap clone() {
299 return new Bootstrap(this);
300 }
301
302
303
304
305
306
307 public Bootstrap clone(EventLoopGroup group) {
308 Bootstrap bs = new Bootstrap(this);
309 bs.group = group;
310 return bs;
311 }
312
313 @Override
314 public final BootstrapConfig config() {
315 return config;
316 }
317
318 final SocketAddress remoteAddress() {
319 return remoteAddress;
320 }
321
322 final AddressResolverGroup<?> resolver() {
323 if (disableResolver) {
324 return null;
325 }
326 return ExternalAddressResolver.getOrDefault(externalResolver);
327 }
328
329
330
331 static final class ExternalAddressResolver {
332 final AddressResolverGroup<SocketAddress> resolverGroup;
333
334 @SuppressWarnings("unchecked")
335 ExternalAddressResolver(AddressResolverGroup<?> resolverGroup) {
336 this.resolverGroup = (AddressResolverGroup<SocketAddress>) resolverGroup;
337 }
338
339 @SuppressWarnings("unchecked")
340 static AddressResolverGroup<SocketAddress> getOrDefault(ExternalAddressResolver externalResolver) {
341 if (externalResolver == null) {
342 AddressResolverGroup<?> defaultResolverGroup = DefaultAddressResolverGroup.INSTANCE;
343 return (AddressResolverGroup<SocketAddress>) defaultResolverGroup;
344 }
345 return externalResolver.resolverGroup;
346 }
347 }
348 }