1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.net;
18 
19 import android.annotation.NonNull;
20 import android.util.Log;
21 
22 import java.io.IOException;
23 import java.net.InetSocketAddress;
24 
25 import javax.net.SocketFactory;
26 import javax.net.ssl.SSLSocket;
27 import javax.net.ssl.SSLSocketFactory;
28 
29 /**
30  * Class for testing connectivity to DNS-over-TLS servers.
31  * {@hide}
32  */
33 public class PrivateDnsConnectivityChecker {
34     private static final String TAG = "NetworkUtils";
35 
36     private static final int PRIVATE_DNS_PORT = 853;
37     private static final int CONNECTION_TIMEOUT_MS = 5000;
38 
PrivateDnsConnectivityChecker()39     private PrivateDnsConnectivityChecker() { }
40 
41     /**
42      * checks that a provided host can perform a TLS handshake on port 853.
43      * @param hostname host to connect to.
44      */
canConnectToPrivateDnsServer(@onNull String hostname)45     public static boolean canConnectToPrivateDnsServer(@NonNull String hostname) {
46         final SocketFactory factory = SSLSocketFactory.getDefault();
47         TrafficStats.setThreadStatsTag(TrafficStats.TAG_SYSTEM_APP);
48 
49         try (SSLSocket socket = (SSLSocket) factory.createSocket()) {
50             socket.setSoTimeout(CONNECTION_TIMEOUT_MS);
51             socket.connect(new InetSocketAddress(hostname, PRIVATE_DNS_PORT));
52             if (!socket.isConnected()) {
53                 Log.w(TAG, String.format("Connection to %s failed.", hostname));
54                 return false;
55             }
56             socket.startHandshake();
57             Log.w(TAG, String.format("TLS handshake to %s succeeded.", hostname));
58             return true;
59         } catch (IOException e) {
60             Log.w(TAG, String.format("TLS handshake to %s failed.", hostname), e);
61             return false;
62         }
63     }
64 }
65