1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.http.impl.conn;
29
30 import java.io.IOException;
31 import java.net.ConnectException;
32 import java.net.InetSocketAddress;
33 import java.net.Socket;
34 import java.net.InetAddress;
35 import java.net.UnknownHostException;
36
37 import org.apache.commons.logging.Log;
38 import org.apache.commons.logging.LogFactory;
39 import org.apache.http.annotation.ThreadSafe;
40
41 import org.apache.http.HttpHost;
42 import org.apache.http.params.HttpParams;
43 import org.apache.http.params.HttpConnectionParams;
44 import org.apache.http.protocol.HttpContext;
45
46 import org.apache.http.conn.ConnectTimeoutException;
47 import org.apache.http.conn.HttpHostConnectException;
48 import org.apache.http.conn.HttpInetSocketAddress;
49 import org.apache.http.conn.OperatedClientConnection;
50 import org.apache.http.conn.ClientConnectionOperator;
51 import org.apache.http.conn.scheme.SchemeLayeredSocketFactory;
52 import org.apache.http.conn.scheme.Scheme;
53 import org.apache.http.conn.scheme.SchemeRegistry;
54 import org.apache.http.conn.scheme.SchemeSocketFactory;
55
56 import org.apache.http.conn.DnsResolver;
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 @ThreadSafe
88 public class DefaultClientConnectionOperator implements ClientConnectionOperator {
89
90 private final Log log = LogFactory.getLog(getClass());
91
92
93 protected final SchemeRegistry schemeRegistry;
94
95
96 protected final DnsResolver dnsResolver;
97
98
99
100
101
102
103
104
105 public DefaultClientConnectionOperator(final SchemeRegistry schemes) {
106 if (schemes == null) {
107 throw new IllegalArgumentException("Scheme registry amy not be null");
108 }
109 this.schemeRegistry = schemes;
110 this.dnsResolver = new SystemDefaultDnsResolver();
111 }
112
113
114
115
116
117
118
119
120
121
122 public DefaultClientConnectionOperator(final SchemeRegistry schemes,final DnsResolver dnsResolver) {
123 if (schemes == null) {
124 throw new IllegalArgumentException(
125 "Scheme registry may not be null");
126 }
127
128 if(dnsResolver == null){
129 throw new IllegalArgumentException("DNS resolver may not be null");
130 }
131
132 this.schemeRegistry = schemes;
133 this.dnsResolver = dnsResolver;
134 }
135
136 public OperatedClientConnection createConnection() {
137 return new DefaultClientConnection();
138 }
139
140 public void openConnection(
141 final OperatedClientConnection conn,
142 final HttpHost target,
143 final InetAddress local,
144 final HttpContext context,
145 final HttpParams params) throws IOException {
146 if (conn == null) {
147 throw new IllegalArgumentException("Connection may not be null");
148 }
149 if (target == null) {
150 throw new IllegalArgumentException("Target host may not be null");
151 }
152 if (params == null) {
153 throw new IllegalArgumentException("Parameters may not be null");
154 }
155 if (conn.isOpen()) {
156 throw new IllegalStateException("Connection must not be open");
157 }
158
159 Scheme schm = schemeRegistry.getScheme(target.getSchemeName());
160 SchemeSocketFactory sf = schm.getSchemeSocketFactory();
161
162 InetAddress[] addresses = resolveHostname(target.getHostName());
163 int port = schm.resolvePort(target.getPort());
164 for (int i = 0; i < addresses.length; i++) {
165 InetAddress address = addresses[i];
166 boolean last = i == addresses.length - 1;
167
168 Socket sock = sf.createSocket(params);
169 conn.opening(sock, target);
170
171 InetSocketAddress remoteAddress = new HttpInetSocketAddress(target, address, port);
172 InetSocketAddress localAddress = null;
173 if (local != null) {
174 localAddress = new InetSocketAddress(local, 0);
175 }
176 if (this.log.isDebugEnabled()) {
177 this.log.debug("Connecting to " + remoteAddress);
178 }
179 try {
180 Socket connsock = sf.connectSocket(sock, remoteAddress, localAddress, params);
181 if (sock != connsock) {
182 sock = connsock;
183 conn.opening(sock, target);
184 }
185 prepareSocket(sock, context, params);
186 conn.openCompleted(sf.isSecure(sock), params);
187 return;
188 } catch (ConnectException ex) {
189 if (last) {
190 throw new HttpHostConnectException(target, ex);
191 }
192 } catch (ConnectTimeoutException ex) {
193 if (last) {
194 throw ex;
195 }
196 }
197 if (this.log.isDebugEnabled()) {
198 this.log.debug("Connect to " + remoteAddress + " timed out. " +
199 "Connection will be retried using another IP address");
200 }
201 }
202 }
203
204 public void updateSecureConnection(
205 final OperatedClientConnection conn,
206 final HttpHost target,
207 final HttpContext context,
208 final HttpParams params) throws IOException {
209 if (conn == null) {
210 throw new IllegalArgumentException("Connection may not be null");
211 }
212 if (target == null) {
213 throw new IllegalArgumentException("Target host may not be null");
214 }
215 if (params == null) {
216 throw new IllegalArgumentException("Parameters may not be null");
217 }
218 if (!conn.isOpen()) {
219 throw new IllegalStateException("Connection must be open");
220 }
221
222 final Scheme schm = schemeRegistry.getScheme(target.getSchemeName());
223 if (!(schm.getSchemeSocketFactory() instanceof SchemeLayeredSocketFactory)) {
224 throw new IllegalArgumentException
225 ("Target scheme (" + schm.getName() +
226 ") must have layered socket factory.");
227 }
228
229 SchemeLayeredSocketFactory lsf = (SchemeLayeredSocketFactory) schm.getSchemeSocketFactory();
230 Socket sock;
231 try {
232 sock = lsf.createLayeredSocket(
233 conn.getSocket(), target.getHostName(), target.getPort(), params);
234 } catch (ConnectException ex) {
235 throw new HttpHostConnectException(target, ex);
236 }
237 prepareSocket(sock, context, params);
238 conn.update(sock, target, lsf.isSecure(sock), params);
239 }
240
241
242
243
244
245
246
247
248
249
250 protected void prepareSocket(
251 final Socket sock,
252 final HttpContext context,
253 final HttpParams params) throws IOException {
254 sock.setTcpNoDelay(HttpConnectionParams.getTcpNoDelay(params));
255 sock.setSoTimeout(HttpConnectionParams.getSoTimeout(params));
256
257 int linger = HttpConnectionParams.getLinger(params);
258 if (linger >= 0) {
259 sock.setSoLinger(linger > 0, linger);
260 }
261 }
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277 protected InetAddress[] resolveHostname(final String host) throws UnknownHostException {
278 return dnsResolver.resolve(host);
279 }
280
281 }
282