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