/** * This software is GPLv2. * Take a look at the LICENSE file for more info. */ package de.tu.dresden.dud.dc.ManagementMessage; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import org.apache.log4j.Logger; import de.tu.dresden.dud.dc.Connection; import de.tu.dresden.dud.dc.KeyExchangeManager; import de.tu.dresden.dud.dc.Server; import de.tu.dresden.dud.dc.Util; import de.tu.dresden.dud.dc.KeyGenerators.KeyGenerator; import de.tu.dresden.dud.dc.WorkCycle.WorkCycleManager; /** * @author klobs * */ public class ManagementMessageWelcome2Service extends ManagementMessage{ // Logging private static Logger log = Logger.getLogger(ManagementMessageWelcome2Service.class); // Features public static final short FEATURE_KEY_GENERATION = 0; public static final short FEATURE_LOST_CONNECTION_HANDLING = 1; public static final short FEATURE_KEY_EXCHANGE = 2; public static final short FEATURE_VARIABLE_PAYLOAD_LENGTH = 3; public static final short FEATURE_EARLY_QUIT_REACTION = 4; private HashMap<Short, Short> featureMap = new HashMap<Short, Short>(10); private int version; private int charLength; private int participantsCount; private int accept; /** * Generates the WELCOME2SERVICE management message. * Introduced in protocol Version 0.0.7 * * Fields are: * TYPE 2 Byte * TOTAL LENGTH 2 Byte * VERSION 2 Byte * CHARACTER LENGTH (in Bytes) 2 Byte * PARTICIPANTS COUNT* 2 Byte * ACCEPT / REJECT 2 Byte * * * registered for the service, but not necessarily taking part in work cycles * * @param s the server for which the WELCOME2SERVICE is to be generated */ public ManagementMessageWelcome2Service(Server s){ ArrayList<byte[]> b = new ArrayList<byte[]>(); setupFeatureList(s); byte[] messagetype = Util.stuffIntIntoShort(ManagementMessage.WELCOME2SERVICE); byte[] version = Util.stuffIntIntoShort(VERSION); byte[] charLength = Util.stuffIntIntoShort(s.getWorkCycleManager().getSymbolLength()); byte[] partCount = Util.stuffIntIntoShort(s.getInfoService().getParticipantCount()); byte[] acRej = Util.stuffIntIntoShort(s.getInfoService().doAccept()); b.add(messagetype ); b.add(version ); b.add(charLength ); b.add(partCount ); b.add(acRej ); b.add(generateFeatureArray()); if(log.isDebugEnabled()){ log.debug("Encoding WELCOME2SERVICE MESSAGE"); log.debug(" Server protocol version: " + String.valueOf(VERSION)); log.trace(" / " + Arrays.toString(version)); log.debug(" Server charlength: " + String.valueOf(s.getWorkCycleManager().getSymbolLength())); log.trace(" / " + Arrays.toString(charLength)); log.debug(" Current users:" + String.valueOf(s.getInfoService().getParticipantCount())); log.trace(" / " + Arrays.toString(partCount)); log.debug(" Server is accepting new participants: " + String.valueOf(s.getInfoService().doAccept())); log.trace(" / " + Arrays.toString(acRej)); } message = craftMessage(b); } /** * Generates the WELCOME2SERVICE management message. * Introduced in protocol Version 0.0.7 * * Fields are: * TYPE 2 Byte * TOTAL LENGTH 2 Byte * VERSION 2 Byte * CHARACTER LENGTH (in Bytes) 2 Byte * PARTICIPANTS COUNT* 2 Byte * ACCEPT / REJECT 2 Byte * FEATURELIST VARIABLE * * * registered for the service, but not necessarily taking part in work cycles * * @param s the server for which the WELCOME2SERVICE is to be generated */ public ManagementMessageWelcome2Service(byte[] payload){ if(payload.length < 8){ log.warn( "Payload length < minimal expected payload Length! Dropping packet!"); errorProcessing = true; } version = Util.stuffBytesIntoUInt(Util.getFirstBytes(payload, 2)); charLength = Util.stuffBytesIntoUInt(Util.getBytesByOffset(payload, 2, 2)); participantsCount = Util.stuffBytesIntoUInt(Util.getBytesByOffset(payload, 4, 2)); accept = Util.stuffBytesIntoUInt(Util.getBytesByOffset(payload, 6, 2)); setupFeatureList(Util.getBytesByOffset(payload, 8, payload.length - 8)); if(log.isDebugEnabled()){ log.debug("Decoding WELCOME2SERVICE MESSAGE"); log.debug(" Server requires " + String.valueOf(version) + " as protocol"); log.debug(" Server requires " + String.valueOf(charLength) + " as charlength"); log.debug(" There are currently " + String.valueOf(participantsCount) + " participants (not necissarily taking part in work cycles)"); log.debug(" Server is accepting new participants: " + String.valueOf(accept)); } } private byte[] generateFeatureArray(){ byte[] fa = new byte[0]; for(Short f: featureMap.keySet()){ fa = Util.concatenate(fa, Util.stuffIntIntoShort(f.shortValue())); fa = Util.concatenate(fa, Util.stuffIntIntoShort(featureMap.get(f).shortValue())); } return fa; } public int getVersion() { return version; } public int getCharLength() { return charLength; } public int getParticipantsCount() { return participantsCount; } public int getAccept() { return accept; } public short getEarlyQuitReaction(){ Short b = featureMap.get(Short.valueOf(FEATURE_EARLY_QUIT_REACTION)); if (b != null){ return b.shortValue(); } return WorkCycleManager.EARLY_QUIT_MUST_NOT_HAPPEN; } public short getKeGMethod(){ Short b = featureMap.get(Short.valueOf(FEATURE_KEY_GENERATION)); if (b != null){ return b.shortValue(); } return KeyGenerator.KGMETHOD_NULL; } public short getKeXMethod(){ Short b = featureMap.get(Short.valueOf(FEATURE_KEY_EXCHANGE)); if (b != null){ return b.shortValue(); } return KeyExchangeManager.KEX_MANUAL; } public short getFeatureMessageLength(){ if (featureMap.containsKey(Short.valueOf(FEATURE_VARIABLE_PAYLOAD_LENGTH))){ return featureMap.get(Short.valueOf(FEATURE_VARIABLE_PAYLOAD_LENGTH)).shortValue(); } return WorkCycleManager.MESSAGE_LENGTHS_FIXED; } private void setupFeatureList(byte[] fa){ if (fa.length % 4 != 0){ log.error("Feature array has wrong size"); errorProcessing = true; } for (int i = 0; i< fa.length; i = i+4){ featureMap.put(Short.valueOf((short) Util.stuffBytesIntoUInt(Util .getBytesByOffset(fa, i, 2))), Short.valueOf((short) Util .stuffBytesIntoUInt(Util.getBytesByOffset(fa, i + 2, 2)))); } } private void setupFeatureList(Server s){ featureMap.put(Short.valueOf(FEATURE_KEY_GENERATION), Short.valueOf(s .getWorkCycleManager().getKeyGenerationMethod())); featureMap.put(Short.valueOf(FEATURE_LOST_CONNECTION_HANDLING), Short .valueOf(Connection.HANDLING_EXPLODE)); featureMap.put(Short.valueOf(FEATURE_KEY_EXCHANGE), Short.valueOf(s .getKeyExchangeManager().getKexHandling())); featureMap.put(Short.valueOf(FEATURE_VARIABLE_PAYLOAD_LENGTH), Short .valueOf(s.getWorkCycleManager().getMessageLengthMode())); featureMap.put(Short.valueOf(FEATURE_EARLY_QUIT_REACTION), Short .valueOf(s.getWorkCycleManager().getEarlyQuitReaction())); } }