/* * VANETsim open source project - http://www.vanet-simulator.org * Copyright (C) 2008 - 2013 Andreas Tomandl, Florian Scheuer, Bernhard Gruber * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package vanetsim.gui.helpers; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.DataInputStream; import java.io.FileInputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.StringReader; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import javax.swing.JOptionPane; import vanetsim.localization.Messages; public class LogOperations extends Thread { /** interface between dialog and operations */ LogAnalyser logAnalyser_; /** type of operation */ private String operation_ = ""; /** variable to save loaded log */ private static String[] savedLog = new String[2]; /** variable to save loaded advanced-log */ private static String[] savedAdvancedLog = new String[2]; /** variable to save silent period header */ private static String silentPeriodHeader; /** variable to save to advanced location information */ private String locationInformation_ = ""; public LogOperations(LogAnalyser logAnalyser){ logAnalyser_ = logAnalyser; } public void run(){ //start analyzing (the attack type has to be set before) if(operation_.equals("MixStandard")) standardAttackMixZones(); else if(operation_.equals("MixAdvanced")) advancedAttackMixZones(); else if(operation_.equals("SilentStandard")) standardAttackSilentPeriod(); else if(operation_.equals("SilentAdvanced")) advancedAttackSilentPeriod(); else if(operation_.equals("SlowStandard")) standardAttackSlow(); //else if(operation_.equals("SlowAdvanced")) advancedAttackSlow(); logAnalyser_.guiControl("startBtn", true); logAnalyser_.guiControl("stopBtn", false); logAnalyser_.guiControl("progressBar", false); logAnalyser_.guiControl("copyBtn", true); //start next job logAnalyser_.startNextJob(false); } /** * Standard attack for mix-zones */ public void standardAttackMixZones(){ logAnalyser_.updateProgressBar(0); logAnalyser_.updateInformationArea(0, 0, false); //hash map to follow vehicles through more mix zones HashMap<String,String> successLog = new HashMap<String,String>(); logAnalyser_.updateProgressBar(5); //save and load data (analysis will be faster the second time, e.g. after changing variables) if(logAnalyser_.isFilePathChanged()){ savedLog = readFileAndHeader(logAnalyser_.getActualJob()); logAnalyser_.setFilePathChanged(false); } logAnalyser_.updateProgressBar(10); //check if we have a correct log -> if yes quit analysis if(savedLog[0] == null || savedLog[1] == null || !savedLog[0].substring(0, 8).equals("Mix-Zone")){ JOptionPane.showMessageDialog(null, Messages.getString("LogOperations.WrongLogType"), "Error", JOptionPane.ERROR_MESSAGE); return; } writeLocationInformationToFile(savedLog[0] + "******************\n", false); String[] mixZoneHeaderArray = savedLog[0].split("\n"); int numberOfMixZones = mixZoneHeaderArray.length; //variables for statistics int[] numberOfVehicles = new int[numberOfMixZones]; int[] numberOfCorrectVehicles = new int[numberOfMixZones]; int numberOfVehiclesTotal = 0; int numberOfCorrectVehiclesTotal = 0; System.out.println("file loaded..."); //temp line variable String line = ""; //variable to save split line of log (":") String[] logData; //index of log data (useful if log structure changes) int timestamp = 0; int steadyID = 2; int nodeID = 10; int direction = 12; int streetName = 14; int streetSpeed = 16; int port = 20; //values for variables set in GUI double timeBufferValue = logAnalyser_.getGuiElement("timeBufferValue"); double biggerStreetValue = 1-logAnalyser_.getGuiElement("biggerStreetValue"); double tuneTimeValue = logAnalyser_.getGuiElement("tuneTimeValue"); double smallerStreetValue = 1-logAnalyser_.getGuiElement("smallerStreetValue"); double drivesStraigthValue = 1-logAnalyser_.getGuiElement("drivesStraigthValue"); double turnsValue = 1-logAnalyser_.getGuiElement("turnsValue"); double makesUTurnValue = 1-logAnalyser_.getGuiElement("makesUTurnValue"); //initializing variables int nodeRadius = 0; double expectedTime = 0; String savedSteadyID = ""; double savedFactor = 0; double streetFactor = 0; double drivingFactor = 0; double factor = 0; int numberTotal = 0; int numberSuccessInRow = 0; //variables for the progressbar long amountOfLines = savedLog[1].split("\n").length; long updateEveryNLine = amountOfLines/80; long counter = 0; if(updateEveryNLine == 0) updateEveryNLine = 1; BufferedReader reader = new BufferedReader(new StringReader(savedLog[1])); try { //read vehicle data line by line and check every vehicle while ((line = reader.readLine()) != null) { counter++; //update progressbar if(counter%updateEveryNLine == 0) logAnalyser_.addToProgressBar(1); if (line.length() > 0){ //get log data of the vehicle we want to check now logData = line.split(":"); if(logData != null && logData.length > 18){ //only attack vehicles which drive into a mix zone if(logData[direction].equals("IN")){ //counter for all vehicles numberOfVehiclesTotal++; //update vehicle counter of the current mix zone for(int i = 0; i < numberOfMixZones; i++){ if(logData[nodeID].equals(mixZoneHeaderArray[i].split(":")[2])) numberOfVehicles[i]++; } //returns to node radius of the mix zone nodeRadius = getNodeRadius(logData[nodeID], savedLog[0]); //expected time to leave mix zone in ms (use tuneTimeValue to influence this time) expectedTime = (((2*nodeRadius)/Integer.parseInt(logData[streetSpeed]))*1000)*tuneTimeValue; //now check every vehicle that left the mix zone in the time (expectedTime + buffer) //set mark for reader (performance tweak, we can resume our buffer on this position later) reader.mark(savedLog[1].length()); //tmp variable to save steadyID and the factor savedSteadyID = ""; savedFactor = 999999999; try { //read vehicle data line by line while ((line = reader.readLine()) != null) { String[] logData2 = line.split(":"); //we only check vehicles until a selected time (performance tweak, calculated expected time + buffer) if((Integer.parseInt(logData[timestamp]) + expectedTime + timeBufferValue) < Integer.parseInt(logData2[timestamp])){ break; } //only check vehicles that leave the same mix-zone if(logData[nodeID].equals(logData2[nodeID]) && logData2[direction].equals("OUT")){ streetFactor = 0; drivingFactor = 0; //calculate the right factors if(logData[streetName].equals(logData2[streetName])){ if(logData[port].equals(logData2[port])){ drivingFactor = makesUTurnValue; } else drivingFactor = drivesStraigthValue; } else{ drivingFactor = turnsValue; } if(Integer.parseInt(logData[streetSpeed]) > Integer.parseInt(logData2[streetSpeed])){ streetFactor = smallerStreetValue; } else{ streetFactor = biggerStreetValue; } //calculate factor: if(drivingFactor == 0) drivingFactor = 0.0000000000000000000000000001; if(streetFactor == 0) streetFactor = 0.0000000000000000000000000001; factor = drivingFactor * streetFactor * Math.abs(((Integer.parseInt(logData[timestamp]) + expectedTime) - Integer.parseInt(logData2[timestamp]))); //always save the smallest vehicle with the smallest factor if(factor < savedFactor){ savedFactor = factor; savedSteadyID = logData2[steadyID]; } } } } catch(IOException e) { System.out.println("Error while doing standard attack"); e.printStackTrace(); } //jump to mark reader.reset(); //update states to log the movement of vehicles through more mix-zones. Format: Number:Number:Boolean -> NumberOfPassedMixZones:NumerOfSuccessfulPassedZones(only in a row):BooleanValueToShowIfVehicleWasFollowedCorrectlyUntilNow String[] successData = {"0","0","true"}; if(successLog.get(logData[steadyID]) != null) successData = successLog.get(logData[steadyID]).split(":"); numberTotal = Integer.parseInt(successData[0]); numberSuccessInRow = Integer.parseInt(successData[1]); if(savedSteadyID.equals(logData[steadyID])){ locationInformation_ += "true:" + logData[nodeID] + ":" + logData[port] + "\n"; successLog.remove(logData[steadyID]); if(successData[2].equals("true")) { successLog.put(logData[steadyID], (numberTotal+1) + ":" + (numberSuccessInRow+1) + ":true"); } else{ successLog.put(logData[steadyID], (numberTotal+1) + ":" + numberSuccessInRow + ":false"); } for(int i = 0; i < numberOfMixZones; i++){ if(logData[nodeID].equals(mixZoneHeaderArray[i].split(":")[2]))numberOfCorrectVehicles[i]++; } numberOfCorrectVehiclesTotal++; } else{ locationInformation_ += "false:" + logData[nodeID] + ":" + logData[port] + "\n"; successLog.remove(logData[steadyID]); successLog.put(logData[steadyID], (numberTotal+1) + ":" + numberSuccessInRow + ":false"); } //update status field in GUI if(numberOfVehiclesTotal%10 == 0)logAnalyser_.updateInformationArea(numberOfVehiclesTotal, numberOfCorrectVehiclesTotal, false); } } } } } catch(IOException e) { System.out.println("Error while doing standard attack"); e.printStackTrace(); } logAnalyser_.updateInformationArea(numberOfVehiclesTotal, numberOfCorrectVehiclesTotal, true); int maxOfRow = 0; //calculate max crossed mix zones for(Map.Entry<String, String> e : successLog.entrySet()){ if(maxOfRow < Integer.parseInt(e.getValue().split(":")[0])) maxOfRow = Integer.parseInt(e.getValue().split(":")[0]); } maxOfRow++; int[][] dataCollection = new int[maxOfRow][maxOfRow]; //calculate advanced states //long vehiclesTotal = 0; for(Map.Entry<String, String> e : successLog.entrySet()){ //vehiclesTotal++; dataCollection[Integer.parseInt(e.getValue().split(":")[0])][Integer.parseInt(e.getValue().split(":")[1])] = dataCollection[Integer.parseInt(e.getValue().split(":")[0])][Integer.parseInt(e.getValue().split(":")[1])] + 1; } logAnalyser_.updateInformationArea("\n\n", false); logAnalyser_.updateInformationArea("#GNU-Plot Data Simple\n", true); logAnalyser_.updateInformationArea("#Privacy VehiclesTotal Probabilities k-Anonymity\n", true); //calculate anonymity set for the silent period and log the results float[] kAnonymityValues = new float[numberOfMixZones]; float numberOfVeh = 0; float numberOfCorrVeh = 0; float numberOfKAnoVehTotal = 0; float numberOfKAnoVeh = 0; float[] tmpKAno = null; for(int i = 0; i < mixZoneHeaderArray.length; i++){ tmpKAno = getKAnonymityInMix(mixZoneHeaderArray[i].split(":")[2],savedLog[1]); kAnonymityValues[i] = tmpKAno[0]; numberOfKAnoVehTotal += tmpKAno[1]; numberOfKAnoVeh += tmpKAno[2]; numberOfVeh += numberOfVehicles[i]; numberOfCorrVeh += numberOfCorrectVehicles[i]; logAnalyser_.updateInformationArea("Mix-Zone" + (i+1) + " " + numberOfVehicles[i] + " " + (float)100*numberOfCorrectVehicles[i]/numberOfVehicles[i] + " " + kAnonymityValues[i] + "\n", true); } logAnalyser_.updateInformationArea("Total " + numberOfVeh + " " + (numberOfCorrVeh*100/numberOfVeh) + " " + (numberOfKAnoVehTotal/numberOfKAnoVeh) + "\n", true); logAnalyser_.writeResultsToFile("simple"); logAnalyser_.updateInformationArea("\n\n", false); logAnalyser_.updateInformationArea("#GNU-Plot Data Detail\n", true); logAnalyser_.updateInformationArea("#Success/Crossed", true); for(int i = 1; i < maxOfRow; i++) logAnalyser_.updateInformationArea(" " + i, true); logAnalyser_.updateInformationArea(" VehiclesLeft", true); //float tmpSumLine = 0; //float vehiclesTotal2 = 0; for(int l = 0; l < maxOfRow;l++){ logAnalyser_.updateInformationArea("\n" + l, true); for(int m = 1; m < maxOfRow;m++){ //tmpSumLine += dataCollection[m][l]; logAnalyser_.updateInformationArea(" " + dataCollection[m][l], true); } //this is the old version of the detailed calculator. Now there is a script -> accumulateDetailedLogFiles() in ReportingControlPanel /* if(l == 0){ logAnalyser_.updateInformationArea(" " + (tmpSumLine/vehiclesTotal), true); } else if(l == 1){ logAnalyser_.updateInformationArea(" " + (tmpSumLine/vehiclesTotal), true); } else{ vehiclesTotal2 = vehiclesTotal; for(int n = 0; n < l;n++){ for(int o = 1; o < l;o++){ vehiclesTotal2 -= dataCollection[o][n]; } } logAnalyser_.updateInformationArea(" " + (tmpSumLine/vehiclesTotal2), true); } tmpSumLine = 0; */ } logAnalyser_.updateProgressBar(100); logAnalyser_.guiControl("progressBar", false); logAnalyser_.updateProgressBar(0); logAnalyser_.writeResultsToFile("detail"); writeLocationInformationToFile(null, true); } /** * Advanced attack for mix-zones */ public void advancedAttackMixZones(){ logAnalyser_.updateProgressBar(0); logAnalyser_.updateInformationArea(0, 0, false); //hash map to follow vehicles through more mix zones HashMap<String,String> successLog = new HashMap<String,String>(); //analyse traffic first logAnalyser_.updateProgressBar(5); //save and load data (analysis will be faster the second time, e.g. after changing variables) if(logAnalyser_.isAdvancedFilePathChanged()){ savedAdvancedLog = readFileAndHeader(logAnalyser_.getAdvancedFilePath_()); logAnalyser_.setAdvancedFilePathChanged(false); } //check if there is a correct header and log is cleaned if(savedAdvancedLog.length < 2){ JOptionPane.showMessageDialog(null, Messages.getString("LogOperations.LogsNeedsCleaning"), "Error", JOptionPane.ERROR_MESSAGE); return; } //check if we have a correct log -> if yes quit analysis if(savedAdvancedLog[0] == null || savedAdvancedLog[1] == null || !savedAdvancedLog[0].substring(0, 8).equals("Mix-Zone")){ JOptionPane.showMessageDialog(null, Messages.getString("LogOperations.WrongLogType"), "Error", JOptionPane.ERROR_MESSAGE); return; } logAnalyser_.updateProgressBar(10); //Hash Map for traffic data about the mix zones HashMap<String,Object[]> trafficDataMap = new HashMap<String,Object[]>(); //analyse all mix zones if second log String tmpHeaders[] = savedAdvancedLog[0].split("\n"); for(int i = 0; i < tmpHeaders.length; i++){ String[] tmpHeader = tmpHeaders[i].split(":"); trafficDataMap.put(tmpHeader[2], getDataOfMixZoneLog(savedAdvancedLog, tmpHeader[2], tmpHeaders.length)); } Object[] tmpObject = null; if(logAnalyser_.isFilePathChanged()){ savedLog = readFileAndHeader(logAnalyser_.getActualJob()); logAnalyser_.setFilePathChanged(false); } //check if we have a correct log -> if yes quit analysis if(savedLog[0] == null || savedLog[1] == null || !savedLog[0].substring(0, 8).equals("Mix-Zone")){ JOptionPane.showMessageDialog(null, Messages.getString("LogOperations.WrongLogType"), "Error", JOptionPane.ERROR_MESSAGE); return; } writeLocationInformationToFile(savedLog[0] + "******************\n", false); System.out.println("file loaded..."); //tmp variable for read lines String line = ""; //variable for split log line String[] logData; String[] logData2; //variables for statistics String[] mixZoneHeaderArray = savedLog[0].split("\n"); int numberOfMixZones = mixZoneHeaderArray.length; int[] numberOfVehicles = new int[numberOfMixZones]; int[] numberOfCorrectVehicles = new int[numberOfMixZones]; int numberOfVehiclesTotal = 0; int numberOfCorrectVehiclesTotal = 0; //index of log data (useful if log structure changes) int timestamp = 0; int steadyID = 2; int nodeID = 10; int direction = 12; int port = 20; //values for variables set in gui double timeBufferValue = logAnalyser_.getGuiElement("timeBufferValue"); //variables String savedSteadyID =""; double savedFaktor = 0; int maxExpectedTime = 0; double factor = 1; //variables for the progressbar long amountOfLines = savedLog[1].split("\n").length; long updateEveryNLine = amountOfLines/50; long counter = 0; BufferedReader reader = new BufferedReader(new StringReader(savedLog[1])); try { //read vehicle data line by line while ((line = reader.readLine()) != null) { counter++; //update progress bar if(counter%updateEveryNLine ==0) logAnalyser_.addToProgressBar(1); if (line.length() > 0){ logData = line.split(":"); if(logData != null && logData.length > 18){ //only attack vehicles which drive into a mix zone if(logData[direction].equals("IN")){ //counter for all vehicles numberOfVehiclesTotal++; for(int i = 0; i < numberOfMixZones; i++){ if(logData[nodeID].equals(mixZoneHeaderArray[i].split(":")[2])) numberOfVehicles[i]++; } tmpObject = trafficDataMap.get(logData[nodeID]); //now check every vehicle that left the mix zone in the timespan (expectedTime + buffer) //set mark for reader (performance tweak, we can resume our buffer on this position later) reader.mark(savedLog[1].length()); savedSteadyID = ""; savedFaktor = 999999999; try { //read vehicle data line by line while ((line = reader.readLine()) != null) { logData2 = line.split(":"); maxExpectedTime = 0; //get max expected time (searches through all possible combinations of entrances and exits for(int i = 0; i < ((int[][])tmpObject[0]).length; i++){ for(int j = 0; j< ((int[][])tmpObject[0]).length; j++){ if(maxExpectedTime < ((int[][])tmpObject[0])[i][j]) maxExpectedTime = ((int[][])tmpObject[0])[i][j]; } } //we only check vehicles until a selected time (performance tweak, calculated expected time + buffer) if((Integer.parseInt(logData[timestamp]) + maxExpectedTime + timeBufferValue) < Integer.parseInt(logData2[timestamp])){ break; } //only check vehicles that leave the same mix-zone if(logData2[direction].equals("OUT") && logData2[nodeID].equals(logData[nodeID])){ //calculate the right factors factor = 1; //if that in GUI use also the calculated probabilities for this mix zone if(logAnalyser_.isProbabilitiesOn()){ factor = ((double)1- ((double[][])tmpObject[1])[Integer.parseInt(logData[port])-1][Integer.parseInt(logData2[port])-1]) * Math.abs(((Integer.parseInt(logData[timestamp]) + ((int[][])tmpObject[0])[Integer.parseInt(logData[port])-1][Integer.parseInt(logData2[port])-1]) - Integer.parseInt(logData2[timestamp]))) ; } //use the expected path of this mix zone to calculate the factor (the smaller the better) factor += Math.abs(((Integer.parseInt(logData[timestamp]) + ((int[][])tmpObject[0])[Integer.parseInt(logData[port])-1][Integer.parseInt(logData2[port])-1]) - Integer.parseInt(logData2[timestamp]))); //always save the smallest factor if(factor < savedFaktor){ savedFaktor = factor; savedSteadyID = logData2[steadyID]; } } } } catch(IOException e) { System.out.println("Error while doing advanced attack"); e.printStackTrace(); } //jump to mark reader.reset(); //update states to log the movement of vehicles through more mix-zones. Format: Number:Number:Boolean -> NumberOfPassedMixZones:NumerOfSuccessfulPassedZones(only in a row):BooleanValueToShowIfVehicleWasFollowedCorrectlyUntilNow String[] successData = {"0","0","true"}; if(successLog.get(logData[steadyID]) != null) successData = successLog.get(logData[steadyID]).split(":"); int numberTotal = Integer.parseInt(successData[0]); int numberSuccessInRow = Integer.parseInt(successData[1]); if(savedSteadyID.equals(logData[steadyID])){ locationInformation_ += "true:" + logData[nodeID] + ":" + logData[port] + "\n"; successLog.remove(logData[steadyID]); if(successData[2].equals("true")) { successLog.put(logData[steadyID], (numberTotal+1) + ":" + (numberSuccessInRow+1) + ":true"); } else{ successLog.put(logData[steadyID], (numberTotal+1) + ":" + numberSuccessInRow + ":false"); } for(int i = 0; i < numberOfMixZones; i++){ if(logData[nodeID].equals(mixZoneHeaderArray[i].split(":")[2]))numberOfCorrectVehicles[i]++; } numberOfCorrectVehiclesTotal++; } else{ locationInformation_ += "false:" + logData[nodeID] + ":" + logData[port] + "\n"; successLog.remove(logData[steadyID]); successLog.put(logData[steadyID], (numberTotal+1) + ":" + numberSuccessInRow + ":false"); } //update status field in GUI if(numberOfVehiclesTotal%10 == 0)logAnalyser_.updateInformationArea(numberOfVehiclesTotal, numberOfCorrectVehiclesTotal, false); } } } } } catch(IOException e) { System.out.println("Error while doing advanced attack"); e.printStackTrace(); } if(numberOfVehiclesTotal%10 == 0)logAnalyser_.updateInformationArea(numberOfVehiclesTotal, numberOfCorrectVehiclesTotal, false); int maxOfRow = 0; //calculate max crossed mix zones for(Map.Entry<String, String> e : successLog.entrySet()){ if(maxOfRow < Integer.parseInt(e.getValue().split(":")[0])) maxOfRow = Integer.parseInt(e.getValue().split(":")[0]); } maxOfRow++; int[][] dataCollection = new int[maxOfRow][maxOfRow]; //calculate advanced stats //float vehiclesTotal = 0; for(Map.Entry<String, String> e : successLog.entrySet()){ //vehiclesTotal++; dataCollection[Integer.parseInt(e.getValue().split(":")[0])][Integer.parseInt(e.getValue().split(":")[1])] = dataCollection[Integer.parseInt(e.getValue().split(":")[0])][Integer.parseInt(e.getValue().split(":")[1])] + 1; } //calculate entropy and kAnonymity float entroTotal = 0; float numberOfVeh = 0; float numberOfCorrVeh = 0; float numberOfKAnoVehTotal = 0; float numberOfKAnoVeh = 0; float[] tmpKAno = null; float[] kAnonymityValues = new float[numberOfMixZones]; logAnalyser_.updateInformationArea("\n\n", false); logAnalyser_.updateInformationArea("#GNU-Plot Data Simple\n", true); logAnalyser_.updateInformationArea("Privacy TotalVehicles Probabilities k-Anonymity Entropy\n", true); for(int i = 0; i < tmpHeaders.length; i++){ //k-Anonymity String[] tmpHeader = tmpHeaders[i].split(":"); tmpKAno = getKAnonymityInMix(mixZoneHeaderArray[i].split(":")[2],savedLog[1]); kAnonymityValues[i] = tmpKAno[0]; numberOfKAnoVehTotal += tmpKAno[1]; numberOfKAnoVeh += tmpKAno[2]; numberOfVeh += numberOfVehicles[i]; numberOfCorrVeh += numberOfCorrectVehicles[i]; //Entropy tmpObject = trafficDataMap.get(tmpHeader[2]); double[][] probabilties = (double[][]) tmpObject[1]; float probabiltiesTotal = 0; float totalProbabilities = 0; for(int m = 0; m < probabilties.length;m++){ for(int n = 0; n < probabilties.length;n++){ totalProbabilities += probabilties[m][n]; } } for(int m = 0; m < probabilties.length;m++){ for(int n = 0; n < probabilties.length;n++){ if(probabilties[m][n] > 0) probabiltiesTotal += (probabilties[m][n]/totalProbabilities*((float)Math.log10(probabilties[m][n]/totalProbabilities)/Math.log10(2))); } } entroTotal += (numberOfVehicles[i]*-probabiltiesTotal); logAnalyser_.updateInformationArea("Mix-Zone" + (i+1) + " " + numberOfVehicles[i] + " " + (float)100*numberOfCorrectVehicles[i]/numberOfVehicles[i] + " " + kAnonymityValues[i] + " " + -probabiltiesTotal + "\n", true); } logAnalyser_.updateInformationArea("Total " + numberOfVeh + " " + (numberOfCorrVeh*100/numberOfVeh) + " " + (numberOfKAnoVehTotal/numberOfKAnoVeh) + " " + (entroTotal/numberOfVeh) + "\n", true); logAnalyser_.writeResultsToFile("simple"); logAnalyser_.updateInformationArea("\n\n", false); logAnalyser_.updateInformationArea("#GNU-Plot Data Detail\n", true); logAnalyser_.updateInformationArea("#Success/Crossed", true); for(int i = 1; i < maxOfRow; i++) logAnalyser_.updateInformationArea(" " + i, true); logAnalyser_.updateInformationArea(" VehiclesLeft", true); //float tmpSumLine = 0; //float vehiclesTotal2 = 0; for(int l = 0; l < maxOfRow;l++){ logAnalyser_.updateInformationArea("\n" + l, true); for(int m = 1; m < maxOfRow;m++){ //tmpSumLine += dataCollection[m][l]; logAnalyser_.updateInformationArea(" " + dataCollection[m][l], true); } //this is the old version of the detailed calculator. Now there is a script -> accumulateDetailedLogFiles() in ReportingControlPanel /* if(l == 0){ logAnalyser_.updateInformationArea(" " + (tmpSumLine/vehiclesTotal), true); } else if(l == 1){ logAnalyser_.updateInformationArea(" " + (tmpSumLine/vehiclesTotal), true); } else{ vehiclesTotal2 = vehiclesTotal; for(int n = 0; n < l;n++){ for(int o = 1; o < l;o++){ vehiclesTotal2 -= dataCollection[o][n]; } } logAnalyser_.updateInformationArea(" " + (tmpSumLine/vehiclesTotal2), true); } tmpSumLine = 0; */ } logAnalyser_.updateProgressBar(100); logAnalyser_.guiControl("progressBar", false); logAnalyser_.updateProgressBar(0); //save results to file logAnalyser_.writeResultsToFile("detail"); //save location information to file writeLocationInformationToFile(null, true); } public void standardAttackSilentPeriod(){ logAnalyser_.updateProgressBar(1); logAnalyser_.updateInformationArea(0, 0, false); //hash map to follow vehicles through mix zones HashMap<String,String> successLog = new HashMap<String,String>(); //save and load data (analysis will be faster the second time, e.g. after changing variables) if(logAnalyser_.isFilePathChanged()){ savedLog[0] = readFile(logAnalyser_.getActualJob()); logAnalyser_.setFilePathChanged(false); } logAnalyser_.updateProgressBar(1); System.out.println("file loaded..."); //temp variables to iterate through data String line = ""; String[] logData; String[] logData2; //variables for statistics int numberOfVehicles = 0; int numberOfCorrectVehicles = 0; //index of log data (useful if log structure changes) int timestamp = 0; int steadyID = 2; int streetSpeed = 16; int x = 20; int y = 22; //values for variables set in GUI double tuneTimeValue = logAnalyser_.getGuiElement("tuneTimeValue"); String tmpString1 = ""; String tmpString2 = ""; int actualTime = 0; int oldTime = 0; //read time of silent period int silentPeriodTime = 0; //this arrays a just to save the beacons-blocks before and after the silent period String dataOne[] = null; String dataTwo[] = null; //String to save the guessed steadyID String steadyIDSave = ""; //other variables for calculation float x1 = 0; float y1 = 0; float expectedWay = 0; float factor = 0; float dx = 0; float dy = 0; float tmpFactor = 0; String[] successData = null; String[] successDataReset = {"0","0","true"}; int numberTotal = 0; int numberSuccessInRow = 0; boolean firstLine = true; long amountOfLines = savedLog[0].split("\n").length; long updateEveryNLine = amountOfLines/98; long counter2 = 0; writeLocationInformationToFile("Silent Period\n******************\n", false); //variables for kAnonymity und Entropy //constant variable (max. driving speed of a vehicle) double maxDrivingSpeed = 6944.44444444444444444444444444444444444; double maxDistance = 0; double maxDistanceSquared = 0; long vehicleX = 0; long vehicleY = 0; long dx2 = 0; long dy2 = 0; double expectedWay2 = 0; double tmpDistance2 = 0; double tmpDistances = 0; double entropiesAdded = 0; int numberOfCheckedVehicles = 0; long numberOfFoundVehicles = 0; float prob = 0; double distanceInTotal = 0; ArrayList<Double> distances = new ArrayList<Double>(); //if the file path has changed we have to read the log again System.out.println("starting analysing..."); //read file into array separated by silent periods BufferedReader reader = new BufferedReader(new StringReader(savedLog[0])); try { //read vehicle data line by line while ((line = reader.readLine()) != null) { counter2++; //update progress bar if(counter2%updateEveryNLine ==0) logAnalyser_.addToProgressBar(1); //check if it's the correct log type if(firstLine){ firstLine = false; silentPeriodHeader = line; silentPeriodTime = Integer.parseInt(silentPeriodHeader.split(":")[2]); maxDistance = maxDrivingSpeed*(double)(silentPeriodTime/1000); maxDistanceSquared = maxDistance*maxDistance; if(!silentPeriodHeader.substring(0, 8).equals("Silent P")){ JOptionPane.showMessageDialog(null, Messages.getString("LogOperations.WrongLogType"), "Error", JOptionPane.ERROR_MESSAGE); return; } } //split log after every silent period and put data into array list. Even it takes long to split up the data, we get a performance boost later for the attack else{ actualTime = Integer.parseInt(line.split(":")[timestamp]); if(oldTime != 0 && Math.abs(actualTime - oldTime) > 1000){ if(tmpString2.equals("")){ tmpString2 = tmpString1; tmpString1 = ""; } else{ //read the 2 beacon blocks dataOne = tmpString2.split("\n"); dataTwo = tmpString1.split("\n"); steadyIDSave = ""; //iterate through the first block for(int j = 0; j < dataOne.length-1; j+=2){ numberOfVehicles++; //first beacon logData = dataOne[j+1].split(":"); //calculate estimated way x1 = Integer.parseInt(logData[x]); y1 = Integer.parseInt(logData[y]); //calculates how far the vehicle could drive at full speed expectedWay = (float)((float)(silentPeriodTime/1000 * Integer.parseInt(logData[streetSpeed]))*tuneTimeValue); factor = 999999999; //now iterate through the second block for(int k = 0; k < dataTwo.length-1; k+=2){ //read first beacon logData2= dataTwo[k].split(":"); dx = x1 - Integer.parseInt(logData2[x]); dy = y1 - Integer.parseInt(logData2[y]); //calculate distance between estimated and real way (the smaller the better) tmpFactor = Math.abs((expectedWay*expectedWay) -(dx*dx + dy*dy)); //save smallest factor if(factor > tmpFactor) { factor = tmpFactor; steadyIDSave = logData2[steadyID]; } } //update states to log the movement of vehicles through more mix-zones. Format: Number:Number:Boolean -> NumberOfPassedMixZones:NumerOfSuccessfulPassedZones(only in a row):BooleanValueToShowIfVehicleWasFollowedCorrectlyUntilNow successData = successDataReset.clone(); if(successLog.get(logData[steadyID]) != null) successData = successLog.get(logData[steadyID]).split(":"); numberTotal = Integer.parseInt(successData[0]); numberSuccessInRow = Integer.parseInt(successData[1]); if(steadyIDSave.equals(logData[steadyID])){ locationInformation_ += "true:" + logData[x] + ":" + logData[y] + "\n"; successLog.remove(logData[steadyID]); if(successData[2].equals("true")) { successLog.put(logData[steadyID], (numberTotal+1) + ":" + (numberSuccessInRow+1) + ":true"); } else{ successLog.put(logData[steadyID], (numberTotal+1) + ":" + numberSuccessInRow + ":false"); } numberOfCorrectVehicles++; } else{ locationInformation_ += "false:" + logData[x] + ":" + logData[y] + "\n"; successLog.remove(logData[steadyID]); successLog.put(logData[steadyID], (numberTotal+1) + ":" + numberSuccessInRow + ":false"); } if(numberOfVehicles%10 == 0)logAnalyser_.updateInformationArea(numberOfVehicles, numberOfCorrectVehicles, false); } writeLocationInformationToFile(null, true); locationInformation_ = ""; //kAnonymity and entropy for(int j = 0; j < dataOne.length-1; j+=2){ numberOfCheckedVehicles++; logData = dataOne[j+1].split(":"); //calculate expected way using the street speed the silent period time and a gui element to tune the value expectedWay2 = (double)((double)(silentPeriodTime/1000 * Integer.parseInt(logData[streetSpeed]))*tuneTimeValue); tmpDistance2 = maxDistance - expectedWay2; vehicleX = Long.parseLong( logData[x]); vehicleY = Long.parseLong( logData[y]); for(int k = 0; k < dataTwo.length-1; k+=2){ logData2= dataTwo[k].split(":"); dx2 = vehicleX - Long.parseLong(logData2[x]); dy2 = vehicleY - Long.parseLong(logData2[y]); //count all vehicles which are inside the reach of the first vehicle (for anonymity set) and get the distances (to the expected way) to calculate the probabilities later if((dx2*dx2 + dy2*dy2) <= maxDistanceSquared){ tmpDistances = tmpDistance2 - Math.abs(expectedWay2 - Math.sqrt(dx2*dx2 + dy2*dy2)); distanceInTotal += tmpDistances; distances.add(tmpDistances); numberOfFoundVehicles++; } } //get anonymity set and entropy //calculate probabilities for anonymity set. prob = 0; for(Double l: distances){ prob = (float)(l.longValue()/distanceInTotal); if(prob >= 0 && prob < 1)entropiesAdded += ((1-prob)*((float)Math.log10((1-prob))/Math.log10(2))); } distances.clear(); distanceInTotal = 0; } tmpString1 = ""; tmpString2 = ""; } } tmpString1 += line + "\n"; oldTime = actualTime; } } tmpString1 = ""; tmpString2 = ""; } catch(Exception e) { e.printStackTrace(); } logAnalyser_.updateInformationArea(numberOfVehicles, numberOfCorrectVehicles, false); int maxOfRow = 0; //calculate max crossed silent period for(Map.Entry<String, String> e : successLog.entrySet()){ if(maxOfRow < Integer.parseInt(e.getValue().split(":")[0])) maxOfRow = Integer.parseInt(e.getValue().split(":")[0]); } maxOfRow++; int[][] dataCollection = new int[maxOfRow][maxOfRow]; //calculate advanced stats //long vehiclesTotal = 0; for(Map.Entry<String, String> e : successLog.entrySet()){ //vehiclesTotal++; dataCollection[Integer.parseInt(e.getValue().split(":")[0])][Integer.parseInt(e.getValue().split(":")[1])] = dataCollection[Integer.parseInt(e.getValue().split(":")[0])][Integer.parseInt(e.getValue().split(":")[1])] + 1; } float[] kAnoAndEntrArray = {(float)numberOfFoundVehicles/numberOfCheckedVehicles, (float) (-entropiesAdded/numberOfCheckedVehicles)}; logAnalyser_.updateInformationArea("\n\n", false); logAnalyser_.updateInformationArea("#GNU-Plot Data Simple\n", true); logAnalyser_.updateInformationArea("#Privacy Probabilites k-Anonymity Entropy\n", true); logAnalyser_.updateInformationArea("Silent-Period " + (float)100*numberOfCorrectVehicles/numberOfVehicles + " " + kAnoAndEntrArray[0] + " " + kAnoAndEntrArray[1] + "\n", true); logAnalyser_.writeResultsToFile("simple"); logAnalyser_.updateInformationArea("\n\n", false); logAnalyser_.updateInformationArea("#GNU-Plot Data Detail\n", true); logAnalyser_.updateInformationArea("#Success/Crossed", true); for(int i = 1; i < maxOfRow; i++) logAnalyser_.updateInformationArea(" " + i, true); logAnalyser_.updateInformationArea(" VehiclesLeft", true); //float tmpSumLine = 0; //float vehiclesTotal2 = 0; for(int l = 0; l < maxOfRow;l++){ logAnalyser_.updateInformationArea("\n" + l, true); for(int m = 1; m < maxOfRow;m++){ // tmpSumLine += dataCollection[m][l]; logAnalyser_.updateInformationArea(" " + dataCollection[m][l], true); } //this is the old version of the detailed calculator. Now there is a script -> accumulateDetailedLogFiles() in ReportingControlPanel /* if(l == 0){ logAnalyser_.updateInformationArea(" " + (tmpSumLine/vehiclesTotal), true); } else if(l == 1){ logAnalyser_.updateInformationArea(" " + (tmpSumLine/vehiclesTotal), true); } else{ vehiclesTotal2 = vehiclesTotal; for(int n = 0; n < l;n++){ for(int o = 1; o < l;o++){ vehiclesTotal2 -= dataCollection[o][n]; } } logAnalyser_.updateInformationArea(" " + (tmpSumLine/vehiclesTotal2), true); } tmpSumLine = 0; */ } logAnalyser_.updateProgressBar(100); logAnalyser_.guiControl("progressBar", false); logAnalyser_.updateProgressBar(0); //write results to file logAnalyser_.writeResultsToFile("detail"); } /** * advanced attack for silent periods */ public void advancedAttackSilentPeriod(){ logAnalyser_.updateProgressBar(1); logAnalyser_.updateInformationArea(0, 0, false); //hash map to follow vehicles through mix zones HashMap<String,String> successLog = new HashMap<String,String>(); //save and load data (analysis will be faster the second time, e.g. after changing variables) if(logAnalyser_.isFilePathChanged()){ savedLog[0] = readFile(logAnalyser_.getActualJob()); logAnalyser_.setFilePathChanged(false); } logAnalyser_.updateProgressBar(2); writeLocationInformationToFile("Silent Period\n******************\n", false); System.out.println("file loaded..."); //temp variables to iterate through data String line = ""; String[] logData; String[] logData2; String[] logData3; String[] logData4; //variables for statistics int numberOfVehicles = 0; int numberOfCorrectVehicles = 0; //index of log data (useful if log structure changes) int timestamp = 0; int steadyID = 2; int streetSpeed = 16; int x = 20; int y = 22; //values for variables set in GUI double tuneTimeValue = logAnalyser_.getGuiElement("tuneTimeValue"); double limitToAngle = logAnalyser_.getGuiElement("limitToAngle"); String tmpString1 = ""; String tmpString2 = ""; //this arrays a just to save the beacons-blocks before and after the silent period String dataOne[] = null; String dataTwo[] = null; int silentPeriodTime = 0; int actualTime = 0; int oldTime = 0; boolean firstLine = true; //variables for calculation float x1 = 0; float x2 = 0; float y1 = 0; float y2 = 0; double expectedWay = 0; float v1 = 0; float v2 = 0; float normalize = 0; float factor = 999999999; float dx = 0; float dy = 0; float x3 = 0; float x4 = 0; float y3 = 0; float y4 = 0; double vector1x = 0; double vector1y = 0; double vector2x = 0; double vector2y = 0; double vector = 0; double vector2 = 0; double cos = 0; double winkelBogenmass = 0; float tmpFactor = 0; //variables for kAnonymity and Entropy //constant variable (max. driving speed of a vehicle) double maxDrivingSpeed = 6944.44444444444444444444444444444444444; double maxDistance = 0; double maxDistanceSquared = 0; long vehicleX = 0; long vehicleY = 0; long dx2 = 0; long dy2 = 0; double expectedWay2 = 0; int numberOfCheckedVehicles = 0; long numberOfFoundVehicles = 0; double distanceInTotal = 0; ArrayList<Double> distances = new ArrayList<Double>(); double tmpDistance2 = 0; double tmpDistances = 0; double entropiesAdded = 0; float prob = 0; //variables for the progress bar long amountOfLines = savedLog[0].split("\n").length; long updateEveryNLine = amountOfLines/98; long counter2 = 0; //read file into array separated by silent periods BufferedReader reader = new BufferedReader(new StringReader(savedLog[0])); try { while ((line = reader.readLine()) != null) { counter2++; //update progress bar if(counter2%updateEveryNLine ==0) logAnalyser_.addToProgressBar(1); //check if it's the correct log type if(firstLine){ firstLine = false; silentPeriodHeader = line; silentPeriodTime = Integer.parseInt(silentPeriodHeader.split(":")[2]); maxDistance = maxDrivingSpeed*(double)(silentPeriodTime/1000); maxDistanceSquared = maxDistance*maxDistance; if(!silentPeriodHeader.substring(0, 8).equals("Silent P")){ JOptionPane.showMessageDialog(null, Messages.getString("LogOperations.WrongLogType"), "Error", JOptionPane.ERROR_MESSAGE); return; } } //split log after every silent period and put data into array list. Even it takes long to split up the data, we get a performance boost later for the attack else{ actualTime = Integer.parseInt(line.split(":")[timestamp]); if(oldTime != 0 && Math.abs(actualTime - oldTime) > 1000){ if(tmpString2.equals("")){ tmpString2 = tmpString1; tmpString1 = ""; } else{ //read the 2 beacon blocks dataOne = tmpString2.split("\n"); dataTwo = tmpString1.split("\n"); String steadyIDSave = ""; //iterate through the first block for(int j = 0; j < dataOne.length-1; j+=2){ numberOfVehicles++; //first beacon and second beacon (needed to calculate a vector) logData = dataOne[j].split(":"); logData2 = dataOne[j+1].split(":"); //calculate estimated way x1 = Integer.parseInt(logData[x]); x2 = Integer.parseInt(logData2[x]); y1 = Integer.parseInt(logData[y]); y2 = Integer.parseInt(logData2[y]); //calculates how far the vehicle could drive at full speed expectedWay = (double)(silentPeriodTime/1000 * Integer.parseInt(logData2[streetSpeed]))*tuneTimeValue; //calculate vector v1 = x2 - x1; v2 = y2 - y1; normalize = (float) (1/Math.sqrt((double)((v1*v1)+(v2*v2)))); v1 *= normalize * expectedWay; v2 *= normalize * expectedWay; v1 += x2; v2 += y2; factor = 999999999; //now iterate through the second block for(int k = 0; k < dataTwo.length-1; k+=2){ //first beacon and second beacon (needed to calculate a vector) logData3= dataTwo[k].split(":"); logData4= dataTwo[k+1].split(":"); dx = v1 - Integer.parseInt(logData3[x]); dy = v2 - Integer.parseInt(logData3[y]); x3 = Integer.parseInt(logData3[x]); x4 = Integer.parseInt(logData4[x]); y3 = Integer.parseInt(logData3[y]); y4 = Integer.parseInt(logData4[y]); //calculate 2. vector and get the angle (it's more likely that the vehicle won't change his vector. So we estimate that the vehicle drives straight ahead and is in this area) vector1x = (x2 - x1); vector1y = (y2 - y1); vector2x = (x4 - x3); vector2y = (y4 - y3); vector = vector1x*vector2x + vector1y*vector2y; vector2 = Math.sqrt(vector1x*vector1x + vector1y*vector1y) * Math.sqrt(vector2x*vector2x + vector2y*vector2y); cos = vector / vector2; winkelBogenmass = Math.acos(cos); tmpFactor = (dx*dx + dy*dy); //save smallest factor if(factor > tmpFactor && Math.toDegrees(winkelBogenmass) < limitToAngle) { factor = tmpFactor; steadyIDSave = logData3[steadyID]; } } //update states to log the movement of vehicles through more mix-zones. Format: Number:Number:Boolean -> NumberOfPassedMixZones:NumerOfSuccessfulPassedZones(only in a row):BooleanValueToShowIfVehicleWasFollowedCorrectlyUntilNow String[] successData = {"0","0","true"}; if(successLog.get(logData[steadyID]) != null) successData = successLog.get(logData[steadyID]).split(":"); int numberTotal = Integer.parseInt(successData[0]); int numberSuccessInRow = Integer.parseInt(successData[1]); if(steadyIDSave.equals(logData[steadyID])){ locationInformation_ += "true:" + logData[x] + ":" + logData[y] + "\n"; successLog.remove(logData[steadyID]); if(successData[2].equals("true")) { successLog.put(logData[steadyID], (numberTotal+1) + ":" + (numberSuccessInRow+1) + ":true"); } else{ successLog.put(logData[steadyID], (numberTotal+1) + ":" + numberSuccessInRow + ":false"); } numberOfCorrectVehicles++; } else{ locationInformation_ += "false:" + logData[x] + ":" + logData[y] + "\n"; successLog.remove(logData[steadyID]); successLog.put(logData[steadyID], (numberTotal+1) + ":" + numberSuccessInRow + ":false"); } if(numberOfVehicles%10 == 0)logAnalyser_.updateInformationArea(numberOfVehicles, numberOfCorrectVehicles, false); } writeLocationInformationToFile(null, true); locationInformation_ = ""; //kAnonymity and entropy for(int j = 0; j < dataOne.length-1; j+=2){ numberOfCheckedVehicles++; logData = dataOne[j+1].split(":"); //calculate expected way using the street speed the silent period time and a gui element to tune the value expectedWay2 = (double)((double)(silentPeriodTime/1000 * Integer.parseInt(logData[streetSpeed]))*tuneTimeValue); tmpDistance2 = maxDistance - expectedWay2; vehicleX = Long.parseLong( logData[x]); vehicleY = Long.parseLong( logData[y]); for(int k = 0; k < dataTwo.length-1; k+=2){ logData2= dataTwo[k].split(":"); dx2 = vehicleX - Long.parseLong(logData2[x]); dy2 = vehicleY - Long.parseLong(logData2[y]); //count all vehicles which are inside the reach of the first vehicle (for anonymity set) and get the distances (to the expected way) to calculate the probabilities later if((dx2*dx2 + dy2*dy2) <= maxDistanceSquared){ tmpDistances = tmpDistance2 - Math.abs(expectedWay2 - Math.sqrt(dx2*dx2 + dy2*dy2)); distanceInTotal += tmpDistances; distances.add(tmpDistances); numberOfFoundVehicles++; } } //get anonymity set and entropy //calculate probabilities for anonymity set. prob = 0; for(Double l: distances){ prob = (float)(l.longValue()/distanceInTotal); if(prob >= 0 && prob < 1)entropiesAdded += ((1-prob)*((float)Math.log10((1-prob))/Math.log10(2))); } distances.clear(); distanceInTotal = 0; } tmpString1 = ""; tmpString2 = ""; } } tmpString1 += line + "\n"; oldTime = actualTime; } } tmpString1 = ""; tmpString2 = ""; } catch(Exception e) { e.printStackTrace(); } int maxOfRow = 0; //calculate max crossed mix zones for(Map.Entry<String, String> e : successLog.entrySet()){ if(maxOfRow < Integer.parseInt(e.getValue().split(":")[0])) maxOfRow = Integer.parseInt(e.getValue().split(":")[0]); } maxOfRow++; int[][] dataCollection = new int[maxOfRow][maxOfRow]; //long vehiclesTotal = 0; for(Map.Entry<String, String> e : successLog.entrySet()){ //vehiclesTotal++; dataCollection[Integer.parseInt(e.getValue().split(":")[0])][Integer.parseInt(e.getValue().split(":")[1])] = dataCollection[Integer.parseInt(e.getValue().split(":")[0])][Integer.parseInt(e.getValue().split(":")[1])] + 1; } float[] kAnoAndEntrArray = {(float)numberOfFoundVehicles/numberOfCheckedVehicles, (float) (-entropiesAdded/numberOfCheckedVehicles)}; logAnalyser_.updateInformationArea("\n\n", false); logAnalyser_.updateInformationArea("#GNU-Plot Data Simple\n", true); logAnalyser_.updateInformationArea("#Privacy Probabilites k-Anonymity Entropy\n", true); logAnalyser_.updateInformationArea("Silent-Period " + (float)100*numberOfCorrectVehicles/numberOfVehicles + " " + kAnoAndEntrArray[0] + " " + kAnoAndEntrArray[1] + "\n", true); logAnalyser_.writeResultsToFile("simple"); logAnalyser_.updateInformationArea("\n\n", false); logAnalyser_.updateInformationArea("#GNU-Plot Data Detail\n", true); logAnalyser_.updateInformationArea("#Success/Crossed", true); for(int i = 1; i < maxOfRow; i++) logAnalyser_.updateInformationArea(" " + i, true); logAnalyser_.updateInformationArea(" VehiclesLeft", true); // float tmpSumLine = 0; // float vehiclesTotal2 = 0; for(int l = 0; l < maxOfRow;l++){ logAnalyser_.updateInformationArea("\n" + l, true); for(int m = 1; m < maxOfRow;m++){ // tmpSumLine += dataCollection[m][l]; logAnalyser_.updateInformationArea(" " + dataCollection[m][l], true); } //this is the old version of the detailed calculator. Now there is a script -> accumulateDetailedLogFiles() in ReportingControlPanel /* if(l == 0){ logAnalyser_.updateInformationArea(" " + (tmpSumLine/vehiclesTotal), true); } else if(l == 1){ logAnalyser_.updateInformationArea(" " + (tmpSumLine/vehiclesTotal), true); } else{ vehiclesTotal2 = vehiclesTotal; for(int n = 0; n < l;n++){ for(int o = 1; o < l;o++){ vehiclesTotal2 -= dataCollection[o][n]; } } logAnalyser_.updateInformationArea(" " + (tmpSumLine/vehiclesTotal2), true); } tmpSumLine = 0; */ } logAnalyser_.updateProgressBar(100); logAnalyser_.guiControl("progressBar", false); logAnalyser_.updateProgressBar(0); logAnalyser_.writeResultsToFile("detail"); } /** * return the radius of a node written in the header of a log file */ public int getNodeRadius(String nodeID, String header){ int returnRadius = -1; String line = ""; String[] informationArray; BufferedReader reader = new BufferedReader(new StringReader(header)); try { //read vehicle header line by line while ((line = reader.readLine()) != null) { informationArray = line.split(":"); if(informationArray != null && informationArray.length > 4){ if(informationArray[2].equals(nodeID)){ return Integer.parseInt(informationArray[4]); } } } } catch(IOException e) { e.printStackTrace(); } return returnRadius; } public void standardAttackSlow(){ logAnalyser_.updateProgressBar(0); logAnalyser_.updateInformationArea(0, 0, false); //hash map to follow vehicles through more mix zones HashMap<String,String> successLog = new HashMap<String,String>(); logAnalyser_.updateProgressBar(5); String completeFile = ""; //save and load data (analysis will be faster the second time, e.g. after changing variables) if(logAnalyser_.isFilePathChanged()){ completeFile = readFile(logAnalyser_.getActualJob()); savedLog = completeFile.split("\n"); logAnalyser_.setFilePathChanged(false); } logAnalyser_.updateProgressBar(10); //check if we have a correct log -> if yes quit analysis if(savedLog[0] == null || !savedLog[0].contains("Slow")){ JOptionPane.showMessageDialog(null, Messages.getString("LogOperations.WrongLogType"), "Error", JOptionPane.ERROR_MESSAGE); return; } writeLocationInformationToFile("Slow-Modell\n******************\n", false); String[] slowHeaderArray = savedLog[0].split(":"); //variables for statistics int numberOfVehicles = 0; int numberOfVehiclesLeftTooSoon = 0; int numberOfCorrectVehicles = 0; System.out.println("file loaded..."); //temp line variable String line = ""; //variable to save split line of log (":") String[] logData; String[] logData2; //index of log data (useful if log structure changes) int timestamp = 0; int steadyID = 2; int pseudonym = 4; int direction = 12; int vehicleSpeed = 18; int x = 20; int y = 22; boolean vehicleLeftTooSoon = false; //success log String[] successData = null; String[] successDataReset = {"0","0", "0", "true"}; int numberTotal = 0; int numberSuccessInRow = 0; int numberSuccessInRowLeftTooSoon = 0; //values for variables set in GUI double tuneTimeValue = logAnalyser_.getGuiElement("tuneTimeValue"); double maxSlowSearchTime = logAnalyser_.getGuiElement("maxSlowSearchTime"); double timeToChangePseudo = Double.parseDouble(slowHeaderArray[3]); //initializing variables float expectedWay = 0; String savedSteadyID = ""; double savedScore = 0; long dx = 0; long dy = 0; double score = 0; double maxDrivingDistance = Integer.parseInt(slowHeaderArray[1])*(maxSlowSearchTime/1000); //double anoTotal = 0; //double anoCounter = 0; //int countertest = 0; //int timeInSlowCounter = 0; //variables for the progressbar long amountOfLines = savedLog.length; long updateEveryNLine = amountOfLines/80; long counter = 0; if(updateEveryNLine == 0) updateEveryNLine = 1; //a ArrayList for all vehicles which reached destination. ArrayList<String> vehiclesReachedGoalArray = new ArrayList<String>(); //int tmpCounter = 0; BufferedReader reader = new BufferedReader(new StringReader(completeFile)); /* try { //read vehicle data line by line and check every vehicle while ((line = reader.readLine()) != null) { //skip empty lines and header lines if (line.length() > 8 && !line.substring(0, 4).equals("Slow")){ //in this loop we look for all vehicles which started a slow period. --> skip vehicles with OUT direction logData = line.split(":"); if(logData[0].equals("VehicleReachedDestination")){ vehiclesReachedGoalArray.add(logData[1]); } if(logData.length == 25){ if(Integer.parseInt(logData[24]) <= 3000){ if(tmpCounter < 200){ System.out.println(line); tmpCounter++; } timeInSlowCounter++; } } } } } catch(IOException e) { System.out.println("Error while doing standard slow attack"); e.printStackTrace(); } System.out.println("*********"); */ ArrayList<String> blacklist = new ArrayList<String>(); //reader = new BufferedReader(new StringReader(completeFile)); try { //read vehicle data line by line and check every vehicle while ((line = reader.readLine()) != null) { //skip empty lines and header lines if (line.length() > 8 && !line.substring(0, 4).equals("Slow")){ //in this loop we look for all vehicles which started a slow period. --> skip vehicles with OUT direction logData = line.split(":"); if(logData[0].equals("VehicleReachedDestination")){ vehiclesReachedGoalArray.add(logData[1] + ":" + logData[2]); /* System.out.println("suche:" + line); //now reverse search the start of this slow ReverseLineReader rlr = new ReverseLineReader(logAnalyser_.getActualJob(), tmpFile.length()); while((tmpLine = rlr.readPreviousLine()) != null){ tmpArray = tmpLine.split(":"); if(tmpArray != null && tmpArray.length > 6){ if(tmpArray[2].equals(logData[1])){ vehiclesReachedGoalArray.add(tmpLine); System.out.println("finde:" + tmpLine); break; } } } */ } else if(logData[direction].equals("IN")){ //take the second beacon. It is more actual line = reader.readLine(); logData = line.split(":"); //numberOfVehicles++; //now check every vehicle that left the mix zone in the time (expectedTime + buffer) //set mark for reader (performance tweak, we can resume our buffer on this position later) reader.mark(completeFile.length()); try { //read vehicle data line by line while ((line = reader.readLine()) != null) { logData2 = line.split(":"); if(logData2[0].equals("VehicleReachedDestination")){ } //we are looking for vehicles leaving the slow period, skip IN! else if(logData2[direction].equals("IN")){ //always two beacons, skip 1 more reader.readLine(); } else{ reader.readLine(); if(logData[pseudonym].equals(logData2[pseudonym])) { blacklist.add(line); break; } //we only check vehicles until a selected time (performance tweak, calculated expected time + buffer) if((Integer.parseInt(logData[timestamp]) + timeToChangePseudo) < Integer.parseInt(logData2[timestamp])){ break; } } } } catch(IOException e) { System.out.println("Error while doing standard slow attack"); e.printStackTrace(); } //jump to mark reader.reset(); } } } } catch(IOException e) { System.out.println("Error while doing standard slow attack"); e.printStackTrace(); } reader = new BufferedReader(new StringReader(completeFile)); try { //read vehicle data line by line and check every vehicle while ((line = reader.readLine()) != null) { counter++; //update progressbar if(counter%updateEveryNLine == 0) logAnalyser_.addToProgressBar(1); //skip empty lines and header lines if (line.length() > 8 && !line.substring(0, 4).equals("Slow")){ //in this loop we look for all vehicles which started a slow period. --> skip vehicles with OUT direction logData = line.split(":"); if(logData[0].equals("VehicleReachedDestination")){ } else if(logData[direction].equals("OUT")){ } else if(logData[direction].equals("IN") && !vehiclesReachedGoalArray.contains(logData[steadyID] + ":" + logData[pseudonym])){ //take the second beacon. It is more actual line = reader.readLine(); logData = line.split(":"); //numberOfVehicles++; //now check every vehicle that left the mix zone in the time (expectedTime + buffer) //set mark for reader (performance tweak, we can resume our buffer on this position later) reader.mark(completeFile.length()); //tmp variable to save steadyID and the factor savedSteadyID = ""; savedScore = 999999999; try { //read vehicle data line by line while ((line = reader.readLine()) != null) { logData2 = line.split(":"); if(logData2[0].equals("VehicleReachedDestination")){ } //we are looking for vehicles leaving the slow period, skip IN! else if(logData2[direction].equals("IN")){ //always two beacons, skip 1 more reader.readLine(); } else{ reader.readLine(); //we only check vehicles until a selected time (performance tweak, calculated expected time + buffer) if((Integer.parseInt(logData[timestamp]) + maxSlowSearchTime) < Integer.parseInt(logData2[timestamp])){ break; } //check if vehicle was under the min time to chance pseudonym if(logData[pseudonym].equals(logData2[pseudonym])){ savedSteadyID = logData2[steadyID]; numberOfVehiclesLeftTooSoon++; vehicleLeftTooSoon = true; break; } if(!blacklist.contains(line)){ dx = Integer.parseInt(logData[x]) - Integer.parseInt(logData2[x]); dy = Integer.parseInt(logData[y]) - Integer.parseInt(logData2[y]); if((maxDrivingDistance*maxDrivingDistance) > (dx*dx + dy*dy)){ //anoTotal++; //if(logData[steadyID].equals(logData2[steadyID]))anoCounter++; expectedWay = (float) ((float)((Integer.parseInt(logData2[timestamp]) - Integer.parseInt(logData[timestamp]))/1000 * Integer.parseInt(logData[vehicleSpeed])) / tuneTimeValue); score = Math.abs((dx*dx + dy*dy) - (expectedWay*expectedWay)); //always save the smallest vehicle with the smallest factor if(score < savedScore){ savedScore = score; savedSteadyID = logData2[steadyID]; } } } } } } catch(IOException e) { System.out.println("Error while doing standard slow attack"); e.printStackTrace(); } //update states to log the movement of vehicles through more slows. Format: successData = successDataReset.clone(); if(successLog.get(logData[steadyID]) != null) successData = successLog.get(logData[steadyID]).split(":"); numberTotal = Integer.parseInt(successData[0]); numberSuccessInRow = Integer.parseInt(successData[1]); numberSuccessInRowLeftTooSoon = Integer.parseInt(successData[2]); numberOfVehicles++; //Test ob in LeftTooSoon ein Fehler ist : if(vehicleLeftTooSoon){ locationInformation_ += "slow:" + logData[x] + ":" + logData[y] + "\n"; numberOfCorrectVehicles++; successLog.remove(logData[steadyID]); if(successData[3].equals("true")) { successLog.put(logData[steadyID], (numberTotal+1) + ":" + numberSuccessInRow + ":" + (numberSuccessInRowLeftTooSoon+1) + ":true"); } else{ successLog.put(logData[steadyID], (numberTotal+1) + ":" + numberSuccessInRow + ":" + numberSuccessInRowLeftTooSoon + ":false"); } } else if(savedSteadyID.equals(logData[steadyID])){ locationInformation_ += "true:" + logData[x] + ":" + logData[y] + "\n"; successLog.remove(logData[steadyID]); if(successData[3].equals("true")) { successLog.put(logData[steadyID], (numberTotal+1) + ":" + (numberSuccessInRow+1) + ":" + (numberSuccessInRowLeftTooSoon+1) + ":true"); } else{ successLog.put(logData[steadyID], (numberTotal+1) + ":" + numberSuccessInRow + ":" + numberSuccessInRowLeftTooSoon + ":false"); } numberOfCorrectVehicles++; } else{ locationInformation_ += "false:" + logData[x] + ":" + logData[y] + "\n"; successLog.remove(logData[steadyID]); successLog.put(logData[steadyID], (numberTotal+1) + ":" + numberSuccessInRow + ":" + numberSuccessInRowLeftTooSoon + ":false"); } //Sicherungskopie /* if(vehicleLeftTooSoon){ locationInformation_ += "slow:" + logData[x] + ":" + logData[y] + "\n"; numberOfCorrectVehicles++; successLog.remove(logData[steadyID]); if(successData[3].equals("true")) { successLog.put(logData[steadyID], (numberTotal+1) + ":" + (numberSuccessInRow+1) + ":" + (numberSuccessInRowLeftTooSoon+1) + ":true"); } else{ successLog.put(logData[steadyID], (numberTotal+1) + ":" + numberSuccessInRow + ":" + (numberSuccessInRowLeftTooSoon) + ":false"); } } else if(savedSteadyID.equals(logData[steadyID])){ locationInformation_ += "true:" + logData[x] + ":" + logData[y] + "\n"; successLog.remove(logData[steadyID]); if(successData[3].equals("true")) { successLog.put(logData[steadyID], (numberTotal+1) + ":" + (numberSuccessInRow+1) + ":" + numberSuccessInRowLeftTooSoon + ":true"); } else{ successLog.put(logData[steadyID], (numberTotal+1) + ":" + numberSuccessInRow + ":" + numberSuccessInRowLeftTooSoon + ":false"); } numberOfCorrectVehicles++; } else{ locationInformation_ += "false:" + logData[x] + ":" + logData[y] + "\n"; successLog.remove(logData[steadyID]); successLog.put(logData[steadyID], (numberTotal+1) + ":" + numberSuccessInRow + ":" + numberSuccessInRowLeftTooSoon + ":false"); } */ if(numberOfVehicles%10 == 0)logAnalyser_.updateInformationArea(numberOfVehicles, numberOfVehiclesLeftTooSoon, numberOfCorrectVehicles, false); writeLocationInformationToFile(null, true); locationInformation_ = ""; vehicleLeftTooSoon = false; //jump to mark reader.reset(); } } } } catch(IOException e) { System.out.println("Error while doing standard slow attack"); e.printStackTrace(); } logAnalyser_.updateInformationArea(numberOfVehicles, numberOfVehiclesLeftTooSoon, numberOfCorrectVehicles, true); /* System.out.println("durchscnitt ano:" + (anoCounter / anoTotal)); System.out.println("total:" + numberOfVehicles + "tosoon: " + numberOfVehiclesLeftTooSoon + "numberOfCorrect:" + numberOfCorrectVehicles); System.out.println("countertest" + countertest); System.out.println("time in slow <= 3000:" + timeInSlowCounter); */ int maxOfRow = 0; //calculate max crossed slow for(Map.Entry<String, String> e : successLog.entrySet()){ if(maxOfRow < Integer.parseInt(e.getValue().split(":")[0])) maxOfRow = Integer.parseInt(e.getValue().split(":")[0]); } maxOfRow++; int[][] dataCollection = new int[maxOfRow][maxOfRow]; int[][] dataCollection2 = new int[maxOfRow][maxOfRow]; //calculate advanced stats //long vehiclesTotal = 0; for(Map.Entry<String, String> e : successLog.entrySet()){ //vehiclesTotal++; //System.out.println(e); dataCollection[Integer.parseInt(e.getValue().split(":")[0])][Integer.parseInt(e.getValue().split(":")[1])] = dataCollection[Integer.parseInt(e.getValue().split(":")[0])][Integer.parseInt(e.getValue().split(":")[1])] + 1; dataCollection2[Integer.parseInt(e.getValue().split(":")[0])][Integer.parseInt(e.getValue().split(":")[2])] = dataCollection2[Integer.parseInt(e.getValue().split(":")[0])][Integer.parseInt(e.getValue().split(":")[2])] + 1; } logAnalyser_.updateInformationArea("\n\n", false); logAnalyser_.updateInformationArea("#GNU-Plot Data Simple\n", true); logAnalyser_.updateInformationArea("#Privacy NumberOfVehicles NumberOfCorrectVehicles NumberOfVehiclesLeftToSoon ProbabilityAll ProbabiltyWithoutLeftToSoon\n", true); logAnalyser_.updateInformationArea("Slow " + numberOfVehicles + " " + numberOfCorrectVehicles + " " + numberOfVehiclesLeftTooSoon + " " + (((float)((float)numberOfCorrectVehicles/(float)numberOfVehicles))*100) + " " + (float)((numberOfCorrectVehicles-numberOfVehiclesLeftTooSoon)*100)/(numberOfVehicles-numberOfVehiclesLeftTooSoon) + "\n", true); logAnalyser_.writeResultsToFile("simple"); logAnalyser_.updateInformationArea("\n\n", false); logAnalyser_.updateInformationArea("#GNU-Plot Data Detail\n", true); logAnalyser_.updateInformationArea("#Success/Crossed", true); for(int i = 1; i < maxOfRow; i++) logAnalyser_.updateInformationArea(" " + i, true); logAnalyser_.updateInformationArea(" VehiclesLeft", true); for(int l = 0; l < maxOfRow;l++){ logAnalyser_.updateInformationArea("\n" + l, true); for(int m = 1; m < maxOfRow;m++){ logAnalyser_.updateInformationArea(" " + dataCollection[m][l], true); } } //write results to file logAnalyser_.writeResultsToFile("detail"); logAnalyser_.updateInformationArea("#GNU-Plot Data Detail WithVehiclesLeftTooSoon\n", true); logAnalyser_.updateInformationArea("#Success/Crossed", true); for(int i = 1; i < maxOfRow; i++) logAnalyser_.updateInformationArea(" " + i, true); logAnalyser_.updateInformationArea(" VehiclesLeft", true); for(int l = 0; l < maxOfRow;l++){ logAnalyser_.updateInformationArea("\n" + l, true); for(int m = 1; m < maxOfRow;m++){ logAnalyser_.updateInformationArea(" " + dataCollection2[m][l], true); } //this is the old version of the detailed calculator. Now there is a script -> accumulateDetailedLogFiles() in ReportingControlPanel } logAnalyser_.updateProgressBar(100); logAnalyser_.guiControl("progressBar", false); logAnalyser_.updateProgressBar(0); //write results to file logAnalyser_.writeResultsToFile("withVehiclesLeftTooSoon"); calculateAverageSlowTime(completeFile); } public void calculateAverageSlowTime(String file){ String line = ""; String[] array; //double sumTotal = 0; //double counter = 0; //int moreThen10 = 0; //int lessThen10 = 0; BufferedReader reader = new BufferedReader(new StringReader(file)); try { //read vehicle data line by line and check every vehicle while ((line = reader.readLine()) != null) { array = line.split(":"); if(array.length == 25){ //counter++; //sumTotal += Integer.parseInt(array[24]); //if(Integer.parseInt(array[24]) > 10000) moreThen10++; //else lessThen10++; } } } catch(IOException e) { System.out.println("Error while doing standard slow attack"); e.printStackTrace(); } //System.out.print("Average:" + sumTotal / counter + " more than 10:" + moreThen10 + " less than 10:" + lessThen10); } /* public void advancedAttackSlow(){ logAnalyser_.updateProgressBar(0); logAnalyser_.updateInformationArea(0, 0, false); //hash map to follow vehicles through more mix zones HashMap<String,String> successLog = new HashMap<String,String>(); logAnalyser_.updateProgressBar(5); String completeFile = ""; //save and load data (analysis will be faster the second time, e.g. after changing variables) if(logAnalyser_.isFilePathChanged()){ completeFile = readFile(logAnalyser_.getActualJob()); savedLog = completeFile.split("\n"); logAnalyser_.setFilePathChanged(false); } logAnalyser_.updateProgressBar(10); //check if we have a correct log -> if yes quit analysis if(savedLog[0] == null || !savedLog[0].contains("Slow")){ JOptionPane.showMessageDialog(null, Messages.getString("LogOperations.WrongLogType"), "Error", JOptionPane.ERROR_MESSAGE); return; } writeLocationInformationToFile(savedLog[0] + "******************\n", false); String[] slowHeaderArray = savedLog[0].split(":"); //variables for statistics int numberOfVehicles = 0; int numberOfVehiclesLeftTooSoon = 0; int numberOfCorrectVehicles = 0; System.out.println("file loaded..."); //temp line variable String line = ""; //variable to save split line of log (":") String[] logDataA; String[] logDataB; String[] logData2A; String[] logData2B; //index of log data (useful if log structure changes) int timestamp = 0; int steadyID = 2; int pseudonym = 4; int direction = 12; int streetName = 14; int streetSpeed = 16; int vehicleSpeed = 18; int x = 20; int y = 22; //values for variables set in GUI double tuneTimeValue = logAnalyser_.getGuiElement("tuneTimeValue"); double maxSlowSearchTime = logAnalyser_.getGuiElement("maxSlowSearchTime"); //initializing variables float expectedWay = 0; float realWay = 0; String savedSteadyID = ""; double savedScore = 0; float dx = 0; float dy = 0; double score = 0; double maxDrivingDistance = 6944.44444444444444444444444444444444444*(maxSlowSearchTime/1000); String line2 = ""; //variables for calculation float x1 = 0; float x2 = 0; float y1 = 0; float y2 = 0; //float v1 = 0; //float v2 = 0; float x3 = 0; float x4 = 0; float y3 = 0; float y4 = 0; double vector1x = 0; double vector1y = 0; double vector2x = 0; double vector2y = 0; double vector = 0; double vector2 = 0; double cos = 0; double winkelBogenmass = 0; float limitToAngle = 80; //variables for the progressbar long amountOfLines = savedLog.length; long updateEveryNLine = amountOfLines/80; long counter = 0; if(updateEveryNLine == 0) updateEveryNLine = 1; BufferedReader reader = new BufferedReader(new StringReader(completeFile)); try { //read vehicle data line by line and check every vehicle while ((line = reader.readLine()) != null) { counter++; //update progressbar if(counter%updateEveryNLine == 0) logAnalyser_.addToProgressBar(1); //skip empty lines and header lines if (line.length() > 8 && !line.substring(0, 4).equals("Slow")){ //in this loop we look for all vehicles which started a slow period. --> skip vehicles with OUT direction logDataA = line.split(":"); if(logDataA[direction].equals("IN")){ //take the second beacon. It is more actual line = reader.readLine(); line2 = line; logDataB = line.split(":"); numberOfVehicles++; //now check every vehicle that left the mix zone in the time (expectedTime + buffer) //set mark for reader (performance tweak, we can resume our buffer on this position later) reader.mark(completeFile.length()); //tmp variable to save steadyID and the factor savedSteadyID = ""; savedScore = 999999999; //calculate estimated way x1 = Integer.parseInt(logDataA[x]); x2 = Integer.parseInt(logDataB[x]); y1 = Integer.parseInt(logDataA[y]); y2 = Integer.parseInt(logDataB[y]); try { //read vehicle data line by line while ((line = reader.readLine()) != null) { logData2A = line.split(":"); logData2B = reader.readLine().split(":"); //we are looking for vehicles leaving the slow period, skip IN! if(logData2A[direction].equals("IN")){ //always two beacons, skip 1 more //reader.readLine(); } else{ //we only check vehicles until a selected time (performance tweak, calculated expected time + buffer) if((Integer.parseInt(logDataB[timestamp]) + maxSlowSearchTime) < Integer.parseInt(logData2A[timestamp])){ break; } //check if vehicle was under the min time to chance pseudonym if(logDataB[pseudonym].equals(logData2A[pseudonym])){ savedSteadyID = logData2A[steadyID]; numberOfVehiclesLeftTooSoon++; break; } dx = Integer.parseInt(logDataB[x]) - Integer.parseInt(logData2A[x]); dy = Integer.parseInt(logDataB[y]) - Integer.parseInt(logData2A[y]); if(maxDrivingDistance*maxDrivingDistance > (dx*dx + dy*dy)){ expectedWay = (float) ((float)((Integer.parseInt(logData2A[timestamp]) - Integer.parseInt(logDataB[timestamp]))/1000 * Integer.parseInt(logDataB[vehicleSpeed])) / tuneTimeValue); score = Math.abs((dx*dx + dy*dy) - (expectedWay*expectedWay)); x3 = Integer.parseInt(logData2A[x]); x4 = Integer.parseInt(logData2B[x]); y3 = Integer.parseInt(logData2A[y]); y4 = Integer.parseInt(logData2B[y]); //calculate 2. vector and get the angle (it's more likely that the vehicle won't change his vector. So we estimate that the vehicle drives straight ahead and is in this area) vector1x = (x2 - x1); vector1y = (y2 - y1); vector2x = (x4 - x3); vector2y = (y4 - y3); vector = vector1x*vector2x + vector1y*vector2y; vector2 = Math.sqrt(vector1x*vector1x + vector1y*vector1y) * Math.sqrt(vector2x*vector2x + vector2y*vector2y); cos = vector / vector2; winkelBogenmass = Math.acos(cos); // System.out.println("compare:" + line2 + " : " + line + " expectedWay^2:" + expectedWay*expectedWay + " : dxbla: " + (dx*dx + dy*dy) + " score:" + score); //always save the smallest vehicle with the smallest factor if(score < savedScore && Math.toDegrees(winkelBogenmass) < limitToAngle){ savedScore = score; savedSteadyID = logData2A[steadyID]; } } } } } catch(IOException e) { System.out.println("Error while doing standard slow attack"); e.printStackTrace(); } if(savedSteadyID.equals(logDataB[steadyID])) numberOfCorrectVehicles++; logAnalyser_.updateInformationArea(numberOfVehicles, numberOfVehiclesLeftTooSoon, numberOfCorrectVehicles, true); //jump to mark reader.reset(); } } } } catch(IOException e) { System.out.println("Error while doing standard slow attack"); e.printStackTrace(); } logAnalyser_.updateInformationArea(numberOfVehicles, numberOfVehiclesLeftTooSoon, numberOfCorrectVehicles, true); /* int maxOfRow = 0; //calculate max crossed mix zones for(Map.Entry<String, String> e : successLog.entrySet()){ if(maxOfRow < Integer.parseInt(e.getValue().split(":")[0])) maxOfRow = Integer.parseInt(e.getValue().split(":")[0]); } maxOfRow++; int[][] dataCollection = new int[maxOfRow][maxOfRow]; //calculate advanced states //long vehiclesTotal = 0; for(Map.Entry<String, String> e : successLog.entrySet()){ //vehiclesTotal++; dataCollection[Integer.parseInt(e.getValue().split(":")[0])][Integer.parseInt(e.getValue().split(":")[1])] = dataCollection[Integer.parseInt(e.getValue().split(":")[0])][Integer.parseInt(e.getValue().split(":")[1])] + 1; } logAnalyser_.updateInformationArea("\n\n", false); logAnalyser_.updateInformationArea("#GNU-Plot Data Simple\n", true); logAnalyser_.updateInformationArea("#Privacy VehiclesTotal Probabilities k-Anonymity\n", true); //calculate anonymity set for the silent period and log the results float[] kAnonymityValues = new float[numberOfMixZones]; float numberOfVeh = 0; float numberOfCorrVeh = 0; float numberOfKAnoVehTotal = 0; float numberOfKAnoVeh = 0; float[] tmpKAno = null; for(int i = 0; i < mixZoneHeaderArray.length; i++){ tmpKAno = getKAnonymityInMix(mixZoneHeaderArray[i].split(":")[2],savedLog[1]); kAnonymityValues[i] = tmpKAno[0]; numberOfKAnoVehTotal += tmpKAno[1]; numberOfKAnoVeh += tmpKAno[2]; numberOfVeh += numberOfVehicles[i]; numberOfCorrVeh += numberOfCorrectVehicles[i]; logAnalyser_.updateInformationArea("Mix-Zone" + (i+1) + " " + numberOfVehicles[i] + " " + (float)100*numberOfCorrectVehicles[i]/numberOfVehicles[i] + " " + kAnonymityValues[i] + "\n", true); } logAnalyser_.updateInformationArea("Total " + numberOfVeh + " " + (numberOfCorrVeh*100/numberOfVeh) + " " + (numberOfKAnoVehTotal/numberOfKAnoVeh) + "\n", true); logAnalyser_.writeResultsToFile("simple"); logAnalyser_.updateInformationArea("\n\n", false); logAnalyser_.updateInformationArea("#GNU-Plot Data Detail\n", true); logAnalyser_.updateInformationArea("#Success/Crossed", true); for(int i = 1; i < maxOfRow; i++) logAnalyser_.updateInformationArea(" " + i, true); logAnalyser_.updateInformationArea(" VehiclesLeft", true); //float tmpSumLine = 0; //float vehiclesTotal2 = 0; for(int l = 0; l < maxOfRow;l++){ logAnalyser_.updateInformationArea("\n" + l, true); for(int m = 1; m < maxOfRow;m++){ //tmpSumLine += dataCollection[m][l]; logAnalyser_.updateInformationArea(" " + dataCollection[m][l], true); } } */ //logAnalyser_.updateProgressBar(100); //logAnalyser_.guiControl("progressBar", false); //logAnalyser_.updateProgressBar(0); //logAnalyser_.writeResultsToFile("detail"); //writeLocationInformationToFile(null, true); /* } */ /** * return k-anonymity of a mix log (for a chosen node id) */ public float[] getKAnonymityInMix(String theNodeID, String log){ String line = ""; String[]logData; String[]logData2; //index of log data (useful if log structure changes) int steadyID = 2; int nodeID = 10; int direction = 12; //variables for statistics int numberOfVehicles = 0; int totalNumberOfVehicles = 0; int tmpNumberOfVehicles = 0; ArrayList<String> savedIDs = new ArrayList<String>(); ArrayList<String> savedInMixZone = new ArrayList<String>(); boolean endOfFile = true; //iterate through beacons BufferedReader reader = new BufferedReader(new StringReader(log)); try { //read vehicle data line by line while ((line = reader.readLine()) != null) { if (line.length() > 0){ logData = line.split(":"); if(logData != null && logData.length > 18){ //lets find the OUTs belonging to the INs if(logData[direction].equals("IN") && logData[nodeID].equals(theNodeID)){ //log all vehicles which drive into the mix-zone savedInMixZone.add(logData[steadyID]); //set mark for reader (performance tweak) reader.mark(log.length()); numberOfVehicles++; try { //read vehicle data line by line while ((line = reader.readLine()) != null) { logData2 = line.split(":"); //delete all vehicles which drive out of the mix-zone if(logData2[direction].equals("OUT") && logData[nodeID].equals(theNodeID)) if(savedInMixZone.contains(logData2[steadyID])) savedInMixZone.remove(logData2[steadyID]); //vehicles leaves mix zone if(logData[steadyID].equals(logData2[steadyID])){ if(logData2[direction].equals("OUT")) endOfFile = false; break; } //vehicle is still in mix zone if(logData2[nodeID].equals(theNodeID)){ //a vehicle could enter and leave mix zone while the other vehicle is still in the zone. Saving logged vehicle IDs to avoid counting vehicles double if(!savedIDs.contains(logData2[steadyID])){ savedIDs.add(logData2[steadyID]); tmpNumberOfVehicles++; } } } } catch(IOException e) { e.printStackTrace(); } //only use the data if end of file has not been reached if(endOfFile) { numberOfVehicles--; tmpNumberOfVehicles = 0; } savedIDs.clear(); totalNumberOfVehicles += tmpNumberOfVehicles + savedInMixZone.size(); tmpNumberOfVehicles = 0; endOfFile = true; //jump to mark reader.reset(); } } } } } catch(IOException e) { e.printStackTrace(); } float[] arr = {(float)totalNumberOfVehicles/numberOfVehicles, totalNumberOfVehicles, numberOfVehicles}; return arr; } /** * Method to read a file */ public String readFile(String filePath){ byte[] data = null; try { java.io.FileInputStream f1; f1 = new java.io.FileInputStream(filePath); FileChannel fc = f1.getChannel(); data = new byte[(int) fc.size()]; MappedByteBuffer b = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()); b.get(data); b.clear(); fc.close(); f1.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return new String(data); } /** * Method to read a file. Reads a file and returns the header and the content split in an String array */ public String[] readFileAndHeader(String filePath){ byte[] data = null; try { java.io.FileInputStream f1; f1 = new java.io.FileInputStream(filePath); FileChannel fc = f1.getChannel(); data = new byte[(int) fc.size()]; MappedByteBuffer b = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()); b.get(data); b.clear(); fc.close(); f1.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return new String(data).split(java.util.regex.Pattern.quote("*******************")); } /** * Method to read a file without the header of the log */ public String readFileWithoutHeader(String filePath){ String returnString = ""; try{ // Open the file that is the first // command line parameter FileInputStream fstream = new FileInputStream(filePath); // Get the object of DataInputStream DataInputStream in = new DataInputStream(fstream); BufferedReader br = new BufferedReader(new InputStreamReader(in)); String strLine; boolean headerFound = false; //Read file line By line while ((strLine = br.readLine()) != null) { if(headerFound)returnString += "\n" +strLine; if(strLine.equals("*******************")) headerFound = true; } //Close the input stream in.close(); }catch (Exception e){//Catch exception if any System.err.println("Error: " + e.getMessage()); } return returnString; } /** * Analyze traffic data to get information for an attack (for a mix node */ public Object[] getDataOfMixZoneLog(String[] file, String mixNodeID, int totalNumberOfAnalysedZones){ //read log. Be careful with big logs!!! String header = file[0]; String log = file[1]; //temp variables String line = ""; String[] logData; //variables for statistics //index of log data (useful if log structure changes) int timestamp = 0; int steadyID = 2; int nodeID = 10; int direction = 12; int port = 20; //mix Zone Information String[] mixInfo; int mixZonePorts = 0; //get amount of ports in mix zone String[] headers = header.split("\n"); for(int i = 0; i < headers.length; i++){ String[] lineSplit = headers[i].split(":"); if(lineSplit[2].equals(mixNodeID)){ mixInfo = lineSplit; mixZonePorts = mixInfo.length - 5; break; } } int portToPortSpeed[][] = new int[mixZonePorts][mixZonePorts]; double portToPortProbability[][] = new double[mixZonePorts][mixZonePorts]; int portToPortFrequency[][] = new int[mixZonePorts][mixZonePorts]; Object[] returnValue = {portToPortSpeed, portToPortProbability, portToPortFrequency}; //variables for progress bar status String[] tmpLines = log.split("\n"); long amountOfLines = tmpLines.length; long updateEveryNLine = (amountOfLines/40)*totalNumberOfAnalysedZones; long counter = 0; BufferedReader reader = new BufferedReader(new StringReader(log)); try { //read vehicle data line by line while ((line = reader.readLine()) != null) { counter++; //Update progress bar if(counter%updateEveryNLine ==0) logAnalyser_.addToProgressBar(1); if (line.length() > 0){ logData = line.split(":"); if(logData != null && logData.length > 18){ //only attack vehicles which drive into a mix zone if(logData[direction].equals("IN") && logData[nodeID].equals(mixNodeID)){ //counter for all vehicles //set mark for reader reader.mark(log.length()); try { //read vehicle data line by line while ((line = reader.readLine()) != null) { String[] logData2 = line.split(":"); //only check vehicles that left the mix zone ("OUT") after our first vehicle went "IN". Also check if it's the same node. if(logData2[direction].equals("OUT") && logData2[nodeID].equals(mixNodeID)){ //check if it's the same vehicle, if yes log the time to cross the mix zone. if(logData[steadyID].equals(logData2[steadyID])){ portToPortSpeed[Integer.parseInt(logData[port])-1][Integer.parseInt(logData2[port])-1] = (int) (Long.parseLong(logData2[timestamp]) - Long.parseLong(logData[timestamp])); portToPortFrequency[Integer.parseInt(logData[port])-1][Integer.parseInt(logData2[port])-1] += 1; break; } } } } catch(IOException e) { e.printStackTrace(); } //jump to mark reader.reset(); } } } } } catch(IOException e) { e.printStackTrace(); } //calculate the probabilities for(int i = 0; i < mixZonePorts; i++){ int totalFrequenciesOfPort = 0; for(int j = 0; j < mixZonePorts; j++){ totalFrequenciesOfPort += portToPortFrequency[i][j]; } for(int k = 0; k < mixZonePorts; k++){ if(totalFrequenciesOfPort != 0)portToPortProbability[i][k] = (double)portToPortFrequency[i][k] / totalFrequenciesOfPort; else portToPortProbability[i][k] = 0; } } return returnValue; } public String getOperation() { return operation_; } public void setOperation(String operation) { this.operation_ = operation; } /** * Writes advanced analyzed information to a file */ public void writeLocationInformationToFile(String header, boolean append){ try { BufferedWriter out = new BufferedWriter(new FileWriter(logAnalyser_.getActualJob().substring(0,logAnalyser_.getActualJob().length()-4) + "_" + logAnalyser_.getLogName() + "_locationInformation.log", append)); if(header != null){ out.write(header); out.close(); } else{ out.write(locationInformation_); out.close(); locationInformation_ = ""; } } catch (IOException e) { e.printStackTrace(); } } }