Codebase list async-http-client / 404d067
New upstream version 2.0.11 Emmanuel Bourg 5 years ago
80 changed file(s) with 1092 addition(s) and 553 deletion(s). Raw diff Collapse all Expand all
11 <parent>
22 <groupId>org.asynchttpclient</groupId>
33 <artifactId>async-http-client-project</artifactId>
4 <version>2.0.10</version>
4 <version>2.0.11</version>
55 </parent>
66 <modelVersion>4.0.0</modelVersion>
77 <artifactId>async-http-client</artifactId>
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
7070 int getPooledConnectionIdleTimeout();
7171
7272 /**
73 * @return the period in millis to clean the pool of dead and idle connections.
74 */
75 int getConnectionPoolCleanerPeriod();
76
77 /**
7378 * Return the maximum time in millisecond an {@link AsyncHttpClient} waits until the response is completed.
7479 *
7580 * @return the maximum time in millisecond an {@link AsyncHttpClient} waits until the response is completed.
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
8484 // keep-alive
8585 private final boolean keepAlive;
8686 private final int pooledConnectionIdleTimeout;
87 private final int connectionPoolCleanerPeriod;
8788 private final int connectionTtl;
8889 private final int maxConnections;
8990 private final int maxConnectionsPerHost;
154155 // keep-alive
155156 boolean keepAlive,//
156157 int pooledConnectionIdleTimeout,//
158 int connectionPoolCleanerPeriod,//
157159 int connectionTtl,//
158160 int maxConnections,//
159161 int maxConnectionsPerHost,//
225227 // keep-alive
226228 this.keepAlive = keepAlive;
227229 this.pooledConnectionIdleTimeout = pooledConnectionIdleTimeout;
230 this.connectionPoolCleanerPeriod = connectionPoolCleanerPeriod;
228231 this.connectionTtl = connectionTtl;
229232 this.maxConnections = maxConnections;
230233 this.maxConnectionsPerHost = maxConnectionsPerHost;
373376 }
374377
375378 @Override
379 public int getConnectionPoolCleanerPeriod() {
380 return connectionPoolCleanerPeriod;
381 }
382
383 @Override
376384 public int getConnectionTtl() {
377385 return connectionTtl;
378386 }
602610 // keep-alive
603611 private boolean keepAlive = defaultKeepAlive();
604612 private int pooledConnectionIdleTimeout = defaultPooledConnectionIdleTimeout();
613 private int connectionPoolCleanerPeriod = defaultConnectionPoolCleanerPeriod();
605614 private int connectionTtl = defaultConnectionTtl();
606615 private int maxConnections = defaultMaxConnections();
607616 private int maxConnectionsPerHost = defaultMaxConnectionsPerHost();
10911100 shutdownTimeout, //
10921101 keepAlive, //
10931102 pooledConnectionIdleTimeout, //
1103 connectionPoolCleanerPeriod, //
10941104 connectionTtl, //
10951105 maxConnections, //
10961106 maxConnectionsPerHost, //
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010-2013 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010-2013 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
3636
3737 public static int defaultPooledConnectionIdleTimeout() {
3838 return AsyncHttpClientConfigHelper.getAsyncHttpClientConfig().getInt(ASYNC_CLIENT_CONFIG_ROOT + "pooledConnectionIdleTimeout");
39 }
40
41 public static int defaultConnectionPoolCleanerPeriod() {
42 return AsyncHttpClientConfigHelper.getAsyncHttpClientConfig().getInt(ASYNC_CLIENT_CONFIG_ROOT + "connectionPoolCleanerPeriod");
3943 }
4044
4145 public static int defaultReadTimeout() {
178178 for (HttpResponseBodyPart part : bodyParts)
179179 target.put(part.getBodyPartBytes());
180180
181 target.flip();
181182 return target;
182183 }
183184
5353 public DefaultChannelPool(AsyncHttpClientConfig config, Timer hashedWheelTimer) {
5454 this(config.getPooledConnectionIdleTimeout(),//
5555 config.getConnectionTtl(),//
56 hashedWheelTimer);
56 hashedWheelTimer,//
57 config.getConnectionPoolCleanerPeriod());
5758 }
5859
5960 private ChannelId channelId(Channel channel) {
6263
6364 public DefaultChannelPool(int maxIdleTime,//
6465 int connectionTtl,//
65 Timer nettyTimer) {
66 Timer nettyTimer,//
67 int cleanerPeriod) {
6668 this(maxIdleTime,//
6769 connectionTtl,//
6870 PoolLeaseStrategy.LIFO,//
69 nettyTimer);
71 nettyTimer,//
72 cleanerPeriod);
7073 }
7174
7275 public DefaultChannelPool(int maxIdleTime,//
7376 int connectionTtl,//
7477 PoolLeaseStrategy poolLeaseStrategy,//
75 Timer nettyTimer) {
78 Timer nettyTimer,//
79 int cleanerPeriod) {
7680 this.maxIdleTime = (int) maxIdleTime;
7781 this.connectionTtl = connectionTtl;
7882 connectionTtlEnabled = connectionTtl > 0;
8185 maxIdleTimeEnabled = maxIdleTime > 0;
8286 this.poolLeaseStrategy = poolLeaseStrategy;
8387
84 cleanerPeriod = Math.min(connectionTtlEnabled ? connectionTtl : Integer.MAX_VALUE, maxIdleTimeEnabled ? maxIdleTime : Long.MAX_VALUE);
88 this.cleanerPeriod = Math.min(cleanerPeriod, Math.min(connectionTtlEnabled ? connectionTtl : Integer.MAX_VALUE, maxIdleTimeEnabled ? maxIdleTime : Integer.MAX_VALUE));
8589
8690 if (connectionTtlEnabled || maxIdleTimeEnabled)
8791 scheduleNewIdleChannelDetector(new IdleChannelDetector());
152156 if (isIdleTimeoutExpired(idleChannel, now) || isRemotelyClosed(idleChannel.channel) || isTtlExpired(idleChannel.channel, now)) {
153157 LOGGER.debug("Adding Candidate expired Channel {}", idleChannel.channel);
154158 if (idleTimeoutChannels == null)
155 idleTimeoutChannels = new ArrayList<>();
159 idleTimeoutChannels = new ArrayList<>(1);
156160 idleTimeoutChannels.add(idleChannel);
157161 }
158162 }
162166
163167 private final List<IdleChannel> closeChannels(List<IdleChannel> candidates) {
164168
165 // lazy create, only if we have a non-closeable channel
169 // lazy create, only if we hit a non-closeable channel
166170 List<IdleChannel> closedChannels = null;
167171 for (int i = 0; i < candidates.size(); i++) {
168172 // We call takeOwnership here to avoid closing a channel that has just been taken out
172172 Realm realm = null;
173173 if (originalFuture != null) {
174174 realm = originalFuture.getRealm();
175 } else if (config.getRealm() != null) {
176 realm = config.getRealm();
177175 } else {
178176 realm = request.getRealm();
177 if (realm == null) {
178 realm = config.getRealm();
179 }
179180 }
180181
181182 Realm proxyRealm = null;
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
1 * Copyright 2010 Ning, Inc.
1 * Copyright (c) 2016 AsyncHttpClient Project. All rights reserved.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
4 * (the "License"); you may not use this file except in compliance with the
5 * License. You may obtain a copy of the License at:
3 * This program is licensed to you under the Apache License Version 2.0,
4 * and you may not use this file except in compliance with the Apache License Version 2.0.
5 * You may obtain a copy of the Apache License Version 2.0 at
6 * http://www.apache.org/licenses/LICENSE-2.0.
67 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 * License for the specific language governing permissions and limitations
13 * under the License.
14 *
8 * Unless required by applicable law or agreed to in writing,
9 * software distributed under the Apache License Version 2.0 is distributed on an
10 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
1512 */
1613 package org.asynchttpclient.oauth;
1714
2320 import java.util.Arrays;
2421 import java.util.List;
2522 import java.util.concurrent.ThreadLocalRandom;
23 import java.util.regex.Pattern;
2624
2725 import org.asynchttpclient.Param;
2826 import org.asynchttpclient.Request;
3432 import org.asynchttpclient.util.Utf8UrlEncoder;
3533
3634 /**
37 * Simple OAuth signature calculator that can used for constructing client signatures
38 * for accessing services that use OAuth for authorization.
39 * <br>
40 * Supports most common signature inclusion and calculation methods: HMAC-SHA1 for
41 * calculation, and Header inclusion as inclusion method. Nonce generation uses
42 * simple random numbers with base64 encoding.
35 * Simple OAuth signature calculator that can used for constructing client signatures for accessing services that use OAuth for authorization. <br>
36 * Supports most common signature inclusion and calculation methods: HMAC-SHA1 for calculation, and Header inclusion as inclusion method. Nonce generation uses simple random
37 * numbers with base64 encoding.
4338 *
4439 * @author tatu (tatu.saloranta@iki.fi)
4540 */
7166
7267 /**
7368 * @param consumerAuth Consumer key to use for signature calculation
74 * @param userAuth Request/access token to use for signature calculation
69 * @param userAuth Request/access token to use for signature calculation
7570 */
7671 public OAuthSignatureCalculator(ConsumerKey consumerAuth, RequestToken userAuth) {
7772 mac = new ThreadSafeHMAC(consumerAuth, userAuth);
8378 public void calculateAndAddSignature(Request request, RequestBuilderBase<?> requestBuilder) {
8479 String nonce = generateNonce();
8580 long timestamp = generateTimestamp();
86 String signature = calculateSignature(request.getMethod(), request.getUri(), timestamp, nonce, request.getFormParams(), request.getQueryParams());
81 String signature = calculateSignature(request, timestamp, nonce);
8782 String headerValue = constructAuthHeader(signature, nonce, timestamp);
8883 requestBuilder.setHeader(HEADER_AUTHORIZATION, headerValue);
8984 }
9085
86 private String encodedParams(long oauthTimestamp, String nonce, List<Param> formParams, List<Param> queryParams) {
87 /**
88 * List of all query and form parameters added to this request; needed for calculating request signature
89 */
90 int allParametersSize = 5 + (userAuth.getKey() != null ? 1 : 0) + (formParams != null ? formParams.size() : 0) + (queryParams != null ? queryParams.size() : 0);
91 OAuthParameterSet allParameters = new OAuthParameterSet(allParametersSize);
92
93 // start with standard OAuth parameters we need
94 allParameters.add(KEY_OAUTH_CONSUMER_KEY, Utf8UrlEncoder.encodeQueryElement(consumerAuth.getKey()));
95 allParameters.add(KEY_OAUTH_NONCE, Utf8UrlEncoder.encodeQueryElement(nonce));
96 allParameters.add(KEY_OAUTH_SIGNATURE_METHOD, OAUTH_SIGNATURE_METHOD);
97 allParameters.add(KEY_OAUTH_TIMESTAMP, String.valueOf(oauthTimestamp));
98 if (userAuth.getKey() != null) {
99 allParameters.add(KEY_OAUTH_TOKEN, Utf8UrlEncoder.encodeQueryElement(userAuth.getKey()));
100 }
101 allParameters.add(KEY_OAUTH_VERSION, OAUTH_VERSION_1_0);
102
103 if (formParams != null) {
104 for (Param param : formParams) {
105 // formParams are not already encoded
106 allParameters.add(Utf8UrlEncoder.encodeQueryElement(param.getName()), Utf8UrlEncoder.encodeQueryElement(param.getValue()));
107 }
108 }
109 if (queryParams != null) {
110 for (Param param : queryParams) {
111 // queryParams are already form-url-encoded
112 // but OAuth1 uses RFC3986_UNRESERVED_CHARS so * and + have to be encoded
113 allParameters.add(percentEncodeAlreadyFormUrlEncoded(param.getName()), percentEncodeAlreadyFormUrlEncoded(param.getValue()));
114 }
115 }
116 return allParameters.sortAndConcat();
117 }
118
91119 private String baseUrl(Uri uri) {
92 /* 07-Oct-2010, tatu: URL may contain default port number; if so, need to extract
93 * from base URL.
120 /*
121 * 07-Oct-2010, tatu: URL may contain default port number; if so, need to remove from base URL.
94122 */
95123 String scheme = uri.getScheme();
96124
97125 StringBuilder sb = StringUtils.stringBuilder();
98126 sb.append(scheme).append("://").append(uri.getHost());
99
127
100128 int port = uri.getPort();
101129 if (scheme.equals("http")) {
102130 if (port == 80)
111139
112140 if (isNonEmpty(uri.getPath()))
113141 sb.append(uri.getPath());
114
142
115143 return sb.toString();
116144 }
117145
118 private String encodedParams(long oauthTimestamp, String nonce, List<Param> formParams, List<Param> queryParams) {
119 /**
120 * List of all query and form parameters added to this request; needed
121 * for calculating request signature
122 */
123 int allParametersSize = 5
124 + (userAuth.getKey() != null ? 1 : 0)
125 + (formParams != null ? formParams.size() : 0)
126 + (queryParams != null ? queryParams.size() : 0);
127 OAuthParameterSet allParameters = new OAuthParameterSet(allParametersSize);
128
129 // start with standard OAuth parameters we need
130 allParameters.add(KEY_OAUTH_CONSUMER_KEY, Utf8UrlEncoder.encodeQueryElement(consumerAuth.getKey()));
131 allParameters.add(KEY_OAUTH_NONCE, Utf8UrlEncoder.encodeQueryElement(nonce));
132 allParameters.add(KEY_OAUTH_SIGNATURE_METHOD, OAUTH_SIGNATURE_METHOD);
133 allParameters.add(KEY_OAUTH_TIMESTAMP, String.valueOf(oauthTimestamp));
134 if (userAuth.getKey() != null) {
135 allParameters.add(KEY_OAUTH_TOKEN, Utf8UrlEncoder.encodeQueryElement(userAuth.getKey()));
136 }
137 allParameters.add(KEY_OAUTH_VERSION, OAUTH_VERSION_1_0);
138
139 if (formParams != null) {
140 for (Param param : formParams) {
141 // formParams are not already encoded
142 allParameters.add(Utf8UrlEncoder.encodeQueryElement(param.getName()), Utf8UrlEncoder.encodeQueryElement(param.getValue()));
143 }
144 }
145 if (queryParams != null) {
146 for (Param param : queryParams) {
147 // queryParams are already encoded
148 allParameters.add(param.getName(), param.getValue());
149 }
150 }
151 return allParameters.sortAndConcat();
152 }
153
154 StringBuilder signatureBaseString(String method, Uri uri, long oauthTimestamp, String nonce,
155 List<Param> formParams, List<Param> queryParams) {
156
146 private static final Pattern STAR_CHAR_PATTERN = Pattern.compile("*", Pattern.LITERAL);
147 private static final Pattern PLUS_CHAR_PATTERN = Pattern.compile("+", Pattern.LITERAL);
148 private static final Pattern ENCODED_TILDE_PATTERN = Pattern.compile("%7E", Pattern.LITERAL);
149
150 private String percentEncodeAlreadyFormUrlEncoded(String s) {
151 s = STAR_CHAR_PATTERN.matcher(s).replaceAll("%2A");
152 s = PLUS_CHAR_PATTERN.matcher(s).replaceAll("%20");
153 s = ENCODED_TILDE_PATTERN.matcher(s).replaceAll("~");
154 return s;
155 }
156
157 StringBuilder signatureBaseString(Request request, long oauthTimestamp, String nonce) {
158
157159 // beware: must generate first as we're using pooled StringBuilder
158 String baseUrl = baseUrl(uri);
159 String encodedParams = encodedParams(oauthTimestamp, nonce, formParams, queryParams);
160 String baseUrl = baseUrl(request.getUri());
161 String encodedParams = encodedParams(oauthTimestamp, nonce, request.getFormParams(), request.getQueryParams());
160162
161163 StringBuilder sb = StringUtils.stringBuilder();
162 sb.append(method); // POST / GET etc (nothing to URL encode)
164 sb.append(request.getMethod()); // POST / GET etc (nothing to URL encode)
163165 sb.append('&');
164166 Utf8UrlEncoder.encodeAndAppendQueryElement(sb, baseUrl);
165
166167
167168 // and all that needs to be URL encoded (... again!)
168169 sb.append('&');
169170 Utf8UrlEncoder.encodeAndAppendQueryElement(sb, encodedParams);
170171 return sb;
171172 }
172
173 /**
174 * Method for calculating OAuth signature using HMAC/SHA-1 method.
175 *
176 * @param method the request methode
177 * @param uri the request Uri
178 * @param oauthTimestamp the timestamp
179 * @param nonce the nonce
180 * @param formParams the formParams
181 * @param queryParams the query params
182 * @return the signature
183 */
184 public String calculateSignature(String method, Uri uri, long oauthTimestamp, String nonce,
185 List<Param> formParams, List<Param> queryParams) {
186
187 StringBuilder sb = signatureBaseString(method, uri, oauthTimestamp, nonce, formParams, queryParams);
173
174 String calculateSignature(Request request, long oauthTimestamp, String nonce) {
175
176 StringBuilder sb = signatureBaseString(request, oauthTimestamp, nonce);
188177
189178 ByteBuffer rawBase = StringUtils.charSequence2ByteBuffer(sb, UTF_8);
190179 byte[] rawSignature = mac.digest(rawBase);
224213 ThreadLocalRandom.current().nextBytes(nonceBuffer);
225214 // let's use base64 encoding over hex, slightly more compact than hex or decimals
226215 return Base64.encode(nonceBuffer);
227 // return String.valueOf(Math.abs(random.nextLong()));
216 // return String.valueOf(Math.abs(random.nextLong()));
228217 }
229218
230219 /**
231 * Container for parameters used for calculating OAuth signature.
232 * About the only confusing aspect is that of whether entries are to be sorted
233 * before encoded or vice versa: if my reading is correct, encoding is to occur
234 * first, then sorting; although this should rarely matter (since sorting is primary
235 * by key, which usually has nothing to encode)... of course, rarely means that
236 * when it would occur it'd be harder to track down.
220 * Container for parameters used for calculating OAuth signature. About the only confusing aspect is that of whether entries are to be sorted before encoded or vice versa: if
221 * my reading is correct, encoding is to occur first, then sorting; although this should rarely matter (since sorting is primary by key, which usually has nothing to encode)...
222 * of course, rarely means that when it would occur it'd be harder to track down.
237223 */
238224 final static class OAuthParameterSet {
239225 private final ArrayList<Parameter> allParameters;
268254 * Helper class for sorting query and form parameters that we need
269255 */
270256 final static class Parameter implements Comparable<Parameter> {
257
271258 private final String key, value;
272259
273260 public Parameter(String key, String value) {
299286
300287 @Override
301288 public boolean equals(Object o) {
302 if (this == o) return true;
303 if (o == null || getClass() != o.getClass()) return false;
289 if (this == o)
290 return true;
291 if (o == null || getClass() != o.getClass())
292 return false;
304293
305294 Parameter parameter = (Parameter) o;
306295
307 if (!key.equals(parameter.key)) return false;
308 if (!value.equals(parameter.value)) return false;
296 if (!key.equals(parameter.key))
297 return false;
298 if (!value.equals(parameter.value))
299 return false;
309300
310301 return true;
311302 }
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
1 * Copyright 2010 Ning, Inc.
1 * Copyright (c) 2016 AsyncHttpClient Project. All rights reserved.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
4 * (the "License"); you may not use this file except in compliance with the
5 * License. You may obtain a copy of the License at:
3 * This program is licensed to you under the Apache License Version 2.0,
4 * and you may not use this file except in compliance with the Apache License Version 2.0.
5 * You may obtain a copy of the Apache License Version 2.0 at
6 * http://www.apache.org/licenses/LICENSE-2.0.
67 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 * License for the specific language governing permissions and limitations
13 * under the License.
8 * Unless required by applicable law or agreed to in writing,
9 * software distributed under the Apache License Version 2.0 is distributed on an
10 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
1412 */
1513 package org.asynchttpclient.util;
1614
22 org.asynchttpclient.maxConnectionsPerHost=-1
33 org.asynchttpclient.connectTimeout=5000
44 org.asynchttpclient.pooledConnectionIdleTimeout=60000
5 org.asynchttpclient.connectionPoolCleanerPeriod=1000
56 org.asynchttpclient.readTimeout=60000
67 org.asynchttpclient.requestTimeout=60000
78 org.asynchttpclient.connectionTtl=-1
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010-2013 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
1 * Copyright 2010 Ning, Inc.
1 * Copyright (c) 2016 AsyncHttpClient Project. All rights reserved.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
4 * (the "License"); you may not use this file except in compliance with the
5 * License. You may obtain a copy of the License at:
3 * This program is licensed to you under the Apache License Version 2.0,
4 * and you may not use this file except in compliance with the Apache License Version 2.0.
5 * You may obtain a copy of the Apache License Version 2.0 at
6 * http://www.apache.org/licenses/LICENSE-2.0.
67 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 * License for the specific language governing permissions and limitations
13 * under the License.
8 * Unless required by applicable law or agreed to in writing,
9 * software distributed under the Apache License Version 2.0 is distributed on an
10 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
1412 */
1513 package org.asynchttpclient.oauth;
1614
2018
2119 import java.io.UnsupportedEncodingException;
2220 import java.net.URLDecoder;
23 import java.util.ArrayList;
2421 import java.util.List;
2522 import java.util.regex.Matcher;
2623 import java.util.regex.Pattern;
2724
2825 import org.asynchttpclient.Param;
2926 import org.asynchttpclient.Request;
30 import org.asynchttpclient.uri.Uri;
3127 import org.testng.annotations.Test;
3228
3329 /**
7874 OAuthSignatureCalculator calc = new OAuthSignatureCalculator(consumer, user);
7975
8076 String signatureBaseString = calc.signatureBaseString(//
81 request.getMethod(),//
82 request.getUri(),//
77 request,//
8378 137131201,//
84 "7d8f3e4a",//
85 request.getFormParams(),//
86 request.getQueryParams()).toString();
79 "7d8f3e4a").toString();
8780
8881 assertEquals(signatureBaseString, "POST&" //
8982 + "http%3A%2F%2Fexample.com%2Frequest" //
107100 OAuthSignatureCalculator calc = new OAuthSignatureCalculator(consumer, user);
108101
109102 String signatureBaseString = calc.signatureBaseString(//
110 request.getMethod(),//
111 request.getUri(),//
103 request,//
112104 137131201,//
113 "ZLc92RAkooZcIO/0cctl0Q==",//
114 request.getFormParams(),//
115 request.getQueryParams()).toString();
105 "ZLc92RAkooZcIO/0cctl0Q==").toString();
116106
117107 assertEquals(signatureBaseString, "POST&" //
118108 + "http%3A%2F%2Fexample.com%2Frequest" //
129119 + "oauth_version%3D1.0");
130120 }
131121
132 @Test(groups = "standalone")
122 @Test
133123 public void testSignatureBaseStringWithProperlyEncodedUri() {
134124
135125 Request request = post("http://example.com/request?b5=%3D%253D&a3=a&c%40=&a2=r%20b")//
141131 testSignatureBaseStringWithEncodableOAuthToken(request);
142132 }
143133
144 @Test(groups = "standalone")
134 @Test
145135 public void testSignatureBaseStringWithRawUri() {
146136
147137 // note: @ is legal so don't decode it into %40 because it won't be
159149
160150 // based on the reference test case from
161151 // http://oauth.pbwiki.com/TestCases
162 @Test(groups = "standalone")
152 @Test
163153 public void testGetCalculateSignature() {
164154 ConsumerKey consumer = new ConsumerKey(CONSUMER_KEY, CONSUMER_SECRET);
165155 RequestToken user = new RequestToken(TOKEN_KEY, TOKEN_SECRET);
166156 OAuthSignatureCalculator calc = new OAuthSignatureCalculator(consumer, user);
167 List<Param> queryParams = new ArrayList<>();
168 queryParams.add(new Param("file", "vacation.jpg"));
169 queryParams.add(new Param("size", "original"));
170 String url = "http://photos.example.net/photos";
171 String sig = calc.calculateSignature("GET", Uri.create(url), TIMESTAMP, NONCE, null, queryParams);
157
158 Request request = get("http://photos.example.net/photos")//
159 .addQueryParam("file", "vacation.jpg")//
160 .addQueryParam("size", "original")//
161 .build();
162
163 String sig = calc.calculateSignature(request, TIMESTAMP, NONCE);
172164
173165 assertEquals(sig, "tR3+Ty81lMeYAr/Fid0kMTYa/WM=");
174166 }
175167
176 @Test(groups = "standalone")
177 public void testPostCalculateSignature() {
168 @Test
169 public void testPostCalculateSignature() throws UnsupportedEncodingException {
178170 ConsumerKey consumer = new ConsumerKey(CONSUMER_KEY, CONSUMER_SECRET);
179171 RequestToken user = new RequestToken(TOKEN_KEY, TOKEN_SECRET);
180172 OAuthSignatureCalculator calc = new StaticOAuthSignatureCalculator(consumer, user, TIMESTAMP, NONCE);
181173
182 List<Param> formParams = new ArrayList<Param>();
183 formParams.add(new Param("file", "vacation.jpg"));
184 formParams.add(new Param("size", "original"));
185 String url = "http://photos.example.net/photos";
186 final Request req = post(url)//
187 .setFormParams(formParams)//
174 final Request req = post("http://photos.example.net/photos")//
175 .addFormParam("file", "vacation.jpg")//
176 .addFormParam("size", "original")//
188177 .setSignatureCalculator(calc)//
189178 .build();
190179
197186 // header: OAuth
198187 // realm="",oauth_version="1.0",oauth_consumer_key="dpf43f3p2l4k3l03",oauth_token="nnch734d00sl2jdk",oauth_timestamp="1191242096",oauth_nonce="kllo9940pd9333jh",oauth_signature_method="HMAC-SHA1",oauth_signature="wPkvxykrw%2BBTdCcGqKr%2B3I%2BPsiM%3D"
199188
200 String authHeader = req.getHeaders().get("Authorization");
189 String authHeader = req.getHeaders().get(AUTHORIZATION);
201190 Matcher m = Pattern.compile("oauth_signature=\"(.+?)\"").matcher(authHeader);
202191 assertEquals(m.find(), true);
203192 String encodedSig = m.group(1);
204 String sig = null;
205 try {
206 sig = URLDecoder.decode(encodedSig, "UTF-8");
207 } catch (UnsupportedEncodingException e) {
208 fail("bad encoding", e);
209 }
193 String sig = URLDecoder.decode(encodedSig, "UTF-8");
210194
211195 assertEquals(sig, "wPkvxykrw+BTdCcGqKr+3I+PsiM=");
212196 }
213197
214 @Test(groups = "standalone")
215 public void testGetWithRequestBuilder() {
198 @Test
199 public void testGetWithRequestBuilder() throws UnsupportedEncodingException {
216200 ConsumerKey consumer = new ConsumerKey(CONSUMER_KEY, CONSUMER_SECRET);
217201 RequestToken user = new RequestToken(TOKEN_KEY, TOKEN_SECRET);
218202 OAuthSignatureCalculator calc = new StaticOAuthSignatureCalculator(consumer, user, TIMESTAMP, NONCE);
219203
220 List<Param> queryParams = new ArrayList<Param>();
221 queryParams.add(new Param("file", "vacation.jpg"));
222 queryParams.add(new Param("size", "original"));
223 String url = "http://photos.example.net/photos";
224
225 final Request req = get(url)//
226 .setQueryParams(queryParams)//
204 final Request req = get("http://photos.example.net/photos")//
205 .addQueryParam("file", "vacation.jpg")//
206 .addQueryParam("size", "original")//
227207 .setSignatureCalculator(calc)//
228208 .build();
229209
239219 // Authorization header: OAuth
240220 // realm="",oauth_version="1.0",oauth_consumer_key="dpf43f3p2l4k3l03",oauth_token="nnch734d00sl2jdk",oauth_timestamp="1191242096",oauth_nonce="kllo9940pd9333jh",oauth_signature_method="HMAC-SHA1",oauth_signature="tR3%2BTy81lMeYAr%2FFid0kMTYa%2FWM%3D"
241221
242 String authHeader = req.getHeaders().get("Authorization");
222 String authHeader = req.getHeaders().get(AUTHORIZATION);
243223 Matcher m = Pattern.compile("oauth_signature=\"(.+?)\"").matcher(authHeader);
244224 assertEquals(m.find(), true);
245225 String encodedSig = m.group(1);
246 String sig = null;
247 try {
248 sig = URLDecoder.decode(encodedSig, "UTF-8");
249 } catch (UnsupportedEncodingException e) {
250 fail("bad encoding", e);
251 }
226 String sig = URLDecoder.decode(encodedSig, "UTF-8");
252227
253228 assertEquals(sig, "tR3+Ty81lMeYAr/Fid0kMTYa/WM=");
254229 assertEquals(req.getUrl(), "http://photos.example.net/photos?file=vacation.jpg&size=original");
255230 }
256231
257 @Test(groups = "standalone")
258 public void testGetWithRequestBuilderAndQuery() {
232 @Test
233 public void testGetWithRequestBuilderAndQuery() throws UnsupportedEncodingException {
259234 ConsumerKey consumer = new ConsumerKey(CONSUMER_KEY, CONSUMER_SECRET);
260235 RequestToken user = new RequestToken(TOKEN_KEY, TOKEN_SECRET);
261236 OAuthSignatureCalculator calc = new StaticOAuthSignatureCalculator(consumer, user, TIMESTAMP, NONCE);
262237
263 String url = "http://photos.example.net/photos?file=vacation.jpg&size=original";
264
265 final Request req = get(url)//
238 final Request req = get("http://photos.example.net/photos?file=vacation.jpg&size=original")//
266239 .setSignatureCalculator(calc)//
267240 .build();
268241
280253
281254 String authHeader = req.getHeaders().get(AUTHORIZATION);
282255 Matcher m = Pattern.compile("oauth_signature=\"(.+?)\"").matcher(authHeader);
283 assertEquals(m.find(), true);
256 assertTrue(m.find());
284257 String encodedSig = m.group(1);
285 String sig = null;
286 try {
287 sig = URLDecoder.decode(encodedSig, "UTF-8");
288 } catch (UnsupportedEncodingException e) {
289 fail("bad encoding", e);
290 }
258 String sig = URLDecoder.decode(encodedSig, "UTF-8");
291259
292260 assertEquals(sig, "tR3+Ty81lMeYAr/Fid0kMTYa/WM=");
293261 assertEquals(req.getUrl(), "http://photos.example.net/photos?file=vacation.jpg&size=original");
296264 "OAuth oauth_consumer_key=\"dpf43f3p2l4k3l03\", oauth_token=\"nnch734d00sl2jdk\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"tR3%2BTy81lMeYAr%2FFid0kMTYa%2FWM%3D\", oauth_timestamp=\"1191242096\", oauth_nonce=\"kllo9940pd9333jh\", oauth_version=\"1.0\"");
297265 }
298266
299 @Test(groups = "standalone")
267 @Test
300268 public void testWithNullRequestToken() {
301 String url = "http://photos.example.net/photos?file=vacation.jpg&size=original";
302269 ConsumerKey consumer = new ConsumerKey("9djdj82h48djs9d2", CONSUMER_SECRET);
303270 RequestToken user = new RequestToken(null, null);
304271 OAuthSignatureCalculator calc = new OAuthSignatureCalculator(consumer, user);
305272
306 final Request request = get(url)//
307 .setSignatureCalculator(calc)//
308 .build();
273 final Request request = get("http://photos.example.net/photos?file=vacation.jpg&size=original").build();
309274
310275 String signatureBaseString = calc.signatureBaseString(//
311 request.getMethod(),//
312 request.getUri(),//
276 request,//
313277 137131201,//
314 "ZLc92RAkooZcIO/0cctl0Q==",//
315 request.getFormParams(),//
316 request.getQueryParams()).toString();
278 "ZLc92RAkooZcIO/0cctl0Q==").toString();
317279
318280 assertEquals(signatureBaseString, "GET&" + //
319281 "http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation.jpg%26" + //
323285 "oauth_timestamp%3D137131201%26" + //
324286 "oauth_version%3D1.0%26size%3Doriginal");
325287 }
288
289 @Test
290 public void testWithStarQueryParameterValue() {
291 ConsumerKey consumer = new ConsumerKey("key", "secret");
292 RequestToken user = new RequestToken(null, null);
293 OAuthSignatureCalculator calc = new OAuthSignatureCalculator(consumer, user);
294
295 final Request request = get("http://term.ie/oauth/example/request_token.php?testvalue=*").build();
296
297 String signatureBaseString = calc.signatureBaseString(//
298 request,//
299 1469019732,//
300 "6ad17f97334700f3ec2df0631d5b7511").toString();
301
302 assertEquals(signatureBaseString, "GET&" + //
303 "http%3A%2F%2Fterm.ie%2Foauth%2Fexample%2Frequest_token.php&"//
304 + "oauth_consumer_key%3Dkey%26"//
305 + "oauth_nonce%3D6ad17f97334700f3ec2df0631d5b7511%26"//
306 + "oauth_signature_method%3DHMAC-SHA1%26"//
307 + "oauth_timestamp%3D1469019732%26"//
308 + "oauth_version%3D1.0%26"//
309 + "testvalue%3D%252A");
310 }
326311 }
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
00 /*
11 * Copyright 2010 Ning, Inc.
22 *
3 * Ning licenses this file to you under the Apache License, version 2.0
3 * This program is licensed to you under the Apache License, version 2.0
44 * (the "License"); you may not use this file except in compliance with the
55 * License. You may obtain a copy of the License at:
66 *
11 <parent>
22 <groupId>org.asynchttpclient</groupId>
33 <artifactId>async-http-client-extras-parent</artifactId>
4 <version>2.0.10</version>
4 <version>2.0.11</version>
55 </parent>
66 <modelVersion>4.0.0</modelVersion>
77 <artifactId>async-http-client-extras-guava</artifactId>
1717 <parent>
1818 <artifactId>async-http-client-extras-parent</artifactId>
1919 <groupId>org.asynchttpclient</groupId>
20 <version>2.0.10</version>
20 <version>2.0.11</version>
2121 </parent>
2222 <artifactId>async-http-client-extras-jdeferred</artifactId>
2323 <name>Asynchronous Http Client JDeferred Extras</name>
11 <parent>
22 <groupId>org.asynchttpclient</groupId>
33 <artifactId>async-http-client-project</artifactId>
4 <version>2.0.10</version>
4 <version>2.0.11</version>
55 </parent>
66 <modelVersion>4.0.0</modelVersion>
77 <artifactId>async-http-client-extras-parent</artifactId>
11 <parent>
22 <groupId>org.asynchttpclient</groupId>
33 <artifactId>async-http-client-extras-parent</artifactId>
4 <version>2.0.10</version>
4 <version>2.0.11</version>
55 </parent>
66 <modelVersion>4.0.0</modelVersion>
77 <artifactId>async-http-client-extras-registry</artifactId>
22 <parent>
33 <artifactId>async-http-client-extras-parent</artifactId>
44 <groupId>org.asynchttpclient</groupId>
5 <version>2.0.10</version>
5 <version>2.0.11</version>
66 </parent>
77 <artifactId>async-http-client-extras-rxjava</artifactId>
88 <name>Asynchronous Http Client RxJava Extras</name>
22 <parent>
33 <artifactId>async-http-client-extras-parent</artifactId>
44 <groupId>org.asynchttpclient</groupId>
5 <version>2.0.10</version>
5 <version>2.0.11</version>
66 </parent>
77 <artifactId>async-http-client-extras-simple</artifactId>
88 <name>Asynchronous Http Simple Client</name>
1919 <parent>
2020 <groupId>org.asynchttpclient</groupId>
2121 <artifactId>netty-bp</artifactId>
22 <version>2.0.10</version>
22 <version>2.0.11</version>
2323 </parent>
2424
2525 <artifactId>netty-codec-dns</artifactId>
11 <parent>
22 <groupId>org.asynchttpclient</groupId>
33 <artifactId>async-http-client-project</artifactId>
4 <version>2.0.10</version>
4 <version>2.0.11</version>
55 </parent>
66 <modelVersion>4.0.0</modelVersion>
77 <artifactId>netty-bp</artifactId>
1919 <parent>
2020 <groupId>org.asynchttpclient</groupId>
2121 <artifactId>netty-bp</artifactId>
22 <version>2.0.10</version>
22 <version>2.0.11</version>
2323 </parent>
2424
2525 <artifactId>netty-resolver</artifactId>
88 <parent>
99 <groupId>org.asynchttpclient</groupId>
1010 <artifactId>netty-bp</artifactId>
11 <version>2.0.10</version>
11 <version>2.0.11</version>
1212 </parent>
1313
1414 <artifactId>netty-resolver-dns</artifactId>
4141 import io.netty.util.concurrent.FastThreadLocal;
4242 import io.netty.util.concurrent.Future;
4343 import io.netty.util.concurrent.Promise;
44 import io.netty.util.internal.EmptyArrays;
4445 import io.netty.util.internal.PlatformDependent;
46 import io.netty.util.internal.StringUtil2;
4547 import io.netty.util.internal.logging.InternalLogger;
4648 import io.netty.util.internal.logging.InternalLoggerFactory;
4749
50 import java.lang.reflect.Method;
4851 import java.net.IDN;
4952 import java.net.Inet4Address;
5053 import java.net.InetAddress;
6669 private static final InetAddress LOCALHOST_ADDRESS;
6770
6871 static final InternetProtocolFamily[] DEFAULT_RESOLVE_ADDRESS_TYPES = new InternetProtocolFamily[2];
72 static final String[] DEFAULT_SEACH_DOMAINS;
6973
7074 static {
7175 // Note that we did not use SystemPropertyUtil.getBoolean() here to emulate the behavior of JDK.
8286 }
8387 }
8488
89 static {
90 String[] searchDomains;
91 try {
92 Class<?> configClass = Class.forName("sun.net.dns.ResolverConfiguration");
93 Method open = configClass.getMethod("open");
94 Method nameservers = configClass.getMethod("searchlist");
95 Object instance = open.invoke(null);
96
97 @SuppressWarnings("unchecked")
98 List<String> list = (List<String>) nameservers.invoke(instance);
99 searchDomains = list.toArray(new String[list.size()]);
100 } catch (Exception ignore) {
101 // Failed to get the system name search domain list.
102 searchDomains = EmptyArrays.EMPTY_STRINGS;
103 }
104 DEFAULT_SEACH_DOMAINS = searchDomains;
105 }
106
85107 private static final DatagramDnsResponseDecoder DECODER = new DatagramDnsResponseDecoder();
86108 private static final DatagramDnsQueryEncoder ENCODER = new DatagramDnsQueryEncoder();
87109
115137 private final int maxPayloadSize;
116138 private final boolean optResourceEnabled;
117139 private final HostsFileEntriesResolver hostsFileEntriesResolver;
140 private final String[] searchDomains;
141 private final int ndots;
118142
119143 /**
120144 * Creates a new DNS-based name resolver that communicates with the specified list of DNS servers.
133157 * @param maxPayloadSize the capacity of the datagram packet buffer
134158 * @param optResourceEnabled if automatic inclusion of a optional records is enabled
135159 * @param hostsFileEntriesResolver the {@link HostsFileEntriesResolver} used to check for local aliases
160 * @param searchDomains the list of search domain
161 * @param ndots the ndots value
136162 */
137163 public DnsNameResolver(
138164 EventLoop eventLoop,
146172 boolean traceEnabled,
147173 int maxPayloadSize,
148174 boolean optResourceEnabled,
149 HostsFileEntriesResolver hostsFileEntriesResolver) {
175 HostsFileEntriesResolver hostsFileEntriesResolver,
176 String[] searchDomains,
177 int ndots) {
150178
151179 super(eventLoop);
152180 checkNotNull(channelFactory, "channelFactory");
160188 this.optResourceEnabled = optResourceEnabled;
161189 this.hostsFileEntriesResolver = checkNotNull(hostsFileEntriesResolver, "hostsFileEntriesResolver");
162190 this.resolveCache = resolveCache;
191 this.searchDomains = checkNotNull(searchDomains, "searchDomains").clone();
192 this.ndots = checkPositive(ndots, "ndots");
163193
164194 Bootstrap b = new Bootstrap();
165195 b.group(executor());
211241
212242 InternetProtocolFamily[] resolveAddressTypesUnsafe() {
213243 return resolvedAddressTypes;
244 }
245
246 final String[] searchDomains() {
247 return searchDomains;
248 }
249
250 final int ndots() {
251 return ndots;
214252 }
215253
216254 /**
374412 private void doResolveUncached(String hostname,
375413 Promise<InetAddress> promise,
376414 DnsCache resolveCache) {
377 final DnsNameResolverContext<InetAddress> ctx =
378 new DnsNameResolverContext<InetAddress>(this, hostname, promise, resolveCache) {
379 @Override
380 protected boolean finishResolve(
381 InternetProtocolFamily f, List<DnsCacheEntry> resolvedEntries) {
382
383 final int numEntries = resolvedEntries.size();
384 for (int i = 0; i < numEntries; i++) {
385 final InetAddress a = resolvedEntries.get(i).address();
386 if (addressMatchFamily(a, f)) {
387 setSuccess(promise(), a);
388 return true;
389 }
390 }
391 return false;
392 }
393 };
394
395 ctx.resolve();
415 SingleResolverContext ctx = new SingleResolverContext(this, hostname, resolveCache);
416 ctx.resolve(promise);
417 }
418
419 final class SingleResolverContext extends DnsNameResolverContext<InetAddress> {
420
421 SingleResolverContext(DnsNameResolver parent, String hostname, DnsCache resolveCache) {
422 super(parent, hostname, resolveCache);
423 }
424
425 @Override
426 DnsNameResolverContext<InetAddress> newResolverContext(DnsNameResolver parent,
427 String hostname, DnsCache resolveCache) {
428 return new SingleResolverContext(parent, hostname, resolveCache);
429 }
430
431 @Override
432 boolean finishResolve(
433 InternetProtocolFamily f, List<DnsCacheEntry> resolvedEntries,
434 Promise<InetAddress> promise) {
435
436 final int numEntries = resolvedEntries.size();
437 for (int i = 0; i < numEntries; i++) {
438 final InetAddress a = resolvedEntries.get(i).address();
439 if (addressMatchFamily(a, f)) {
440 setSuccess(promise, a);
441 return true;
442 }
443 }
444 return false;
445 }
396446 }
397447
398448 @Override
470520 return true;
471521 }
472522
473 private void doResolveAllUncached(final String hostname,
474 final Promise<List<InetAddress>> promise,
523 final class ListResolverContext extends DnsNameResolverContext<List<InetAddress>> {
524 ListResolverContext(DnsNameResolver parent, String hostname, DnsCache resolveCache) {
525 super(parent, hostname, resolveCache);
526 }
527
528 @Override
529 DnsNameResolverContext<List<InetAddress>> newResolverContext(DnsNameResolver parent, String hostname,
530 DnsCache resolveCache) {
531 return new ListResolverContext(parent, hostname, resolveCache);
532 }
533
534 @Override
535 boolean finishResolve(
536 InternetProtocolFamily f, List<DnsCacheEntry> resolvedEntries,
537 Promise<List<InetAddress>> promise) {
538
539 List<InetAddress> result = null;
540 final int numEntries = resolvedEntries.size();
541 for (int i = 0; i < numEntries; i++) {
542 final InetAddress a = resolvedEntries.get(i).address();
543 if (addressMatchFamily(a, f)) {
544 if (result == null) {
545 result = new ArrayList<InetAddress>(numEntries);
546 }
547 result.add(a);
548 }
549 }
550
551 if (result != null) {
552 promise.trySuccess(result);
553 return true;
554 }
555 return false;
556 }
557 }
558
559 private void doResolveAllUncached(String hostname,
560 Promise<List<InetAddress>> promise,
475561 DnsCache resolveCache) {
476 final DnsNameResolverContext<List<InetAddress>> ctx =
477 new DnsNameResolverContext<List<InetAddress>>(this, hostname, promise, resolveCache) {
478 @Override
479 protected boolean finishResolve(
480 InternetProtocolFamily f, List<DnsCacheEntry> resolvedEntries) {
481
482 List<InetAddress> result = null;
483 final int numEntries = resolvedEntries.size();
484 for (int i = 0; i < numEntries; i++) {
485 final InetAddress a = resolvedEntries.get(i).address();
486 if (addressMatchFamily(a, f)) {
487 if (result == null) {
488 result = new ArrayList<InetAddress>(numEntries);
489 }
490 result.add(a);
491 }
492 }
493
494 if (result != null) {
495 promise().trySuccess(result);
496 return true;
497 }
498 return false;
499 }
500 };
501
502 ctx.resolve();
562 DnsNameResolverContext<List<InetAddress>> ctx = new ListResolverContext(this, hostname, resolveCache);
563 ctx.resolve(promise);
503564 }
504565
505566 private static String hostname(String inetHost) {
506 return IDN.toASCII(inetHost);
567 String hostname = IDN.toASCII(inetHost);
568 // Check for http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6894622
569 if (StringUtil2.endsWith(inetHost, '.') && !StringUtil2.endsWith(hostname, '.')) {
570 hostname += ".";
571 }
572 return hostname;
507573 }
508574
509575 /**
4848 private int maxPayloadSize = 4096;
4949 private boolean optResourceEnabled = true;
5050 private HostsFileEntriesResolver hostsFileEntriesResolver = HostsFileEntriesResolver.DEFAULT;
51 private String[] searchDomains = DnsNameResolver.DEFAULT_SEACH_DOMAINS;
52 private int ndots = 1;
5153
5254 /**
5355 * Creates a new builder.
282284 */
283285 public DnsNameResolverBuilder hostsFileEntriesResolver(HostsFileEntriesResolver hostsFileEntriesResolver) {
284286 this.hostsFileEntriesResolver = hostsFileEntriesResolver;
287 return this;
288 }
289
290 /**
291 * Set the list of search domains of the resolver.
292 *
293 * @param searchDomains the search domains
294 * @return {@code this}
295 */
296 public DnsNameResolverBuilder searchDomains(Iterable<String> searchDomains) {
297 checkNotNull(searchDomains, "searchDomains");
298
299 final List<String> list =
300 InternalThreadLocalMap.get().arrayList(4);
301
302 for (String f : searchDomains) {
303 if (f == null) {
304 break;
305 }
306
307 // Avoid duplicate entries.
308 if (list.contains(f)) {
309 continue;
310 }
311
312 list.add(f);
313 }
314
315 this.searchDomains = list.toArray(new String[list.size()]);
316 return this;
317 }
318
319 /**
320 * Set the number of dots which must appear in a name before an initial absolute query is made.
321 *
322 * @param ndots the ndots value
323 * @return {@code this}
324 */
325 public DnsNameResolverBuilder ndots(int ndots) {
326 this.ndots = ndots;
285327 return this;
286328 }
287329
311353 traceEnabled,
312354 maxPayloadSize,
313355 optResourceEnabled,
314 hostsFileEntriesResolver);
356 hostsFileEntriesResolver,
357 searchDomains,
358 ndots);
315359 }
316360 }
3434 import io.netty.util.concurrent.FutureListener;
3535 import io.netty.util.concurrent.Promise;
3636 import io.netty.util.internal.StringUtil;
37 import io.netty.util.internal.StringUtil2;
3738
3839 import java.net.Inet4Address;
3940 import java.net.Inet6Address;
6768
6869 private final DnsNameResolver parent;
6970 private final DnsServerAddressStream nameServerAddrs;
70 private final Promise<T> promise;
7171 private final String hostname;
7272 private final DnsCache resolveCache;
7373 private final boolean traceEnabled;
8585
8686 protected DnsNameResolverContext(DnsNameResolver parent,
8787 String hostname,
88 Promise<T> promise,
8988 DnsCache resolveCache) {
9089 this.parent = parent;
91 this.promise = promise;
9290 this.hostname = hostname;
9391 this.resolveCache = resolveCache;
9492
9997 allowedQueries = maxAllowedQueries;
10098 }
10199
102 protected Promise<T> promise() {
103 return promise;
104 }
105
106 void resolve() {
100 void resolve(Promise<T> promise) {
101 boolean directSearch = parent.searchDomains().length == 0 || StringUtil2.endsWith(hostname, '.');
102 if (directSearch) {
103 internalResolve(promise);
104 } else {
105 final Promise<T> original = promise;
106 promise = parent.executor().newPromise();
107 promise.addListener(new FutureListener<T>() {
108 int count;
109 @Override
110 public void operationComplete(Future<T> future) throws Exception {
111 if (future.isSuccess()) {
112 original.trySuccess(future.getNow());
113 } else if (count < parent.searchDomains().length) {
114 String searchDomain = parent.searchDomains()[count++];
115 Promise<T> nextPromise = parent.executor().newPromise();
116 String nextHostname = DnsNameResolverContext.this.hostname + "." + searchDomain;
117 DnsNameResolverContext<T> nextContext = newResolverContext(parent,
118 nextHostname, resolveCache);
119 nextContext.internalResolve(nextPromise);
120 nextPromise.addListener(this);
121 } else {
122 original.tryFailure(future.cause());
123 }
124 }
125 });
126 int dots = 0;
127 for (int idx = hostname.length() - 1; idx >= 0; idx--) {
128 if (hostname.charAt(idx) == '.' && ++dots >= parent.ndots()) {
129 internalResolve(promise);
130 return;
131 }
132 }
133 promise.tryFailure(new UnknownHostException(hostname));
134 }
135 }
136
137 private void internalResolve(Promise<T> promise) {
107138 InetSocketAddress nameServerAddrToTry = nameServerAddrs.next();
108139 for (InternetProtocolFamily f: resolveAddressTypes) {
109140 final DnsRecordType type;
118149 throw new Error();
119150 }
120151
121 query(nameServerAddrToTry, new DefaultDnsQuestion(hostname, type));
122 }
123 }
124
125 private void query(InetSocketAddress nameServerAddr, final DnsQuestion question) {
152 query(nameServerAddrToTry, new DefaultDnsQuestion(hostname, type), promise);
153 }
154 }
155
156 private void query(InetSocketAddress nameServerAddr, final DnsQuestion question, final Promise<T> promise) {
126157 if (allowedQueries == 0 || promise.isCancelled()) {
127 tryToFinishResolve();
158 tryToFinishResolve(promise);
128159 return;
129160 }
130161
144175
145176 try {
146177 if (future.isSuccess()) {
147 onResponse(question, future.getNow());
178 onResponse(question, future.getNow(), promise);
148179 } else {
149180 // Server did not respond or I/O error occurred; try again.
150181 if (traceEnabled) {
151182 addTrace(future.cause());
152183 }
153 query(nameServerAddrs.next(), question);
184 query(nameServerAddrs.next(), question, promise);
154185 }
155186 } finally {
156 tryToFinishResolve();
187 tryToFinishResolve(promise);
157188 }
158189 }
159190 });
160191 }
161192
162 void onResponse(final DnsQuestion question, AddressedEnvelope<DnsResponse, InetSocketAddress> envelope) {
193 void onResponse(final DnsQuestion question, AddressedEnvelope<DnsResponse, InetSocketAddress> envelope,
194 Promise<T> promise) {
163195 try {
164196 final DnsResponse res = envelope.content();
165197 final DnsResponseCode code = res.code();
166198 if (code == DnsResponseCode.NOERROR) {
167199 final DnsRecordType type = question.type();
168200 if (type == DnsRecordType.A || type == DnsRecordType.AAAA) {
169 onResponseAorAAAA(type, question, envelope);
201 onResponseAorAAAA(type, question, envelope, promise);
170202 } else if (type == DnsRecordType.CNAME) {
171 onResponseCNAME(question, envelope);
203 onResponseCNAME(question, envelope, promise);
172204 }
173205 return;
174206 }
181213
182214 // Retry with the next server if the server did not tell us that the domain does not exist.
183215 if (code != DnsResponseCode.NXDOMAIN) {
184 query(nameServerAddrs.next(), question);
216 query(nameServerAddrs.next(), question, promise);
185217 }
186218 } finally {
187219 ReferenceCountUtil.safeRelease(envelope);
189221 }
190222
191223 private void onResponseAorAAAA(
192 DnsRecordType qType, DnsQuestion question, AddressedEnvelope<DnsResponse, InetSocketAddress> envelope) {
224 DnsRecordType qType, DnsQuestion question, AddressedEnvelope<DnsResponse, InetSocketAddress> envelope,
225 Promise<T> promise) {
193226
194227 // We often get a bunch of CNAMES as well when we asked for A/AAAA.
195228 final DnsResponse response = envelope.content();
266299
267300 // We aked for A/AAAA but we got only CNAME.
268301 if (!cnames.isEmpty()) {
269 onResponseCNAME(question, envelope, cnames, false);
270 }
271 }
272
273 private void onResponseCNAME(DnsQuestion question, AddressedEnvelope<DnsResponse, InetSocketAddress> envelope) {
274 onResponseCNAME(question, envelope, buildAliasMap(envelope.content()), true);
302 onResponseCNAME(question, envelope, cnames, false, promise);
303 }
304 }
305
306 private void onResponseCNAME(DnsQuestion question, AddressedEnvelope<DnsResponse, InetSocketAddress> envelope,
307 Promise<T> promise) {
308 onResponseCNAME(question, envelope, buildAliasMap(envelope.content()), true, promise);
275309 }
276310
277311 private void onResponseCNAME(
278312 DnsQuestion question, AddressedEnvelope<DnsResponse, InetSocketAddress> response,
279 Map<String, String> cnames, boolean trace) {
313 Map<String, String> cnames, boolean trace, Promise<T> promise) {
280314
281315 // Resolve the host name in the question into the real host name.
282316 final String name = question.name().toLowerCase(Locale.US);
295329 }
296330
297331 if (found) {
298 followCname(response.sender(), name, resolved);
332 followCname(response.sender(), name, resolved, promise);
299333 } else if (trace && traceEnabled) {
300334 addTrace(response.sender(), "no matching CNAME record found");
301335 }
331365 return cnames != null? cnames : Collections.<String, String>emptyMap();
332366 }
333367
334 void tryToFinishResolve() {
368 void tryToFinishResolve(Promise<T> promise) {
335369 if (!queriesInProgress.isEmpty()) {
336370 // There are still some queries we did not receive responses for.
337371 if (gotPreferredAddress()) {
338372 // But it's OK to finish the resolution process if we got a resolved address of the preferred type.
339 finishResolve();
373 finishResolve(promise);
340374 }
341375
342376 // We did not get any resolved address of the preferred type, so we can't finish the resolution process.
349383 if (!triedCNAME) {
350384 // As the last resort, try to query CNAME, just in case the name server has it.
351385 triedCNAME = true;
352 query(nameServerAddrs.next(), new DefaultDnsQuestion(hostname, DnsRecordType.CNAME));
386 query(nameServerAddrs.next(), new DefaultDnsQuestion(hostname, DnsRecordType.CNAME), promise);
353387 return;
354388 }
355389 }
356390
357391 // We have at least one resolved address or tried CNAME as the last resort..
358 finishResolve();
392 finishResolve(promise);
359393 }
360394
361395 private boolean gotPreferredAddress() {
384418 return false;
385419 }
386420
387 private void finishResolve() {
421 private void finishResolve(Promise<T> promise) {
388422 if (!queriesInProgress.isEmpty()) {
389423 // If there are queries in progress, we should cancel it because we already finished the resolution.
390424 for (Iterator<Future<AddressedEnvelope<DnsResponse, InetSocketAddress>>> i = queriesInProgress.iterator();
401435 if (resolvedEntries != null) {
402436 // Found at least one resolved address.
403437 for (InternetProtocolFamily f: resolveAddressTypes) {
404 if (finishResolve(f, resolvedEntries)) {
438 if (finishResolve(f, resolvedEntries, promise)) {
405439 return;
406440 }
407441 }
434468 promise.tryFailure(cause);
435469 }
436470
437 protected abstract boolean finishResolve(
438 InternetProtocolFamily f, List<DnsCacheEntry> resolvedEntries);
471 abstract boolean finishResolve(InternetProtocolFamily f, List<DnsCacheEntry> resolvedEntries,
472 Promise<T> promise);
473
474 abstract DnsNameResolverContext<T> newResolverContext(DnsNameResolver parent, String hostname,
475 DnsCache resolveCache);
439476
440477 static String decodeDomainName(ByteBuf in) {
441478 in.markReaderIndex();
449486 }
450487 }
451488
452 private void followCname(InetSocketAddress nameServerAddr, String name, String cname) {
489 private void followCname(InetSocketAddress nameServerAddr, String name, String cname, Promise<T> promise) {
453490
454491 if (traceEnabled) {
455492 if (trace == null) {
466503 }
467504
468505 final InetSocketAddress nextAddr = nameServerAddrs.next();
469 query(nextAddr, new DefaultDnsQuestion(cname, DnsRecordType.A));
470 query(nextAddr, new DefaultDnsQuestion(cname, DnsRecordType.AAAA));
506 query(nextAddr, new DefaultDnsQuestion(cname, DnsRecordType.A), promise);
507 query(nextAddr, new DefaultDnsQuestion(cname, DnsRecordType.AAAA), promise);
471508 }
472509
473510 private void addTrace(InetSocketAddress nameServerAddr, String msg) {
0 /*
1 * Copyright 2012 The Netty Project
2 *
3 * The Netty Project licenses this file to you under the Apache License,
4 * version 2.0 (the "License"); you may not use this file except in compliance
5 * with the License. You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 * License for the specific language governing permissions and limitations
13 * under the License.
14 */
15 package io.netty.util.internal;
16
17 /**
18 * String utility class.
19 */
20 public final class StringUtil2 {
21
22 /**
23 * Determine if the string {@code s} ends with the char {@code c}.
24 *
25 * @param s the string to test
26 * @param c the tested char
27 * @return true if {@code s} ends with the char {@code c}
28 */
29 public static boolean endsWith(CharSequence s, char c) {
30 int len = s.length();
31 return len > 0 && s.charAt(len - 1) == c;
32 }
33
34 private StringUtil2() {
35 // Unused.
36 }
37 }
2727 import io.netty.handler.codec.dns.DnsResponse;
2828 import io.netty.handler.codec.dns.DnsResponseCode;
2929 import io.netty.handler.codec.dns.DnsSection;
30 import io.netty.util.NetUtil;
3130 import io.netty.util.concurrent.Future;
3231 import io.netty.util.internal.StringUtil;
33 import io.netty.util.internal.ThreadLocalRandom;
3432 import io.netty.util.internal.logging.InternalLogger;
3533 import io.netty.util.internal.logging.InternalLoggerFactory;
36 import org.apache.directory.server.dns.DnsServer;
37 import org.apache.directory.server.dns.io.encoder.DnsMessageEncoder;
38 import org.apache.directory.server.dns.io.encoder.ResourceRecordEncoder;
39 import org.apache.directory.server.dns.messages.DnsMessage;
40 import org.apache.directory.server.dns.messages.QuestionRecord;
41 import org.apache.directory.server.dns.messages.RecordClass;
42 import org.apache.directory.server.dns.messages.RecordType;
43 import org.apache.directory.server.dns.messages.ResourceRecord;
44 import org.apache.directory.server.dns.messages.ResourceRecordModifier;
45 import org.apache.directory.server.dns.protocol.DnsProtocolHandler;
46 import org.apache.directory.server.dns.protocol.DnsUdpDecoder;
47 import org.apache.directory.server.dns.protocol.DnsUdpEncoder;
48 import org.apache.directory.server.dns.store.DnsAttribute;
49 import org.apache.directory.server.dns.store.RecordStore;
50 import org.apache.directory.server.protocol.shared.transport.UdpTransport;
51 import org.apache.mina.core.buffer.IoBuffer;
52 import org.apache.mina.core.session.IoSession;
53 import org.apache.mina.filter.codec.ProtocolCodecFactory;
54 import org.apache.mina.filter.codec.ProtocolCodecFilter;
55 import org.apache.mina.filter.codec.ProtocolDecoder;
56 import org.apache.mina.filter.codec.ProtocolEncoder;
57 import org.apache.mina.filter.codec.ProtocolEncoderOutput;
58 import org.apache.mina.transport.socket.DatagramAcceptor;
59 import org.apache.mina.transport.socket.DatagramSessionConfig;
6034 import org.junit.AfterClass;
6135 import org.junit.BeforeClass;
6236 import org.junit.Test;
6337
64 import java.io.IOException;
6538 import java.net.InetAddress;
6639 import java.net.InetSocketAddress;
6740 import java.net.UnknownHostException;
261234 StringUtil.EMPTY_STRING);
262235 }
263236
264 private static final TestDnsServer dnsServer = new TestDnsServer();
237 private static final TestDnsServer dnsServer = new TestDnsServer(DOMAINS);
265238 private static final EventLoopGroup group = new NioEventLoopGroup(1);
266239
267240 private static DnsNameResolverBuilder newResolver() {
274247
275248 private static DnsNameResolverBuilder newResolver(InternetProtocolFamily... resolvedAddressTypes) {
276249 return newResolver()
250 .resolvedAddressTypes(resolvedAddressTypes);
251 }
252
253 private static DnsNameResolverBuilder newNonCachedResolver(InternetProtocolFamily... resolvedAddressTypes) {
254 return newResolver()
255 .resolveCache(NoopDnsCache.INSTANCE)
277256 .resolvedAddressTypes(resolvedAddressTypes);
278257 }
279258
343322 DnsNameResolver resolver = newResolver(InternetProtocolFamily.IPv6).build();
344323 try {
345324 testResolve0(resolver, EXCLUSIONS_RESOLVE_AAAA);
325 } finally {
326 resolver.close();
327 }
328 }
329
330 @Test
331 public void testNonCachedResolve() throws Exception {
332 DnsNameResolver resolver = newNonCachedResolver(InternetProtocolFamily.IPv4).build();
333 try {
334 testResolve0(resolver, EXCLUSIONS_RESOLVE_A);
346335 } finally {
347336 resolver.close();
348337 }
514503 futures.put(hostname, resolver.query(new DefaultDnsQuestion(hostname, DnsRecordType.MX)));
515504 }
516505
517 private static final class TestDnsServer extends DnsServer {
518 private static final Map<String, byte[]> BYTES = new HashMap<String, byte[]>();
519 private static final String[] IPV6_ADDRESSES;
520 static {
521 BYTES.put("::1", new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1});
522 BYTES.put("0:0:0:0:0:0:1:1", new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1});
523 BYTES.put("0:0:0:0:0:1:1:1", new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1});
524 BYTES.put("0:0:0:0:1:1:1:1", new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1});
525 BYTES.put("0:0:0:1:1:1:1:1", new byte[] {0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1});
526 BYTES.put("0:0:1:1:1:1:1:1", new byte[] {0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1});
527 BYTES.put("0:1:1:1:1:1:1:1", new byte[] {0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1});
528 BYTES.put("1:1:1:1:1:1:1:1", new byte[] {0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1});
529
530 IPV6_ADDRESSES = BYTES.keySet().toArray(new String[BYTES.size()]);
531 }
532
533 @Override
534 public void start() throws IOException {
535 InetSocketAddress address = new InetSocketAddress(NetUtil.LOCALHOST4, 0);
536 UdpTransport transport = new UdpTransport(address.getHostName(), address.getPort());
537 setTransports(transport);
538
539 DatagramAcceptor acceptor = transport.getAcceptor();
540
541 acceptor.setHandler(new DnsProtocolHandler(this, new TestRecordStore()) {
542 @Override
543 public void sessionCreated(IoSession session) throws Exception {
544 // USe our own codec to support AAAA testing
545 session.getFilterChain()
546 .addFirst("codec", new ProtocolCodecFilter(new TestDnsProtocolUdpCodecFactory()));
547 }
548 });
549
550 ((DatagramSessionConfig) acceptor.getSessionConfig()).setReuseAddress(true);
551
552 // Start the listener
553 acceptor.bind();
554 }
555
556 public InetSocketAddress localAddress() {
557 return (InetSocketAddress) getTransports()[0].getAcceptor().getLocalAddress();
558 }
559
560 /**
561 * {@link ProtocolCodecFactory} which allows to test AAAA resolution.
562 */
563 private static final class TestDnsProtocolUdpCodecFactory implements ProtocolCodecFactory {
564 private final DnsMessageEncoder encoder = new DnsMessageEncoder();
565 private final TestAAAARecordEncoder recordEncoder = new TestAAAARecordEncoder();
566
567 @Override
568 public ProtocolEncoder getEncoder(IoSession session) throws Exception {
569 return new DnsUdpEncoder() {
570
571 @Override
572 public void encode(IoSession session, Object message, ProtocolEncoderOutput out) {
573 IoBuffer buf = IoBuffer.allocate(1024);
574 DnsMessage dnsMessage = (DnsMessage) message;
575 encoder.encode(buf, dnsMessage);
576 for (ResourceRecord record: dnsMessage.getAnswerRecords()) {
577 // This is a hack to allow to also test for AAAA resolution as DnsMessageEncoder
578 // does not support it and it is hard to extend, because the interesting methods
579 // are private...
580 // In case of RecordType.AAAA we need to encode the RecordType by ourselves.
581 if (record.getRecordType() == RecordType.AAAA) {
582 try {
583 recordEncoder.put(buf, record);
584 } catch (IOException e) {
585 // Should never happen
586 throw new IllegalStateException(e);
587 }
588 }
589 }
590 buf.flip();
591
592 out.write(buf);
593 }
594 };
595 }
596
597 @Override
598 public ProtocolDecoder getDecoder(IoSession session) throws Exception {
599 return new DnsUdpDecoder();
600 }
601
602 private static final class TestAAAARecordEncoder extends ResourceRecordEncoder {
603
604 @Override
605 protected void putResourceRecordData(IoBuffer ioBuffer, ResourceRecord resourceRecord) {
606 byte[] bytes = BYTES.get(resourceRecord.get(DnsAttribute.IP_ADDRESS));
607 if (bytes == null) {
608 throw new IllegalStateException();
609 }
610 // encode the ::1
611 ioBuffer.put(bytes);
612 }
613 }
614 }
615
616 private static final class TestRecordStore implements RecordStore {
617 private static final int[] NUMBERS = new int[254];
618 private static final char[] CHARS = new char[26];
619
620 static {
621 for (int i = 0; i < NUMBERS.length; i++) {
622 NUMBERS[i] = i + 1;
623 }
624
625 for (int i = 0; i < CHARS.length; i++) {
626 CHARS[i] = (char) ('a' + i);
627 }
628 }
629
630 private static int index(int arrayLength) {
631 return Math.abs(ThreadLocalRandom.current().nextInt()) % arrayLength;
632 }
633
634 private static String nextDomain() {
635 return CHARS[index(CHARS.length)] + ".netty.io";
636 }
637
638 private static String nextIp() {
639 return ipPart() + "." + ipPart() + '.' + ipPart() + '.' + ipPart();
640 }
641
642 private static int ipPart() {
643 return NUMBERS[index(NUMBERS.length)];
644 }
645
646 private static String nextIp6() {
647 return IPV6_ADDRESSES[index(IPV6_ADDRESSES.length)];
648 }
649
650 @Override
651 public Set<ResourceRecord> getRecords(QuestionRecord questionRecord) {
652 String name = questionRecord.getDomainName();
653 if (DOMAINS.contains(name)) {
654 ResourceRecordModifier rm = new ResourceRecordModifier();
655 rm.setDnsClass(RecordClass.IN);
656 rm.setDnsName(name);
657 rm.setDnsTtl(100);
658 rm.setDnsType(questionRecord.getRecordType());
659
660 switch (questionRecord.getRecordType()) {
661 case A:
662 do {
663 rm.put(DnsAttribute.IP_ADDRESS, nextIp());
664 } while (ThreadLocalRandom.current().nextBoolean());
665 break;
666 case AAAA:
667 do {
668 rm.put(DnsAttribute.IP_ADDRESS, nextIp6());
669 } while (ThreadLocalRandom.current().nextBoolean());
670 break;
671 case MX:
672 int priority = 0;
673 do {
674 rm.put(DnsAttribute.DOMAIN_NAME, nextDomain());
675 rm.put(DnsAttribute.MX_PREFERENCE, String.valueOf(++priority));
676 } while (ThreadLocalRandom.current().nextBoolean());
677 break;
678 default:
679 return null;
680 }
681 return Collections.singleton(rm.getEntry());
682 }
683 return null;
684 }
685 }
686 }
687506 }
0 /*
1 * Copyright 2016 The Netty Project
2 *
3 * The Netty Project licenses this file to you under the Apache License,
4 * version 2.0 (the "License"); you may not use this file except in compliance
5 * with the License. You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 * License for the specific language governing permissions and limitations
13 * under the License.
14 */
15 package io.netty.resolver.dns;
16
17 import io.netty.channel.EventLoopGroup;
18 import io.netty.channel.nio.NioEventLoopGroup;
19 import io.netty.channel.socket.nio.NioDatagramChannel;
20 import io.netty.util.concurrent.Future;
21 import org.junit.After;
22 import org.junit.Before;
23 import org.junit.Test;
24
25 import java.net.InetAddress;
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.Collections;
29 import java.util.HashSet;
30 import java.util.List;
31 import java.util.Set;
32 import java.util.concurrent.TimeUnit;
33
34 import static org.junit.Assert.assertEquals;
35 import static org.junit.Assert.assertFalse;
36 import static org.junit.Assert.assertTrue;
37
38 public class SearchDomainTest {
39
40 private DnsNameResolverBuilder newResolver() {
41 return new DnsNameResolverBuilder(group.next())
42 .channelType(NioDatagramChannel.class)
43 .nameServerAddresses(DnsServerAddresses.singleton(dnsServer.localAddress()))
44 .maxQueriesPerResolve(1)
45 .optResourceEnabled(false);
46 }
47
48 private TestDnsServer dnsServer;
49 private EventLoopGroup group;
50
51 @Before
52 public void before() {
53 group = new NioEventLoopGroup(1);
54 }
55
56 @After
57 public void destroy() {
58 if (dnsServer != null) {
59 dnsServer.stop();
60 dnsServer = null;
61 }
62 group.shutdownGracefully();
63 }
64
65 @Test
66 public void testResolve() throws Exception {
67 Set<String> domains = new HashSet<String>();
68 domains.add("host1.foo.com");
69 domains.add("host1");
70 domains.add("host3");
71 domains.add("host4.sub.foo.com");
72 domains.add("host5.sub.foo.com");
73 domains.add("host5.sub");
74
75 TestDnsServer.MapRecordStoreA store = new TestDnsServer.MapRecordStoreA(domains);
76 dnsServer = new TestDnsServer(store);
77 dnsServer.start();
78
79 DnsNameResolver resolver = newResolver().searchDomains(Collections.singletonList("foo.com")).build();
80
81 String a = "host1.foo.com";
82 String resolved = assertResolve(resolver, a);
83 assertEquals(store.getAddress("host1.foo.com"), resolved);
84
85 // host1 resolves host1.foo.com with foo.com search domain
86 resolved = assertResolve(resolver, "host1");
87 assertEquals(store.getAddress("host1.foo.com"), resolved);
88
89 // "host1." absolute query
90 resolved = assertResolve(resolver, "host1.");
91 assertEquals(store.getAddress("host1"), resolved);
92
93 // "host2" not resolved
94 assertNotResolve(resolver, "host2");
95
96 // "host3" does not contain a dot or is not absolute
97 assertNotResolve(resolver, "host3");
98
99 // "host3." does not contain a dot but is absolute
100 resolved = assertResolve(resolver, "host3.");
101 assertEquals(store.getAddress("host3"), resolved);
102
103 // "host4.sub" contains a dot but not resolved then resolved to "host4.sub.foo.com" with "foo.com" search domain
104 resolved = assertResolve(resolver, "host4.sub");
105 assertEquals(store.getAddress("host4.sub.foo.com"), resolved);
106
107 // "host5.sub" contains a dot and is resolved
108 resolved = assertResolve(resolver, "host5.sub");
109 assertEquals(store.getAddress("host5.sub"), resolved);
110 }
111
112 @Test
113 public void testResolveAll() throws Exception {
114 Set<String> domains = new HashSet<String>();
115 domains.add("host1.foo.com");
116 domains.add("host1");
117 domains.add("host3");
118 domains.add("host4.sub.foo.com");
119 domains.add("host5.sub.foo.com");
120 domains.add("host5.sub");
121
122 TestDnsServer.MapRecordStoreA store = new TestDnsServer.MapRecordStoreA(domains, 2);
123 dnsServer = new TestDnsServer(store);
124 dnsServer.start();
125
126 DnsNameResolver resolver = newResolver().searchDomains(Collections.singletonList("foo.com")).build();
127
128 String a = "host1.foo.com";
129 List<String> resolved = assertResolveAll(resolver, a);
130 assertEquals(store.getAddresses("host1.foo.com"), resolved);
131
132 // host1 resolves host1.foo.com with foo.com search domain
133 resolved = assertResolveAll(resolver, "host1");
134 assertEquals(store.getAddresses("host1.foo.com"), resolved);
135
136 // "host1." absolute query
137 resolved = assertResolveAll(resolver, "host1.");
138 assertEquals(store.getAddresses("host1"), resolved);
139
140 // "host2" not resolved
141 assertNotResolveAll(resolver, "host2");
142
143 // "host3" does not contain a dot or is not absolute
144 assertNotResolveAll(resolver, "host3");
145
146 // "host3." does not contain a dot but is absolute
147 resolved = assertResolveAll(resolver, "host3.");
148 assertEquals(store.getAddresses("host3"), resolved);
149
150 // "host4.sub" contains a dot but not resolved then resolved to "host4.sub.foo.com" with "foo.com" search domain
151 resolved = assertResolveAll(resolver, "host4.sub");
152 assertEquals(store.getAddresses("host4.sub.foo.com"), resolved);
153
154 // "host5.sub" contains a dot and is resolved
155 resolved = assertResolveAll(resolver, "host5.sub");
156 assertEquals(store.getAddresses("host5.sub"), resolved);
157 }
158
159 @Test
160 public void testMultipleSearchDomain() throws Exception {
161 Set<String> domains = new HashSet<String>();
162 domains.add("host1.foo.com");
163 domains.add("host2.bar.com");
164 domains.add("host3.bar.com");
165 domains.add("host3.foo.com");
166
167 TestDnsServer.MapRecordStoreA store = new TestDnsServer.MapRecordStoreA(domains);
168 dnsServer = new TestDnsServer(store);
169 dnsServer.start();
170
171 DnsNameResolver resolver = newResolver().searchDomains(Arrays.asList("foo.com", "bar.com")).build();
172
173 // "host1" resolves via the "foo.com" search path
174 String resolved = assertResolve(resolver, "host1");
175 assertEquals(store.getAddress("host1.foo.com"), resolved);
176
177 // "host2" resolves via the "bar.com" search path
178 resolved = assertResolve(resolver, "host2");
179 assertEquals(store.getAddress("host2.bar.com"), resolved);
180
181 // "host3" resolves via the the "foo.com" search path as it is the first one
182 resolved = assertResolve(resolver, "host3");
183 assertEquals(store.getAddress("host3.foo.com"), resolved);
184
185 // "host4" does not resolve
186 assertNotResolve(resolver, "host4");
187 }
188
189 @Test
190 public void testSearchDomainWithNdots2() throws Exception {
191 Set<String> domains = new HashSet<String>();
192 domains.add("host1.sub.foo.com");
193 domains.add("host2.sub.foo.com");
194 domains.add("host2.sub");
195
196 TestDnsServer.MapRecordStoreA store = new TestDnsServer.MapRecordStoreA(domains);
197 dnsServer = new TestDnsServer(store);
198 dnsServer.start();
199
200 DnsNameResolver resolver = newResolver().searchDomains(Collections.singleton("foo.com")).ndots(2).build();
201
202 String resolved = assertResolve(resolver, "host1.sub");
203 assertEquals(store.getAddress("host1.sub.foo.com"), resolved);
204
205 // "host2.sub" is resolved with the foo.com search domain as ndots = 2
206 resolved = assertResolve(resolver, "host2.sub");
207 assertEquals(store.getAddress("host2.sub.foo.com"), resolved);
208 }
209
210 private void assertNotResolve(DnsNameResolver resolver, String inetHost) throws InterruptedException {
211 Future<InetAddress> fut = resolver.resolve(inetHost);
212 assertTrue(fut.await(10, TimeUnit.SECONDS));
213 assertFalse(fut.isSuccess());
214 }
215
216 private void assertNotResolveAll(DnsNameResolver resolver, String inetHost) throws InterruptedException {
217 Future<List<InetAddress>> fut = resolver.resolveAll(inetHost);
218 assertTrue(fut.await(10, TimeUnit.SECONDS));
219 assertFalse(fut.isSuccess());
220 }
221
222 private String assertResolve(DnsNameResolver resolver, String inetHost) throws InterruptedException {
223 Future<InetAddress> fut = resolver.resolve(inetHost);
224 assertTrue(fut.await(10, TimeUnit.SECONDS));
225 return fut.getNow().getHostAddress();
226 }
227
228 private List<String> assertResolveAll(DnsNameResolver resolver, String inetHost) throws InterruptedException {
229 Future<List<InetAddress>> fut = resolver.resolveAll(inetHost);
230 assertTrue(fut.await(10, TimeUnit.SECONDS));
231 List<String> list = new ArrayList<String>();
232 for (InetAddress addr : fut.getNow()) {
233 list.add(addr.getHostAddress());
234 }
235 return list;
236 }
237 }
0 /*
1 * Copyright 2016 The Netty Project
2 *
3 * The Netty Project licenses this file to you under the Apache License,
4 * version 2.0 (the "License"); you may not use this file except in compliance
5 * with the License. You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 * License for the specific language governing permissions and limitations
13 * under the License.
14 */
15 package io.netty.resolver.dns;
16
17 import io.netty.util.NetUtil;
18 import io.netty.util.internal.ThreadLocalRandom;
19 import org.apache.directory.server.dns.DnsException;
20 import org.apache.directory.server.dns.DnsServer;
21 import org.apache.directory.server.dns.io.encoder.DnsMessageEncoder;
22 import org.apache.directory.server.dns.io.encoder.ResourceRecordEncoder;
23 import org.apache.directory.server.dns.messages.DnsMessage;
24 import org.apache.directory.server.dns.messages.QuestionRecord;
25 import org.apache.directory.server.dns.messages.RecordClass;
26 import org.apache.directory.server.dns.messages.RecordType;
27 import org.apache.directory.server.dns.messages.ResourceRecord;
28 import org.apache.directory.server.dns.messages.ResourceRecordImpl;
29 import org.apache.directory.server.dns.messages.ResourceRecordModifier;
30 import org.apache.directory.server.dns.protocol.DnsProtocolHandler;
31 import org.apache.directory.server.dns.protocol.DnsUdpDecoder;
32 import org.apache.directory.server.dns.protocol.DnsUdpEncoder;
33 import org.apache.directory.server.dns.store.DnsAttribute;
34 import org.apache.directory.server.dns.store.RecordStore;
35 import org.apache.directory.server.protocol.shared.transport.UdpTransport;
36 import org.apache.mina.core.buffer.IoBuffer;
37 import org.apache.mina.core.session.IoSession;
38 import org.apache.mina.filter.codec.ProtocolCodecFactory;
39 import org.apache.mina.filter.codec.ProtocolCodecFilter;
40 import org.apache.mina.filter.codec.ProtocolDecoder;
41 import org.apache.mina.filter.codec.ProtocolEncoder;
42 import org.apache.mina.filter.codec.ProtocolEncoderOutput;
43 import org.apache.mina.transport.socket.DatagramAcceptor;
44 import org.apache.mina.transport.socket.DatagramSessionConfig;
45
46 import java.io.IOException;
47 import java.net.InetSocketAddress;
48 import java.util.ArrayList;
49 import java.util.Collections;
50 import java.util.HashMap;
51 import java.util.LinkedHashSet;
52 import java.util.List;
53 import java.util.Map;
54 import java.util.Set;
55
56 final class TestDnsServer extends DnsServer {
57 private static final Map<String, byte[]> BYTES = new HashMap<String, byte[]>();
58 private static final String[] IPV6_ADDRESSES;
59
60 static {
61 BYTES.put("::1", new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1});
62 BYTES.put("0:0:0:0:0:0:1:1", new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1});
63 BYTES.put("0:0:0:0:0:1:1:1", new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1});
64 BYTES.put("0:0:0:0:1:1:1:1", new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1});
65 BYTES.put("0:0:0:1:1:1:1:1", new byte[]{0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1});
66 BYTES.put("0:0:1:1:1:1:1:1", new byte[]{0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1});
67 BYTES.put("0:1:1:1:1:1:1:1", new byte[]{0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1});
68 BYTES.put("1:1:1:1:1:1:1:1", new byte[]{0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1});
69
70 IPV6_ADDRESSES = BYTES.keySet().toArray(new String[BYTES.size()]);
71 }
72
73 private final RecordStore store;
74
75 TestDnsServer(Set<String> domains) {
76 this.store = new TestRecordStore(domains);
77 }
78
79 TestDnsServer(RecordStore store) {
80 this.store = store;
81 }
82
83 @Override
84 public void start() throws IOException {
85 InetSocketAddress address = new InetSocketAddress(NetUtil.LOCALHOST4, 50000);
86 UdpTransport transport = new UdpTransport(address.getHostName(), address.getPort());
87 setTransports(transport);
88
89 DatagramAcceptor acceptor = transport.getAcceptor();
90
91 acceptor.setHandler(new DnsProtocolHandler(this, store) {
92 @Override
93 public void sessionCreated(IoSession session) throws Exception {
94 // USe our own codec to support AAAA testing
95 session.getFilterChain()
96 .addFirst("codec", new ProtocolCodecFilter(new TestDnsProtocolUdpCodecFactory()));
97 }
98 });
99
100 ((DatagramSessionConfig) acceptor.getSessionConfig()).setReuseAddress(true);
101
102 // Start the listener
103 acceptor.bind();
104 }
105
106 public InetSocketAddress localAddress() {
107 return (InetSocketAddress) getTransports()[0].getAcceptor().getLocalAddress();
108 }
109
110 /**
111 * {@link ProtocolCodecFactory} which allows to test AAAA resolution.
112 */
113 private static final class TestDnsProtocolUdpCodecFactory implements ProtocolCodecFactory {
114 private final DnsMessageEncoder encoder = new DnsMessageEncoder();
115 private final TestAAAARecordEncoder recordEncoder = new TestAAAARecordEncoder();
116
117 @Override
118 public ProtocolEncoder getEncoder(IoSession session) throws Exception {
119 return new DnsUdpEncoder() {
120
121 @Override
122 public void encode(IoSession session, Object message, ProtocolEncoderOutput out) {
123 IoBuffer buf = IoBuffer.allocate(1024);
124 DnsMessage dnsMessage = (DnsMessage) message;
125 encoder.encode(buf, dnsMessage);
126 for (ResourceRecord record : dnsMessage.getAnswerRecords()) {
127 // This is a hack to allow to also test for AAAA resolution as DnsMessageEncoder
128 // does not support it and it is hard to extend, because the interesting methods
129 // are private...
130 // In case of RecordType.AAAA we need to encode the RecordType by ourselves.
131 if (record.getRecordType() == RecordType.AAAA) {
132 try {
133 recordEncoder.put(buf, record);
134 } catch (IOException e) {
135 // Should never happen
136 throw new IllegalStateException(e);
137 }
138 }
139 }
140 buf.flip();
141
142 out.write(buf);
143 }
144 };
145 }
146
147 @Override
148 public ProtocolDecoder getDecoder(IoSession session) throws Exception {
149 return new DnsUdpDecoder();
150 }
151
152 private static final class TestAAAARecordEncoder extends ResourceRecordEncoder {
153
154 @Override
155 protected void putResourceRecordData(IoBuffer ioBuffer, ResourceRecord resourceRecord) {
156 byte[] bytes = BYTES.get(resourceRecord.get(DnsAttribute.IP_ADDRESS));
157 if (bytes == null) {
158 throw new IllegalStateException();
159 }
160 // encode the ::1
161 ioBuffer.put(bytes);
162 }
163 }
164 }
165
166 public static final class MapRecordStoreA implements RecordStore {
167
168 private final Map<String, List<String>> domainMap;
169
170 public MapRecordStoreA(Set<String> domains, int length) {
171 domainMap = new HashMap<String, List<String>>(domains.size());
172 for (String domain : domains) {
173 List<String> addresses = new ArrayList<String>(length);
174 for (int i = 0; i < length; i++) {
175 addresses.add(TestRecordStore.nextIp());
176 }
177 domainMap.put(domain, addresses);
178 }
179 }
180
181 public MapRecordStoreA(Set<String> domains) {
182 this(domains, 1);
183 }
184
185 public String getAddress(String domain) {
186 return domainMap.get(domain).get(0);
187 }
188
189 public List<String> getAddresses(String domain) {
190 return domainMap.get(domain);
191 }
192
193 @Override
194 public Set<ResourceRecord> getRecords(QuestionRecord questionRecord) throws DnsException {
195 String name = questionRecord.getDomainName();
196 List<String> addresses = domainMap.get(name);
197 if (addresses != null && questionRecord.getRecordType() == RecordType.A) {
198 Set<ResourceRecord> records = new LinkedHashSet<ResourceRecord>();
199 for (String address : addresses) {
200 HashMap<String, Object> attributes = new HashMap<String, Object>();
201 attributes.put(DnsAttribute.IP_ADDRESS.toLowerCase(), address);
202 records.add(new ResourceRecordImpl(name, questionRecord.getRecordType(),
203 RecordClass.IN, 100, attributes) {
204 @Override
205 public int hashCode() {
206 return System.identityHashCode(this);
207 }
208 @Override
209 public boolean equals(Object o) {
210 return false;
211 }
212 });
213 }
214 return records;
215 }
216 return null;
217 }
218 }
219
220 private static final class TestRecordStore implements RecordStore {
221 private static final int[] NUMBERS = new int[254];
222 private static final char[] CHARS = new char[26];
223
224 static {
225 for (int i = 0; i < NUMBERS.length; i++) {
226 NUMBERS[i] = i + 1;
227 }
228
229 for (int i = 0; i < CHARS.length; i++) {
230 CHARS[i] = (char) ('a' + i);
231 }
232 }
233
234 private static int index(int arrayLength) {
235 return Math.abs(ThreadLocalRandom.current().nextInt()) % arrayLength;
236 }
237
238 private static String nextDomain() {
239 return CHARS[index(CHARS.length)] + ".netty.io";
240 }
241
242 private static String nextIp() {
243 return ipPart() + "." + ipPart() + '.' + ipPart() + '.' + ipPart();
244 }
245
246 private static int ipPart() {
247 return NUMBERS[index(NUMBERS.length)];
248 }
249
250 private static String nextIp6() {
251 return IPV6_ADDRESSES[index(IPV6_ADDRESSES.length)];
252 }
253
254 private final Set<String> domains;
255
256 public TestRecordStore(Set<String> domains) {
257 this.domains = domains;
258 }
259
260 @Override
261 public Set<ResourceRecord> getRecords(QuestionRecord questionRecord) {
262 String name = questionRecord.getDomainName();
263 if (domains.contains(name)) {
264 ResourceRecordModifier rm = new ResourceRecordModifier();
265 rm.setDnsClass(RecordClass.IN);
266 rm.setDnsName(name);
267 rm.setDnsTtl(100);
268 rm.setDnsType(questionRecord.getRecordType());
269
270 switch (questionRecord.getRecordType()) {
271 case A:
272 do {
273 rm.put(DnsAttribute.IP_ADDRESS, nextIp());
274 } while (ThreadLocalRandom.current().nextBoolean());
275 break;
276 case AAAA:
277 do {
278 rm.put(DnsAttribute.IP_ADDRESS, nextIp6());
279 } while (ThreadLocalRandom.current().nextBoolean());
280 break;
281 case MX:
282 int priority = 0;
283 do {
284 rm.put(DnsAttribute.DOMAIN_NAME, nextDomain());
285 rm.put(DnsAttribute.MX_PREFERENCE, String.valueOf(++priority));
286 } while (ThreadLocalRandom.current().nextBoolean());
287 break;
288 default:
289 return null;
290 }
291 return Collections.singleton(rm.getEntry());
292 }
293 return null;
294 }
295 }
296 }
88 <groupId>org.asynchttpclient</groupId>
99 <artifactId>async-http-client-project</artifactId>
1010 <name>Asynchronous Http Client Project</name>
11 <version>2.0.10</version>
11 <version>2.0.11</version>
1212 <packaging>pom</packaging>
1313 <description>
1414 The Async Http Client (AHC) library's purpose is to allow Java
372372 <surefire.redirectTestOutputToFile>true</surefire.redirectTestOutputToFile>
373373 <source.property>1.8</source.property>
374374 <target.property>1.8</target.property>
375 <netty.version>4.0.38.Final</netty.version>
375 <netty.version>4.0.39.Final</netty.version>
376376 <slf4j.version>1.7.21</slf4j.version>
377377 <logback.version>1.1.7</logback.version>
378378 <testng.version>6.9.10</testng.version>