DnsPinger.java revision d2fe04b71a89a0608eb7c67065dead2a1f540122
1bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy/* 2bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy * Copyright (C) 2011 The Android Open Source Project 3bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy * 4bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy * Licensed under the Apache License, Version 2.0 (the "License"); 5bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy * you may not use this file except in compliance with the License. 6bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy * You may obtain a copy of the License at 7bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy * 8bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy * http://www.apache.org/licenses/LICENSE-2.0 9bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy * 10bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy * Unless required by applicable law or agreed to in writing, software 11bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy * distributed under the License is distributed on an "AS IS" BASIS, 12bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy * See the License for the specific language governing permissions and 14bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy * limitations under the License. 15bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy */ 16bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy 17a7bc1135c270fd4a84ab7ad45b7194e9b580300eIsaac Levypackage android.net; 18bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy 19bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levyimport android.content.Context; 20d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levyimport android.os.Handler; 21d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levyimport android.os.Looper; 22d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levyimport android.os.Message; 23bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levyimport android.os.SystemClock; 243541ce04ddb1b559ac9e79b5067c93b910f22955Isaac Levyimport android.provider.Settings; 25bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levyimport android.util.Slog; 26bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy 27d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levyimport com.android.internal.util.Protocol; 28d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy 29d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levyimport java.io.IOException; 30bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levyimport java.net.DatagramPacket; 31bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levyimport java.net.DatagramSocket; 32bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levyimport java.net.InetAddress; 333ee9d05d971cbf0c720057aec54ffac289af40feIsaac Levyimport java.net.NetworkInterface; 34bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levyimport java.net.SocketTimeoutException; 35d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levyimport java.util.ArrayList; 36bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levyimport java.util.Collection; 37d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levyimport java.util.Iterator; 38d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levyimport java.util.List; 39bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levyimport java.util.Random; 40d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levyimport java.util.concurrent.atomic.AtomicInteger; 41bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy 42bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy/** 43bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy * Performs a simple DNS "ping" by sending a "server status" query packet to the 44bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy * DNS server. As long as the server replies, we consider it a success. 45bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy * <p> 46bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy * We do not use a simple hostname lookup because that could be cached and the 47bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy * API may not differentiate between a time out and a failure lookup (which we 48bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy * really care about). 49bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy * <p> 50bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy * 51bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy * @hide 52bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy */ 53d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levypublic final class DnsPinger extends Handler { 54bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy private static final boolean V = true; 55bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy 56d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy private static final int RECEIVE_POLL_INTERVAL_MS = 30; 57bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy private static final int DNS_PORT = 53; 58bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy 59d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy /** Short socket timeout so we don't block one any 'receive' call */ 60d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy private static final int SOCKET_TIMEOUT_MS = 1; 61d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy 62bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy /** Used to generate IDs */ 63d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy private static final Random sRandom = new Random(); 64d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy private static final AtomicInteger sCounter = new AtomicInteger(); 65bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy 66bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy private ConnectivityManager mConnectivityManager = null; 67d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy private final Context mContext; 68d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy private final int mConnectionType; 69d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy private final Handler mTarget; 70d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy private final InetAddress mDefaultDns; 71bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy private String TAG; 72bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy 73d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy private static final int BASE = Protocol.BASE_DNS_PINGER; 74d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy 75b1ef292b3d0c2b4b4c77bb7b442df8e73d1fbb5eIsaac Levy /** 76d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy * Async response packet for dns pings. 77d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy * arg1 is the ID of the ping, also returned by {@link #pingDnsAsync(InetAddress, int, int)} 78d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy * arg2 is the delay, or is negative on error. 79b1ef292b3d0c2b4b4c77bb7b442df8e73d1fbb5eIsaac Levy */ 80d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy public static final int DNS_PING_RESULT = BASE; 81d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy /** An error code for a {@link #DNS_PING_RESULT} packet */ 82d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy public static final int TIMEOUT = -1; 83d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy /** An error code for a {@link #DNS_PING_RESULT} packet */ 84d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy public static final int SOCKET_EXCEPTION = -2; 85d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy 86d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy /** 87d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy * Send a new ping via a socket. arg1 is ID, arg2 is timeout, obj is InetAddress to ping 88d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy */ 89d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy private static final int ACTION_PING_DNS = BASE + 1; 90d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy private static final int ACTION_LISTEN_FOR_RESPONSE = BASE + 2; 91d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy private static final int ACTION_CANCEL_ALL_PINGS = BASE + 3; 92d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy 93d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy private List<ActivePing> mActivePings = new ArrayList<ActivePing>(); 94d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy private int mEventCounter; 95d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy 96d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy private class ActivePing { 97d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy DatagramSocket socket; 98d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy int internalId; 99d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy short packetId; 100d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy int timeout; 101d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy Integer result; 102d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy long start = SystemClock.elapsedRealtime(); 103d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy } 104d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy 105d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy public DnsPinger(Context context, String TAG, Looper looper, 106d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy Handler target, int connectionType) { 107d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy super(looper); 108d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy this.TAG = TAG; 109bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy mContext = context; 110d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy mTarget = target; 111b1ef292b3d0c2b4b4c77bb7b442df8e73d1fbb5eIsaac Levy mConnectionType = connectionType; 1123541ce04ddb1b559ac9e79b5067c93b910f22955Isaac Levy if (!ConnectivityManager.isNetworkTypeValid(connectionType)) { 113d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy throw new IllegalArgumentException("Invalid connectionType in constructor: " 114d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy + connectionType); 1153541ce04ddb1b559ac9e79b5067c93b910f22955Isaac Levy } 1163541ce04ddb1b559ac9e79b5067c93b910f22955Isaac Levy mDefaultDns = getDefaultDns(); 117d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy mEventCounter = 0; 118d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy } 119d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy 120d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy @Override 121d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy public void handleMessage(Message msg) { 122d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy switch (msg.what) { 123d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy case ACTION_PING_DNS: 124d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy try { 125d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy ActivePing newActivePing = new ActivePing(); 126d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy InetAddress dnsAddress = (InetAddress) msg.obj; 127d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy newActivePing.internalId = msg.arg1; 128d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy newActivePing.timeout = msg.arg2; 129d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy newActivePing.socket = new DatagramSocket(); 130d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy // Set some socket properties 131d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy newActivePing.socket.setSoTimeout(SOCKET_TIMEOUT_MS); 132d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy 133d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy // Try to bind but continue ping if bind fails 134d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy try { 135d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy newActivePing.socket.setNetworkInterface(NetworkInterface.getByName( 136d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy getCurrentLinkProperties().getInterfaceName())); 137d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy } catch (Exception e) { 138d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy Slog.w(TAG,"sendDnsPing::Error binding to socket", e); 139d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy } 140d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy 141d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy newActivePing.packetId = (short) sRandom.nextInt(); 142d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy byte[] buf = mDnsQuery.clone(); 143d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy buf[0] = (byte) (newActivePing.packetId >> 8); 144d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy buf[1] = (byte) newActivePing.packetId; 145d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy 146d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy // Send the DNS query 147d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy DatagramPacket packet = new DatagramPacket(buf, 148d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy buf.length, dnsAddress, DNS_PORT); 149d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy if (V) { 150d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy Slog.v(TAG, "Sending a ping to " + dnsAddress.getHostAddress() 151d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy + " with ID " + newActivePing.packetId + "."); 152d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy } 153d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy 154d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy newActivePing.socket.send(packet); 155d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy mActivePings.add(newActivePing); 156d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy mEventCounter++; 157d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy sendMessageDelayed(obtainMessage(ACTION_LISTEN_FOR_RESPONSE, mEventCounter, 0), 158d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy RECEIVE_POLL_INTERVAL_MS); 159d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy } catch (IOException e) { 160d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy sendResponse((short) msg.arg1, SOCKET_EXCEPTION); 161d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy } 162d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy break; 163d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy case ACTION_LISTEN_FOR_RESPONSE: 164d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy if (msg.arg1 != mEventCounter) { 165d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy break; 166d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy } 167d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy for (ActivePing curPing : mActivePings) { 168d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy try { 169d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy /** Each socket will block for {@link #SOCKET_TIMEOUT_MS} in receive() */ 170d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy byte[] responseBuf = new byte[2]; 171d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy DatagramPacket replyPacket = new DatagramPacket(responseBuf, 2); 172d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy curPing.socket.receive(replyPacket); 173d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy // Check that ID field matches (we're throwing out the rest of the packet) 174d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy if (responseBuf[0] == (byte) (curPing.packetId >> 8) && 175d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy responseBuf[1] == (byte) curPing.packetId) { 176d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy curPing.result = 177d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy (int) (SystemClock.elapsedRealtime() - curPing.start); 178d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy } else { 179d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy if (V) { 180d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy Slog.v(TAG, "response ID didn't match, ignoring packet"); 181d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy } 182d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy } 183d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy } catch (SocketTimeoutException e) { 184d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy // A timeout here doesn't mean anything - squelsh this exception 185d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy } catch (Exception e) { 186d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy if (V) { 187d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy Slog.v(TAG, "DnsPinger.pingDns got socket exception: ", e); 188d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy } 189d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy curPing.result = SOCKET_EXCEPTION; 190d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy } 191d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy } 192d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy Iterator<ActivePing> iter = mActivePings.iterator(); 193d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy while (iter.hasNext()) { 194d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy ActivePing curPing = iter.next(); 195d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy if (curPing.result != null) { 196d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy sendResponse(curPing.internalId, curPing.result); 197d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy curPing.socket.close(); 198d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy iter.remove(); 199d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy } else if (SystemClock.elapsedRealtime() > 200d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy curPing.start + curPing.timeout) { 201d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy sendResponse(curPing.internalId, TIMEOUT); 202d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy curPing.socket.close(); 203d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy iter.remove(); 204d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy } 205d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy } 206d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy if (!mActivePings.isEmpty()) { 207d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy sendMessageDelayed(obtainMessage(ACTION_LISTEN_FOR_RESPONSE, mEventCounter, 0), 208d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy RECEIVE_POLL_INTERVAL_MS); 209d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy } 210d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy break; 211d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy case ACTION_CANCEL_ALL_PINGS: 212d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy for (ActivePing activePing : mActivePings) 213d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy activePing.socket.close(); 214d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy mActivePings.clear(); 215d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy removeMessages(ACTION_PING_DNS); 216d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy break; 217d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy } 218bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy } 219bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy 220bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy /** 2213541ce04ddb1b559ac9e79b5067c93b910f22955Isaac Levy * @return The first DNS in the link properties of the specified connection 2223541ce04ddb1b559ac9e79b5067c93b910f22955Isaac Levy * type or the default system DNS if the link properties has null 2233541ce04ddb1b559ac9e79b5067c93b910f22955Isaac Levy * dns set. Should not be null. 224bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy */ 225bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy public InetAddress getDns() { 2263ee9d05d971cbf0c720057aec54ffac289af40feIsaac Levy LinkProperties curLinkProps = getCurrentLinkProperties(); 2273541ce04ddb1b559ac9e79b5067c93b910f22955Isaac Levy if (curLinkProps == null) { 2283541ce04ddb1b559ac9e79b5067c93b910f22955Isaac Levy Slog.e(TAG, "getCurLinkProperties:: LP for type" + mConnectionType + " is null!"); 2293541ce04ddb1b559ac9e79b5067c93b910f22955Isaac Levy return mDefaultDns; 2303541ce04ddb1b559ac9e79b5067c93b910f22955Isaac Levy } 2313541ce04ddb1b559ac9e79b5067c93b910f22955Isaac Levy 2323541ce04ddb1b559ac9e79b5067c93b910f22955Isaac Levy Collection<InetAddress> dnses = curLinkProps.getDnses(); 2333541ce04ddb1b559ac9e79b5067c93b910f22955Isaac Levy if (dnses == null || dnses.size() == 0) { 2343541ce04ddb1b559ac9e79b5067c93b910f22955Isaac Levy Slog.v(TAG, "getDns::LinkProps has null dns - returning default"); 2353541ce04ddb1b559ac9e79b5067c93b910f22955Isaac Levy return mDefaultDns; 2363541ce04ddb1b559ac9e79b5067c93b910f22955Isaac Levy } 237bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy 238bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy return dnses.iterator().next(); 239bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy } 240bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy 241d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy /** 242d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy * Send a ping. The response will come via a {@link #DNS_PING_RESULT} to the handler 243d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy * specified at creation. 244d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy * @param dns address of dns server to ping 245d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy * @param timeout timeout for ping 246d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy * @return an ID field, which will also be included in the {@link #DNS_PING_RESULT} message. 247d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy */ 248d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy public int pingDnsAsync(InetAddress dns, int timeout, int delay) { 249d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy int id = sCounter.incrementAndGet(); 250d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy sendMessageDelayed(obtainMessage(ACTION_PING_DNS, id, timeout, dns), delay); 251d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy return id; 252d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy } 253d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy 254d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy public void cancelPings() { 255d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy obtainMessage(ACTION_CANCEL_ALL_PINGS).sendToTarget(); 256d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy } 257d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy 258d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy private void sendResponse(int internalId, int responseVal) { 259d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy if(V) { 260d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy Slog.v(TAG, "Responding with id " + internalId + " and val " + responseVal); 261d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy } 262d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy mTarget.sendMessage(obtainMessage(DNS_PING_RESULT, internalId, responseVal)); 263d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy } 264d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy 2653ee9d05d971cbf0c720057aec54ffac289af40feIsaac Levy private LinkProperties getCurrentLinkProperties() { 2663ee9d05d971cbf0c720057aec54ffac289af40feIsaac Levy if (mConnectivityManager == null) { 2673ee9d05d971cbf0c720057aec54ffac289af40feIsaac Levy mConnectivityManager = (ConnectivityManager) mContext.getSystemService( 2683ee9d05d971cbf0c720057aec54ffac289af40feIsaac Levy Context.CONNECTIVITY_SERVICE); 2693ee9d05d971cbf0c720057aec54ffac289af40feIsaac Levy } 2703ee9d05d971cbf0c720057aec54ffac289af40feIsaac Levy 2713ee9d05d971cbf0c720057aec54ffac289af40feIsaac Levy return mConnectivityManager.getLinkProperties(mConnectionType); 2723ee9d05d971cbf0c720057aec54ffac289af40feIsaac Levy } 2733ee9d05d971cbf0c720057aec54ffac289af40feIsaac Levy 2743541ce04ddb1b559ac9e79b5067c93b910f22955Isaac Levy private InetAddress getDefaultDns() { 2753541ce04ddb1b559ac9e79b5067c93b910f22955Isaac Levy String dns = Settings.Secure.getString(mContext.getContentResolver(), 2763541ce04ddb1b559ac9e79b5067c93b910f22955Isaac Levy Settings.Secure.DEFAULT_DNS_SERVER); 2773541ce04ddb1b559ac9e79b5067c93b910f22955Isaac Levy if (dns == null || dns.length() == 0) { 2783541ce04ddb1b559ac9e79b5067c93b910f22955Isaac Levy dns = mContext.getResources().getString( 2793541ce04ddb1b559ac9e79b5067c93b910f22955Isaac Levy com.android.internal.R.string.config_default_dns_server); 2803541ce04ddb1b559ac9e79b5067c93b910f22955Isaac Levy } 2813541ce04ddb1b559ac9e79b5067c93b910f22955Isaac Levy try { 2823541ce04ddb1b559ac9e79b5067c93b910f22955Isaac Levy return NetworkUtils.numericToInetAddress(dns); 2833541ce04ddb1b559ac9e79b5067c93b910f22955Isaac Levy } catch (IllegalArgumentException e) { 2843541ce04ddb1b559ac9e79b5067c93b910f22955Isaac Levy Slog.w(TAG, "getDefaultDns::malformed default dns address"); 2853541ce04ddb1b559ac9e79b5067c93b910f22955Isaac Levy return null; 286b1ef292b3d0c2b4b4c77bb7b442df8e73d1fbb5eIsaac Levy } 287b1ef292b3d0c2b4b4c77bb7b442df8e73d1fbb5eIsaac Levy } 288b1ef292b3d0c2b4b4c77bb7b442df8e73d1fbb5eIsaac Levy 289d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy private static final byte[] mDnsQuery = new byte[] { 290d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy 0, 0, // [0-1] is for ID (will set each time) 291d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy 0, 0, // [2-3] are flags. Set byte[2] = 1 for recursion desired (RD) on. Currently off. 292d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy 0, 1, // [4-5] bytes are for number of queries (QCOUNT) 293d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy 0, 0, // [6-7] unused count field for dns response packets 294d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy 0, 0, // [8-9] unused count field for dns response packets 295d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy 0, 0, // [10-11] unused count field for dns response packets 296d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy 3, 'w', 'w', 'w', 297d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy 6, 'g', 'o', 'o', 'g', 'l', 'e', 298d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy 3, 'c', 'o', 'm', 299d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy 0, // null terminator of address (also called empty TLD) 300d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy 0, 1, // QTYPE, set to 1 = A (host address) 301d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy 0, 1 // QCLASS, set to 1 = IN (internet) 302d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy }; 303bc7dfb58bffea133ccf6d94470a26f8d193f4890Isaac Levy} 304