// metadata here is user's network type device used geolocation if permitted etc
// Google storage forbids to store user related data
// So we send that data to a private server
@Override
        protected Void doInBackground(String... args) {
            if (isCancelled()) {
                return null;
            }
            // TODO subscribe to network events instead of using this
            if (!networkAvailable) {
                Toast.makeText(
                        context,
                        getString(R.string.toast_nonetwork),
                        Toast.LENGTH_LONG).show();
            } else {
                // TODO remove this but with caution
                updateUIBean = new UpdateUIBean();
                // TODO to test different configs change the files poiting by CONFIG_FILE
                //  avoid changing the code directly
                Config.readConfigFile(ReplayConstants.CONFIG_FILE, context);
                SharedPreferences sharedPrefs =
                        PreferenceManager.getDefaultSharedPreferences(context);
                try {
                    // metadata here is user's network type device used geolocation if permitted etc
                    // Google storage forbids to store user related data
                    // So we send that data to a private server
                    server = sharedPrefs.getString("pref_server", "wehe2.meddle.mobi");
                    metadataServer = "wehe-metadata.meddle.mobi";
                    // We first resolve the IP of the server and then communicate with the server
                    // Using IP only, because we have multiple server under same domain and we want
                    // the client not to switch server during a test run
                    // TODO come up with a better way to handle Inet related queries, since this
                    //  introduced inefficiency
                    final InetAddress[] address = {null, null};
                    new Thread() {
                        public void run() {
                            while (!(address[0] instanceof Inet4Address || address[0] instanceof Inet6Address)) {
                                try {
                                    server = InetAddress.getByName(server).getHostAddress();
                                    address[0] = InetAddress.getByName(server);
                                } catch (UnknownHostException e) {
                                    Log.w("GetReplayServerIP", "get IP of replay server failed!");
                                    e.printStackTrace();
                                }
                            }
                        }
                    }.start();
                    new Thread() {
                        public void run() {
                            while (!(address[1] instanceof Inet4Address || address[1] instanceof Inet6Address)) {
                                try {
                                    metadataServer = InetAddress.getByName(metadataServer).getHostAddress();
                                    address[1] = InetAddress.getByName(metadataServer);
                                } catch (UnknownHostException e) {
                                    Log.w("GetReplayServerIP", "get IP of replay server failed!");
                                    e.printStackTrace();
                                }
                            }
                        }
                    }.start();
                    int maxWaitTime = 5000;
                    int currentWaitTime = 500;
                    while (!(address[0] instanceof Inet4Address || address[0] instanceof Inet6Address)
                            && !(address[1] instanceof Inet4Address || address[1] instanceof Inet6Address)) {
                        try {
                            if (currentWaitTime <= maxWaitTime) {
                                Thread.sleep(currentWaitTime);
                                currentWaitTime += 500;
                            } else {
                                Toast.makeText(context, R.string.server_unavailable,
                                        Toast.LENGTH_LONG).show();
                                return null;
                            }
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    if (address[0] instanceof Inet6Address)
                        server = "[" + server + "]";
                    if (address[1] instanceof Inet6Address)
                        metadataServer = "[" + metadataServer + "]";
                    try {
                        CertificateFactory cf = CertificateFactory.getInstance("X.509");
                        Certificate ca;
                        try (InputStream caInput = getResources().openRawResource(R.raw.main)) {
                            ca = cf.generateCertificate(caInput);
                            System.out.println("main=" + ((X509Certificate) ca).getIssuerDN());
                        }
                        // Create a KeyStore containing our trusted CAs
                        String keyStoreType = KeyStore.getDefaultType();
                        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
                        keyStore.load(null, null);
                        keyStore.setCertificateEntry("main", ca);
                        // Create a TrustManager that trusts the CAs in our KeyStore
                        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
                        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
                        tmf.init(keyStore);
                        // Create an SSLContext that uses our TrustManager
                        SSLContext context = SSLContext.getInstance("TLS");
                        context.init(null, tmf.getTrustManagers(), null);
                        sslSocketFactory = context.getSocketFactory();
                        hostnameVerifier = (hostname, session) -> true;
                    } catch (CertificateException e) {
                        e.printStackTrace();
                    } catch (NoSuchAlgorithmException e) {
                        e.printStackTrace();
                    } catch (KeyStoreException e) {
                        e.printStackTrace();
                    } catch (KeyManagementException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    try {
                        CertificateFactory cf = CertificateFactory.getInstance("X.509");
                        Certificate ca;
                        try (InputStream caInput = getResources().openRawResource(R.raw.metadata)) {
                            ca = cf.generateCertificate(caInput);
                            System.out.println("metadata=" + ((X509Certificate) ca).getIssuerDN());
                        }
                        // Create a KeyStore containing our trusted CAs
                        String keyStoreType = KeyStore.getDefaultType();
                        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
                        keyStore.load(null, null);
                        keyStore.setCertificateEntry("metadata", ca);
                        // Create a TrustManager that trusts the CAs in our KeyStore
                        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
                        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
                        tmf.init(keyStore);
                        // Create an SSLContext that uses our TrustManager
                        SSLContext context = SSLContext.getInstance("TLS");
                        context.init(null, tmf.getTrustManagers(), null);
                        metadataSocketFactory = context.getSocketFactory();
                    } catch (CertificateException e) {
                        e.printStackTrace();
                    } catch (NoSuchAlgorithmException e) {
                        e.printStackTrace();
                    } catch (KeyStoreException e) {
                        e.printStackTrace();
                    } catch (KeyManagementException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    Log.d("GetReplayServerIP", "Server IP: " + server);
                } catch (NullPointerException e) {
                    e.printStackTrace();
                    Log.w("GetReplayServerIP", "Invalid IP address!");
                }
                // Extract data that was sent by previous activity. In our case, list of
                // apps, server and timing
                enableTiming = "true";
                doTest = false;
                int port = Integer.valueOf(Config.get("result_port"));
                analyzerServerUrl = ("https://" + server + ":" + port + "/Results");
                date = new Date();
                results = new JSONArray();
                Log.d("Result Channel",
                        "path: " + server + " port: " + port);
                confirmationReplays = sharedPrefs.getBoolean("confirmationReplays", true);
                // generate or retrieve an id for this phone
                boolean hasID = sharedPrefs.getBoolean("hasID", false);
                if (!hasID) {
                    randomID = new RandomString(10).nextString();
                    SharedPreferences.Editor editor = sharedPrefs.edit();
                    editor.putBoolean("hasID", true);
                    editor.putString("ID", randomID);
                    editor.apply();
                } else {
                    randomID = sharedPrefs.getString("ID", null);
                }
                a_threshold = Integer.parseInt(Objects.requireNonNull(sharedPrefs.getString("pref_threshold_area", "10")));
                ks2pvalue_threshold = Integer.parseInt(Objects.requireNonNull(sharedPrefs.getString("pref_threshold_ks2p", "5")));
                confirmationReplays = sharedPrefs.getBoolean("pref_multiple_tests", true);
                // to get historyCount
                settings = getSharedPreferences(STATUS, Context.MODE_PRIVATE);
                // generate or retrieve an historyCount for this phone
                boolean hasHistoryCount = settings.getBoolean("hasHistoryCount", false);
                if (!hasHistoryCount) {
                    historyCount = 0;
                    SharedPreferences.Editor editor = settings.edit();
                    editor.putBoolean("hasHistoryCount", true);
                    editor.putInt("historyCount", historyCount);
                    editor.apply();
                } else {
                    historyCount = settings.getInt("historyCount", -1);
                }
                // check if retrieve historyCount succeeded
                if (historyCount == -1)
                    throw new RuntimeException();
                Config.set("timing", enableTiming);
                // make sure server is initialized!
                while (server == null) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                Config.set("server", server);
                Config.set("jitter", "true");
                Config.set("publicIP", "");
                new Thread(new Runnable() {
                    public void run() {
                        Config.set("publicIP", getPublicIP("80"));
                    }
                }).start();
                // Find a way to switch to no wait
                while (Config.get("publicIP").equals("")) {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                Log.d("Replay", "public IP: " + Config.get("publicIP"));
            }
            for (ApplicationBean app : selectedApps) {
                rerun = false;
                // Set the app to run test for
                this.app = app;
                // Run the test on this.app
                runTest();
            }
            // Keep checking if the user exited from ReplayActivity or not
            // TODO find a better way stop the tests immediately without continues checking
            if (isCancelled()) {
                return null;
            }
            if (results.length() > 0) {
                Log.d("Result Channel", "Storing results");
                saveResults();
            }
            if (isCancelled()) {
                return null;
            }
            showFinishDialog();
            Log.d("Result Channel", "Exiting normally");
            return null;
        }
PreferenceManager.getDefaultSharedPreferences(context);
try {
// metadata here is user's network type device used geolocation if permitted etc
// Google storage forbids to store user related data
// So we send that data to a private server
server = sharedPrefs.getString("pref_server", "wehe2.meddle.mobi");
metadataServer = "wehe-metadata.meddle.mobi";
Toast.LENGTH_LONG).show();
} else {
// TODO remove this but with caution
updateUIBean = new UpdateUIBean();
// TODO to test different configs change the files poiting by CONFIG_FILE
// avoid changing the code directly
Config.readConfigFile(ReplayConstants.CONFIG_FILE, context);
SharedPreferences sharedPrefs =
PreferenceManager.getDefaultSharedPreferences(context);
try {
// metadata here is user's network type device used geolocation if permitted etc
// Google storage forbids to store user related data
// So we send that data to a private server
server = sharedPrefs.getString("pref_server", "wehe2.meddle.mobi");
metadataServer = "wehe-metadata.meddle.mobi";
// We first resolve the IP of the server and then communicate with the server
// Using IP only, because we have multiple server under same domain and we want
// the client not to switch server during a test run
// TODO come up with a better way to handle Inet related queries, since this
// introduced inefficiency
final InetAddress[] address = {null, null};
new Thread() {
public void run() {
@Override
protected Void doInBackground(String... args) {
if (isCancelled()) {
return null;
}
// TODO subscribe to network events instead of using this
if (!networkAvailable) {
Toast.makeText(
context,
getString(R.string.toast_nonetwork),
Toast.LENGTH_LONG).show();
} else {
// TODO remove this but with caution
updateUIBean = new UpdateUIBean();
// TODO to test different configs change the files poiting by CONFIG_FILE
// avoid changing the code directly
Config.readConfigFile(ReplayConstants.CONFIG_FILE, context);
SharedPreferences sharedPrefs =
PreferenceManager.getDefaultSharedPreferences(context);
try {
// metadata here is user's network type device used geolocation if permitted etc
// Google storage forbids to store user related data
// So we send that data to a private server
server = sharedPrefs.getString("pref_server", "wehe2.meddle.mobi");
metadataServer = "wehe-metadata.meddle.mobi";
// We first resolve the IP of the server and then communicate with the server
// Using IP only, because we have multiple server under same domain and we want
// the client not to switch server during a test run
// TODO come up with a better way to handle Inet related queries, since this
// introduced inefficiency
final InetAddress[] address = {null, null};
new Thread() {
public void run() {
while (!(address[0] instanceof Inet4Address || address[0] instanceof Inet6Address)) {
try {
server = InetAddress.getByName(server).getHostAddress();
address[0] = InetAddress.getByName(server);
} catch (UnknownHostException e) {
Log.w("GetReplayServerIP", "get IP of replay server failed!");
e.printStackTrace();
}
}
}