/******************************************************************************* * gMix open source project - https://svs.informatik.uni-hamburg.de/gmix/ * Copyright (C) 2014 SVS * * 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 userGeneratedContent.simulatorPlugIns.plugins.outputStrategy; import java.security.SecureRandom; import org.apache.commons.math.MathException; import org.apache.commons.math.distribution.ExponentialDistributionImpl; import staticContent.evaluation.simulator.Simulator; import staticContent.evaluation.simulator.annotations.plugin.Plugin; import staticContent.evaluation.simulator.annotations.property.DoubleSimulationProperty; import staticContent.evaluation.simulator.annotations.property.FloatSimulationProperty; import staticContent.evaluation.simulator.annotations.property.IntSimulationProperty; import staticContent.evaluation.simulator.annotations.property.requirements.SgMixMaxClientMixDelayRequirement; import staticContent.evaluation.simulator.annotations.property.requirements.SgMixMaxInterMixDelayRequirement; import staticContent.evaluation.simulator.annotations.property.requirements.SgMixMinClientMixDelayRequirement; import staticContent.evaluation.simulator.annotations.property.requirements.SgMixMinInterMixDelayRequirement; import staticContent.evaluation.simulator.core.message.BasicMixMessage; import staticContent.evaluation.simulator.core.networkComponent.AbstractClient; import staticContent.evaluation.simulator.core.networkComponent.NetworkNode; // This is an example of how to manually cap a plugin // by providing the pluginLayerKay. If the pluginLayer // is not present, the SimPropRegistry tries to find a superclass! @Plugin(pluginKey = "STOP_AND_GO", pluginName="Stop And Go", pluginLayerKey = "OUTPUT_STRATEGY") public class StopAndGoMessage extends BasicMixMessage { private long[] tsMin; // 0: first mix; 1: second mix... private long[] tsMax; public int[] delay; private int tsMinCounter = 0; private int tsMaxCounter = 0; private int delayCounter = 0; private ExponentialDistributionImpl expDist; private static SecureRandom secureRandom = new SecureRandom(); private int identifier; private static int idCounter = 0; @DoubleSimulationProperty ( name = "Security parameter mu", key = "SGMIX_SECURITY_PARAMETER_MU") private double securityParameterMu; @IntSimulationProperty( name = "Minimum inter mix delay (ms)", key = "SGMIX_MIN_INTER_MIX_DELAY", min = 0, value_requirements = SgMixMinInterMixDelayRequirement.class) private int minInterMixDelay; @IntSimulationProperty( name = "Maximum inter mix delay (ms)", key = "SGMIX_MAX_INTER_MIX_DELAY", min = 0, value_requirements = SgMixMaxInterMixDelayRequirement.class) private int maxInterMixDelay; @IntSimulationProperty( name = "Minimum client mix delay (ms)", key = "SGMIX_MIN_CLIENT_MIX_DELAY", value_requirements=SgMixMinClientMixDelayRequirement.class, min = 0) private int minClientMixDelay; @IntSimulationProperty( name = "Maximum client mix delay (ms)", key = "SGMIX_MAX_CLIENT_MIX_DELAY", value_requirements=SgMixMaxClientMixDelayRequirement.class, min = 0) private int maxClientMixDelay; @IntSimulationProperty( name = "Maximum clock deviation (ms)", key = "SGMIX_MAX_CLOCK_DEVITION", min = 0) private int maxClockDeviation; public StopAndGoMessage(boolean isRequest, NetworkNode source, NetworkNode destination, AbstractClient owner, long creationTime, boolean isDummy) { super(isRequest, source, destination, owner, creationTime, isDummy); this.identifier = idCounter++; // generate delays securityParameterMu = Simulator.settings.getPropertyAsDouble("SGMIX_SECURITY_PARAMETER_MU"); Simulator simulator = Simulator.getSimulator(); int numberOfMixes = simulator.getMixes().size(); this.delay = new int[numberOfMixes]; this.expDist = new ExponentialDistributionImpl(1d/securityParameterMu); this.expDist.reseedRandomGenerator(secureRandom.nextLong()); boolean useTimeStamps = Simulator.settings.getPropertyAsBoolean("SGMIX_USE_TIMESTAMPS"); for (int i=0; i<numberOfMixes; i++) { try { delay[i] = (int)Math.round(expDist.sample() * 1000d); } catch (MathException e) { e.printStackTrace(); throw new RuntimeException("ERROR: could not draw sample from exponential distribution!"); } } if (useTimeStamps) { minInterMixDelay = Simulator.settings.getPropertyAsInt("SGMIX_MIN_INTER_MIX_DELAY"); maxInterMixDelay = Simulator.settings.getPropertyAsInt("SGMIX_MAX_INTER_MIX_DELAY"); minClientMixDelay = Simulator.settings.getPropertyAsInt("SGMIX_MIN_CLIENT_MIX_DELAY"); maxClientMixDelay = Simulator.settings.getPropertyAsInt("SGMIX_MAX_CLIENT_MIX_DELAY"); maxClockDeviation = Simulator.settings.getPropertyAsInt("SGMIX_MAX_CLOCK_DEVITION"); tsMin = new long[numberOfMixes]; tsMax = new long[numberOfMixes]; for (int i=0; i<numberOfMixes; i++) { if (isRequest) { tsMin[i] = getMinTimestampForRequest(i, maxClockDeviation, delay, minInterMixDelay, minClientMixDelay); tsMax[i] = getMaxTimestampForRequest(i, maxClockDeviation, delay, maxInterMixDelay, maxClientMixDelay); } else { tsMin[i] = getMinTimestampForReply(i, maxClockDeviation, delay, minInterMixDelay, minClientMixDelay); tsMax[i] = getMaxTimestampForReply(i, maxClockDeviation, delay, maxInterMixDelay, maxClientMixDelay); } } } } // mixNumer: 0,1,...,numberOfMixes public static long getMinTimestampForRequest( int mixNumber, int maxClockDeviation, int[] sgDelays, int minInterMixDelay, int minClientMixDelay) { int sumOfSgDelays = 0; for (int i=0; i<mixNumber; i++) sumOfSgDelays += sgDelays[i]; int minDelay = minClientMixDelay + mixNumber * minInterMixDelay; int maxClockDev = (mixNumber + 1) * maxClockDeviation; return Simulator.getNow() + sumOfSgDelays + minDelay - maxClockDev; } public static long getMaxTimestampForRequest( int mixNumber, int maxClockDeviation, int[] sgDelays, int maxInterMixDelay, int maxClientMixDelay) { int sumOfSgDelays = 0; for (int i=0; i<mixNumber; i++) sumOfSgDelays += sgDelays[i]; int maxDelay = maxClientMixDelay + mixNumber * maxInterMixDelay; int maxClockDev = (mixNumber + 1) * maxClockDeviation; return Simulator.getNow() + sumOfSgDelays + maxDelay + maxClockDev; } public static long getMinTimestampForReply( int mixNumber, int maxClockDeviation, int[] sgDelays, int minInterMixDelay, int minClientMixDelay) { if (mixNumber == 0) return Long.MIN_VALUE; int sumOfSgDelays = 0; for (int i=0; i<mixNumber; i++) sumOfSgDelays += sgDelays[i]; int minDelay = mixNumber * minInterMixDelay; int maxClockDev = mixNumber * maxClockDeviation; if (mixNumber == sgDelays.length-1) minDelay = minDelay - minInterMixDelay + minClientMixDelay; return Simulator.getNow() + sumOfSgDelays + minDelay - maxClockDev; } public static long getMaxTimestampForReply( int mixNumber, int maxClockDeviation, int[] sgDelays, int maxInterMixDelay, int maxClientMixDelay) { if (mixNumber == 0) return Long.MAX_VALUE; int sumOfSgDelays = 0; for (int i=0; i<mixNumber; i++) sumOfSgDelays += sgDelays[i]; int maxDelay = mixNumber * maxInterMixDelay; int maxClockDev = mixNumber * maxClockDeviation; if (mixNumber == sgDelays.length-1) maxDelay = maxDelay - maxInterMixDelay + maxClientMixDelay; return Simulator.getNow() + sumOfSgDelays + maxDelay - maxClockDev; } // call only once per mix! public long getTsMin() { return tsMin[tsMinCounter++]; } // call only once per mix! public long getTsMax() { return tsMax[tsMaxCounter++]; } // call only once per mix! public int getDelay() { return delay[delayCounter++]; } public String toString() { String replyOrRequest = super.isRequest() ? "Request" : "Reply"; String timeInfo = " "; for (int i=0; i<tsMin.length; i++) timeInfo += ""+i +": [min:" +tsMin[i] +", expected: "+delay[i] +", max: "+tsMax[i] +"] "; return "MixMessage ("+replyOrRequest +", owner: "+owner +", id: " +identifier +timeInfo+")"; } }