diff options
| -rw-r--r-- | core/java/android/net/DnsPinger.java | 334 |
1 files changed, 0 insertions, 334 deletions
diff --git a/core/java/android/net/DnsPinger.java b/core/java/android/net/DnsPinger.java deleted file mode 100644 index 7acf3f556595..000000000000 --- a/core/java/android/net/DnsPinger.java +++ /dev/null @@ -1,334 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.content.Context; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.os.SystemClock; -import android.provider.Settings; -import android.util.Log; - -import com.android.internal.util.Protocol; - -import java.io.IOException; -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.net.SocketTimeoutException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Random; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * Performs a simple DNS "ping" by sending a "server status" query packet to the - * DNS server. As long as the server replies, we consider it a success. - * <p> - * We do not use a simple hostname lookup because that could be cached and the - * API may not differentiate between a time out and a failure lookup (which we - * really care about). - * <p> - * - * @hide - */ -public final class DnsPinger extends Handler { - private static final boolean DBG = false; - - private static final int RECEIVE_POLL_INTERVAL_MS = 200; - private static final int DNS_PORT = 53; - - /** Short socket timeout so we don't block one any 'receive' call */ - private static final int SOCKET_TIMEOUT_MS = 1; - - /** Used to generate IDs */ - private static final Random sRandom = new Random(); - private static final AtomicInteger sCounter = new AtomicInteger(); - - private ConnectivityManager mConnectivityManager = null; - private final Context mContext; - private final int mConnectionType; - private final Handler mTarget; - private final ArrayList<InetAddress> mDefaultDns; - private String TAG; - - //Invalidates old dns requests upon a cancel - private AtomicInteger mCurrentToken = new AtomicInteger(); - - private static final int BASE = Protocol.BASE_DNS_PINGER; - - /** - * Async response packet for dns pings. - * arg1 is the ID of the ping, also returned by {@link #pingDnsAsync(InetAddress, int, int)} - * arg2 is the delay, or is negative on error. - */ - public static final int DNS_PING_RESULT = BASE; - /** An error code for a {@link #DNS_PING_RESULT} packet */ - public static final int TIMEOUT = -1; - /** An error code for a {@link #DNS_PING_RESULT} packet */ - public static final int SOCKET_EXCEPTION = -2; - - /** - * Send a new ping via a socket. arg1 is ID, arg2 is timeout, obj is InetAddress to ping - */ - private static final int ACTION_PING_DNS = BASE + 1; - private static final int ACTION_LISTEN_FOR_RESPONSE = BASE + 2; - private static final int ACTION_CANCEL_ALL_PINGS = BASE + 3; - - private List<ActivePing> mActivePings = new ArrayList<ActivePing>(); - private int mEventCounter; - - private class ActivePing { - DatagramSocket socket; - int internalId; - short packetId; - int timeout; - Integer result; - long start = SystemClock.elapsedRealtime(); - } - - /* Message argument for ACTION_PING_DNS */ - private class DnsArg { - InetAddress dns; - int seq; - - DnsArg(InetAddress d, int s) { - dns = d; - seq = s; - } - } - - public DnsPinger(Context context, String TAG, Looper looper, - Handler target, int connectionType) { - super(looper); - this.TAG = TAG; - mContext = context; - mTarget = target; - mConnectionType = connectionType; - if (!ConnectivityManager.isNetworkTypeValid(connectionType)) { - throw new IllegalArgumentException("Invalid connectionType in constructor: " - + connectionType); - } - mDefaultDns = new ArrayList<InetAddress>(); - mDefaultDns.add(getDefaultDns()); - mEventCounter = 0; - } - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case ACTION_PING_DNS: - DnsArg dnsArg = (DnsArg) msg.obj; - if (dnsArg.seq != mCurrentToken.get()) { - break; - } - try { - ActivePing newActivePing = new ActivePing(); - InetAddress dnsAddress = dnsArg.dns; - newActivePing.internalId = msg.arg1; - newActivePing.timeout = msg.arg2; - newActivePing.socket = new DatagramSocket(); - // Set some socket properties - newActivePing.socket.setSoTimeout(SOCKET_TIMEOUT_MS); - - // Try to bind but continue ping if bind fails - try { - newActivePing.socket.setNetworkInterface(NetworkInterface.getByName( - getCurrentLinkProperties().getInterfaceName())); - } catch (Exception e) { - loge("sendDnsPing::Error binding to socket " + e); - } - - newActivePing.packetId = (short) sRandom.nextInt(); - byte[] buf = mDnsQuery.clone(); - buf[0] = (byte) (newActivePing.packetId >> 8); - buf[1] = (byte) newActivePing.packetId; - - // Send the DNS query - DatagramPacket packet = new DatagramPacket(buf, - buf.length, dnsAddress, DNS_PORT); - if (DBG) { - log("Sending a ping " + newActivePing.internalId + - " to " + dnsAddress.getHostAddress() - + " with packetId " + newActivePing.packetId + "."); - } - - newActivePing.socket.send(packet); - mActivePings.add(newActivePing); - mEventCounter++; - sendMessageDelayed(obtainMessage(ACTION_LISTEN_FOR_RESPONSE, mEventCounter, 0), - RECEIVE_POLL_INTERVAL_MS); - } catch (IOException e) { - sendResponse(msg.arg1, -9999, SOCKET_EXCEPTION); - } - break; - case ACTION_LISTEN_FOR_RESPONSE: - if (msg.arg1 != mEventCounter) { - break; - } - for (ActivePing curPing : mActivePings) { - try { - /** Each socket will block for {@link #SOCKET_TIMEOUT_MS} in receive() */ - byte[] responseBuf = new byte[2]; - DatagramPacket replyPacket = new DatagramPacket(responseBuf, 2); - curPing.socket.receive(replyPacket); - // Check that ID field matches (we're throwing out the rest of the packet) - if (responseBuf[0] == (byte) (curPing.packetId >> 8) && - responseBuf[1] == (byte) curPing.packetId) { - curPing.result = - (int) (SystemClock.elapsedRealtime() - curPing.start); - } else { - if (DBG) { - log("response ID didn't match, ignoring packet"); - } - } - } catch (SocketTimeoutException e) { - // A timeout here doesn't mean anything - squelsh this exception - } catch (Exception e) { - if (DBG) { - log("DnsPinger.pingDns got socket exception: " + e); - } - curPing.result = SOCKET_EXCEPTION; - } - } - Iterator<ActivePing> iter = mActivePings.iterator(); - while (iter.hasNext()) { - ActivePing curPing = iter.next(); - if (curPing.result != null) { - sendResponse(curPing.internalId, curPing.packetId, curPing.result); - curPing.socket.close(); - iter.remove(); - } else if (SystemClock.elapsedRealtime() > - curPing.start + curPing.timeout) { - sendResponse(curPing.internalId, curPing.packetId, TIMEOUT); - curPing.socket.close(); - iter.remove(); - } - } - if (!mActivePings.isEmpty()) { - sendMessageDelayed(obtainMessage(ACTION_LISTEN_FOR_RESPONSE, mEventCounter, 0), - RECEIVE_POLL_INTERVAL_MS); - } - break; - case ACTION_CANCEL_ALL_PINGS: - for (ActivePing activePing : mActivePings) - activePing.socket.close(); - mActivePings.clear(); - break; - } - } - - /** - * Returns a list of DNS addresses, coming from either the link properties of the - * specified connection or the default system DNS if the link properties has no dnses. - * @return a non-empty non-null list - */ - public List<InetAddress> getDnsList() { - LinkProperties curLinkProps = getCurrentLinkProperties(); - if (curLinkProps == null) { - loge("getCurLinkProperties:: LP for type" + mConnectionType + " is null!"); - return mDefaultDns; - } - - Collection<InetAddress> dnses = curLinkProps.getDnsServers(); - if (dnses == null || dnses.size() == 0) { - loge("getDns::LinkProps has null dns - returning default"); - return mDefaultDns; - } - - return new ArrayList<InetAddress>(dnses); - } - - /** - * Send a ping. The response will come via a {@link #DNS_PING_RESULT} to the handler - * specified at creation. - * @param dns address of dns server to ping - * @param timeout timeout for ping - * @return an ID field, which will also be included in the {@link #DNS_PING_RESULT} message. - */ - public int pingDnsAsync(InetAddress dns, int timeout, int delay) { - int id = sCounter.incrementAndGet(); - sendMessageDelayed(obtainMessage(ACTION_PING_DNS, id, timeout, - new DnsArg(dns, mCurrentToken.get())), delay); - return id; - } - - public void cancelPings() { - mCurrentToken.incrementAndGet(); - obtainMessage(ACTION_CANCEL_ALL_PINGS).sendToTarget(); - } - - private void sendResponse(int internalId, int externalId, int responseVal) { - if(DBG) { - log("Responding to packet " + internalId + - " externalId " + externalId + - " and val " + responseVal); - } - mTarget.sendMessage(obtainMessage(DNS_PING_RESULT, internalId, responseVal)); - } - - private LinkProperties getCurrentLinkProperties() { - if (mConnectivityManager == null) { - mConnectivityManager = (ConnectivityManager) mContext.getSystemService( - Context.CONNECTIVITY_SERVICE); - } - - return mConnectivityManager.getLinkProperties(mConnectionType); - } - - private InetAddress getDefaultDns() { - String dns = Settings.Global.getString(mContext.getContentResolver(), - Settings.Global.DEFAULT_DNS_SERVER); - if (dns == null || dns.length() == 0) { - dns = mContext.getResources().getString( - com.android.internal.R.string.config_default_dns_server); - } - try { - return NetworkUtils.numericToInetAddress(dns); - } catch (IllegalArgumentException e) { - loge("getDefaultDns::malformed default dns address"); - return null; - } - } - - private static final byte[] mDnsQuery = new byte[] { - 0, 0, // [0-1] is for ID (will set each time) - 1, 0, // [2-3] are flags. Set byte[2] = 1 for recursion desired (RD) on. Currently on. - 0, 1, // [4-5] bytes are for number of queries (QCOUNT) - 0, 0, // [6-7] unused count field for dns response packets - 0, 0, // [8-9] unused count field for dns response packets - 0, 0, // [10-11] unused count field for dns response packets - 3, 'w', 'w', 'w', - 6, 'g', 'o', 'o', 'g', 'l', 'e', - 3, 'c', 'o', 'm', - 0, // null terminator of address (also called empty TLD) - 0, 1, // QTYPE, set to 1 = A (host address) - 0, 1 // QCLASS, set to 1 = IN (internet) - }; - - private void log(String s) { - Log.d(TAG, s); - } - - private void loge(String s) { - Log.e(TAG, s); - } -} |