package org.itxtech.daedalus.fragment; import android.content.Context; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.design.widget.Snackbar; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; import android.widget.*; import de.measite.minidns.DNSMessage; import de.measite.minidns.Question; import de.measite.minidns.Record; import de.measite.minidns.record.A; import de.measite.minidns.source.NetworkDataSource; import de.measite.minidns.util.InetAddressUtil; import org.itxtech.daedalus.Daedalus; import org.itxtech.daedalus.R; import org.itxtech.daedalus.activity.MainActivity; import org.itxtech.daedalus.util.DnsServerHelper; import java.io.IOException; import java.net.InetAddress; import java.util.ArrayList; import java.util.Arrays; import java.util.Random; import java.util.Set; /** * Daedalus Project * * @author iTX Technologies * @link https://itxtech.org * <p> * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. */ public class DnsTestFragment extends ToolbarFragment { private static final String TAG = "DServerTest"; private static Thread mThread = null; private static Runnable mRunnable = null; private DnsTestHandler mHandler = null; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_dns_test, container, false); final TextView textViewTestInfo = (TextView) view.findViewById(R.id.textView_test_info); final Spinner spinnerServerChoice = (Spinner) view.findViewById(R.id.spinner_server_choice); ArrayAdapter spinnerArrayAdapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_1, DnsServerHelper.getNames(Daedalus.getInstance())); spinnerServerChoice.setAdapter(spinnerArrayAdapter); spinnerServerChoice.setSelection(DnsServerHelper.getPosition(DnsServerHelper.getPrimary())); final AutoCompleteTextView textViewTestUrl = (AutoCompleteTextView) view.findViewById(R.id.autoCompleteTextView_test_url); ArrayAdapter autoCompleteArrayAdapter = new ArrayAdapter<>(Daedalus.getInstance(), android.R.layout.simple_list_item_1, Daedalus.DEFAULT_TEST_DOMAINS); textViewTestUrl.setAdapter(autoCompleteArrayAdapter); mRunnable = new Runnable() { @Override public void run() { try { String testDomain = textViewTestUrl.getText().toString(); if (testDomain.equals("")) { testDomain = Daedalus.DEFAULT_TEST_DOMAINS[0]; } StringBuilder testText = new StringBuilder(); ArrayList<String> dnsServers = new ArrayList<String>() {{ add(DnsServerHelper.getAddressByDescription(Daedalus.getInstance(), spinnerServerChoice.getSelectedItem().toString())); String servers = Daedalus.getPrefs().getString("dns_test_servers", ""); if (!servers.equals("")) { addAll(Arrays.asList(servers.split(","))); } }}; DNSQuery dnsQuery = new DNSQuery(); for (String dnsServer : dnsServers) { testText = testServer(dnsQuery, dnsServer, testDomain, testText); } mHandler.obtainMessage(DnsTestHandler.MSG_TEST_DONE).sendToTarget(); } catch (Exception e) { Log.e(TAG, e.toString()); } } private StringBuilder testServer(DNSQuery dnsQuery, String dnsServer, String testUrl, StringBuilder testText) { Log.d(TAG, "Testing DNS " + dnsServer); testText.append(getResources().getString(R.string.test_domain)).append(" ").append(testUrl).append("\n").append(getResources().getString(R.string.test_dns_server)).append(" ").append(dnsServer); mHandler.obtainMessage(DnsTestHandler.MSG_DISPLAY_STATUS, testText.toString()).sendToTarget(); Question question = new Question(testUrl, Record.TYPE.getType(A.class)); DNSMessage.Builder message = DNSMessage.builder(); message.setQuestion(question); message.setId((new Random()).nextInt()); message.setRecursionDesired(true); message.getEdnsBuilder().setUdpPayloadSize(1024).setDnssecOk(false); try { long startTime = System.currentTimeMillis(); DNSMessage responseMessage = dnsQuery.query(message.build(), InetAddressUtil.ipv4From(dnsServer), 53);//Auto forward ports long endTime = System.currentTimeMillis(); Set<A> answers = responseMessage.getAnswersFor(question); if (answers != null && answers.size() > 0) { for (A a : answers) { InetAddress inetAddress = a.getInetAddress(); testText.append("\n").append(getResources().getString(R.string.test_result_resolved)).append(" ").append(inetAddress.getHostAddress()); } testText.append("\n").append(getResources().getString(R.string.test_time_used)).append(" "). append(String.valueOf(endTime - startTime)).append(" ms\n\n"); } else { testText.append("\n").append(getResources().getString(R.string.test_failed)).append("\n\n"); } } catch (Exception e) { testText.append("\n").append(getResources().getString(R.string.test_failed)).append("\n\n"); Log.e(TAG, e.toString()); } mHandler.obtainMessage(DnsTestHandler.MSG_DISPLAY_STATUS, testText.toString()).sendToTarget(); return testText; } }; final Button startTestBut = (Button) view.findViewById(R.id.button_start_test); startTestBut.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Snackbar.make(v, R.string.notice_start_test, Snackbar.LENGTH_LONG) .setAction("Action", null).show(); startTestBut.setVisibility(View.INVISIBLE); InputMethodManager imm = (InputMethodManager) Daedalus.getInstance().getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(v.getWindowToken(), 0); textViewTestInfo.setText(""); if (mThread == null) { mThread = new Thread(mRunnable); mThread.start(); } } }); mHandler = new DnsTestHandler(); mHandler.setViews(startTestBut, textViewTestInfo); return view; } @Override public void checkStatus() { menu.findItem(R.id.nav_dns_test).setChecked(true); toolbar.setTitle(R.string.action_dns_test); } @Override public void onDestroy() { super.onDestroy(); stopThread(); mHandler.removeCallbacks(mRunnable); mRunnable = null; mHandler.shutdown(); mHandler = null; } private static void stopThread() { try { if (mThread != null) { mThread.interrupt(); mThread = null; } } catch (Exception ignored) { } } private static class DnsTestHandler extends Handler { static final int MSG_DISPLAY_STATUS = 0; static final int MSG_TEST_DONE = 1; private Button startTestBtn = null; private TextView textViewTestInfo = null; void setViews(Button startTestButton, TextView textViewTestInfo) { this.startTestBtn = startTestButton; this.textViewTestInfo = textViewTestInfo; } void shutdown() { startTestBtn = null; textViewTestInfo = null; } public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case MSG_DISPLAY_STATUS: if (MainActivity.getInstance().getCurrentFragment() == MainActivity.FRAGMENT_DNS_TEST) { textViewTestInfo.setText((String) msg.obj); } break; case MSG_TEST_DONE: if (MainActivity.getInstance().getCurrentFragment() == MainActivity.FRAGMENT_DNS_TEST) { startTestBtn.setVisibility(View.VISIBLE); } stopThread(); break; } } } private class DNSQuery extends NetworkDataSource { public DNSMessage query(DNSMessage message, InetAddress address, int port) throws IOException { return queryUdp(message, address, port); } } }