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.ChannelOption;
22 import io.netty.channel.ChannelPipeline;
23 import io.netty.channel.ChannelPromise;
24 import io.netty.channel.EventLoopGroup;
25 import io.netty.util.AttributeKey;
26 import io.netty.util.internal.logging.InternalLogger;
27 import io.netty.util.internal.logging.InternalLoggerFactory;
28
29 import java.net.InetAddress;
30 import java.net.InetSocketAddress;
31 import java.net.SocketAddress;
32 import java.util.Map;
33 import java.util.Map.Entry;
34
35
36
37
38
39
40
41
42 public class Bootstrap extends AbstractBootstrap<Bootstrap, Channel> {
43
44 private static final InternalLogger logger = InternalLoggerFactory.getInstance(Bootstrap.class);
45
46 private volatile SocketAddress remoteAddress;
47
48 public Bootstrap() { }
49
50 private Bootstrap(Bootstrap bootstrap) {
51 super(bootstrap);
52 remoteAddress = bootstrap.remoteAddress;
53 }
54
55
56
57
58
59 public Bootstrap remoteAddress(SocketAddress remoteAddress) {
60 this.remoteAddress = remoteAddress;
61 return this;
62 }
63
64
65
66
67 public Bootstrap remoteAddress(String inetHost, int inetPort) {
68 remoteAddress = new InetSocketAddress(inetHost, inetPort);
69 return this;
70 }
71
72
73
74
75 public Bootstrap remoteAddress(InetAddress inetHost, int inetPort) {
76 remoteAddress = new InetSocketAddress(inetHost, inetPort);
77 return this;
78 }
79
80
81
82
83 public ChannelFuture connect() {
84 validate();
85 SocketAddress remoteAddress = this.remoteAddress;
86 if (remoteAddress == null) {
87 throw new IllegalStateException("remoteAddress not set");
88 }
89
90 return doConnect(remoteAddress, localAddress());
91 }
92
93
94
95
96 public ChannelFuture connect(String inetHost, int inetPort) {
97 return connect(new InetSocketAddress(inetHost, inetPort));
98 }
99
100
101
102
103 public ChannelFuture connect(InetAddress inetHost, int inetPort) {
104 return connect(new InetSocketAddress(inetHost, inetPort));
105 }
106
107
108
109
110 public ChannelFuture connect(SocketAddress remoteAddress) {
111 if (remoteAddress == null) {
112 throw new NullPointerException("remoteAddress");
113 }
114
115 validate();
116 return doConnect(remoteAddress, localAddress());
117 }
118
119
120
121
122 public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress) {
123 if (remoteAddress == null) {
124 throw new NullPointerException("remoteAddress");
125 }
126 validate();
127 return doConnect(remoteAddress, localAddress);
128 }
129
130
131
132
133 private ChannelFuture doConnect(final SocketAddress remoteAddress, final SocketAddress localAddress) {
134 final ChannelFuture regFuture = initAndRegister();
135 final Channel channel = regFuture.channel();
136 if (regFuture.cause() != null) {
137 return regFuture;
138 }
139
140 final ChannelPromise promise = channel.newPromise();
141 if (regFuture.isDone()) {
142 doConnect0(regFuture, channel, remoteAddress, localAddress, promise);
143 } else {
144 regFuture.addListener(new ChannelFutureListener() {
145 @Override
146 public void operationComplete(ChannelFuture future) throws Exception {
147 doConnect0(regFuture, channel, remoteAddress, localAddress, promise);
148 }
149 });
150 }
151
152 return promise;
153 }
154
155 private static void doConnect0(
156 final ChannelFuture regFuture, final Channel channel,
157 final SocketAddress remoteAddress, final SocketAddress localAddress, final ChannelPromise promise) {
158
159
160
161 channel.eventLoop().execute(new Runnable() {
162 @Override
163 public void run() {
164 if (regFuture.isSuccess()) {
165 if (localAddress == null) {
166 channel.connect(remoteAddress, promise);
167 } else {
168 channel.connect(remoteAddress, localAddress, promise);
169 }
170 promise.addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
171 } else {
172 promise.setFailure(regFuture.cause());
173 }
174 }
175 });
176 }
177
178 @Override
179 @SuppressWarnings("unchecked")
180 void init(Channel channel) throws Exception {
181 ChannelPipeline p = channel.pipeline();
182 p.addLast(handler());
183
184 final Map<ChannelOption<?>, Object> options = options();
185 synchronized (options) {
186 setChannelOptions(channel, options, logger);
187 }
188
189 final Map<AttributeKey<?>, Object> attrs = attrs();
190 synchronized (attrs) {
191 for (Entry<AttributeKey<?>, Object> e: attrs.entrySet()) {
192 channel.attr((AttributeKey<Object>) e.getKey()).set(e.getValue());
193 }
194 }
195 }
196
197 @Override
198 public Bootstrap validate() {
199 super.validate();
200 if (handler() == null) {
201 throw new IllegalStateException("handler not set");
202 }
203 return this;
204 }
205
206 @Override
207 @SuppressWarnings("CloneDoesntCallSuperClone")
208 public Bootstrap clone() {
209 return new Bootstrap(this);
210 }
211
212
213
214
215
216
217 public Bootstrap clone(EventLoopGroup group) {
218 Bootstrap bs = new Bootstrap(this);
219 bs.group = group;
220 return bs;
221 }
222
223 @Override
224 public String toString() {
225 if (remoteAddress == null) {
226 return super.toString();
227 }
228
229 StringBuilder buf = new StringBuilder(super.toString());
230 buf.setLength(buf.length() - 1);
231
232 return buf.append(", remoteAddress: ")
233 .append(remoteAddress)
234 .append(')')
235 .toString();
236 }
237 }