/**
* 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.LinkedList;
import java.util.Iterator;
import org.apache.log4j.Logger;
import de.tu.dresden.dud.dc.Participant;
import de.tu.dresden.dud.dc.Util;
/**
* Everybody that wants to take part in work cycles, needs to receive this
* confirmation before.
*
* @author klobs
*
*/
public class ManagementMessageWelcome2WorkCycle extends ManagementMessage {
// Logging
private static Logger log = Logger.getLogger(ManagementMessageWelcome2WorkCycle.class);
public static final int ACCEPTED = 0;
public static final int REJECTED = 1;
private int accepted = -1;
private LinkedList<Participant> activeParticipant = new LinkedList<Participant>();
private long workcycle = -1;
private int timeout = -1;
/**
* Generates the ManagementMessageWelcome2WorkCycle management message.
* Introduced in protocol Version 0.0.11
*
* Fields are:
*
* ACCEPTED 1 Byte
* WORK CYCLE 8 Byte
* TIMEOUT 2 Byte
* PARTCOUNT 2 Byte
* 1st PART ID LENGTH 2 Byte
* 1st PART ID variable
* 1st PART USERNAME LENGTH 2 Byte
* 1st PART USERNAME variable
* 1st PART DSA SIGNATURE LENGTH 2 Byte
* 1st PART DSA SIGNATURE variable
* 1st PART DH PUBLIC PART LENGTH 2 Byte
* 1st PART DH PUBLIC PART variable
* 1st PART PUBLIC PART SIGNATURE L. 2 Byte
* 1st PART PUBLIC PART SIGNATURE variable...
* ... and so on for every active participant.
*
* @param accepted
* accepted / rejected
* @param workCycleNumber
* the work cycle number in which the participant is expected to
* participate.
* @param timeout
* timeout in ms
*/
public ManagementMessageWelcome2WorkCycle(int accepted, long workCycleNumber,
int timeout, ArrayList<Participant> activeConnections) {
ArrayList<byte[]> b = new ArrayList<byte[]>();
Participant p = null;
byte[] messagetype = Util.stuffIntIntoShort(ManagementMessage.WELCOME2WORKCYCLE);
byte[] acc = Util.stuffIntIntoByte(accepted);
byte[] rno = Util.stuffLongIntoLong(workCycleNumber);
byte[] to = Util.stuffIntIntoShort(timeout);
byte[] ac = Util.stuffIntIntoShort(activeConnections.size());
b.add(messagetype);
b.add(acc);
b.add(rno);
b.add(to);
b.add(ac);
for (Iterator<Participant> i = activeConnections.iterator(); i
.hasNext();) {
p = i.next();
b.add(Util.stuffIntIntoShort(p.getId().length()));
b.add(p.getId().getBytes());
b.add(Util.stuffIntIntoShort(p.getUsername().length()));
b.add(p.getUsername().getBytes());
b.add(Util.stuffIntIntoShort(p.getDSAPublicSignature().length));
b.add(p.getDSAPublicSignature());
b.add(Util.stuffIntIntoShort(p.getDHPublicPart().length));
b.add(p.getDHPublicPart());
b.add(Util.stuffIntIntoShort(p.getDHPublicPartSignature().length));
b.add(p.getDHPublicPartSignature());
}
if(log.isDebugEnabled()){
log.debug("Encoding WELCOME2WORKCYCLE MESSAGE");
log.debug(" Server accepted / rejected reason number: "
+ String.valueOf(accepted) + " / " + Arrays.toString(acc));
log.debug(" Send message for work cycle number: "
+ String.valueOf(workCycleNumber) + " / "
+ Arrays.toString(rno));
log.debug(" The timeout in ms has been set to: "
+ String.valueOf(timeout) + " / " + Arrays.toString(to));
}
message = craftMessage(b);
}
/**
* Generates the ManagementMessageWelcome2WorkCycle management message.
* Introduced in protocol Version 0.0.11
*
* Fields are:
*
* ACCEPTED 1 Byte
* WORK CYCLE 8 Byte
* TIMEOUT 2 Byte
* PARTCOUNT 2 Byte
* 1st PART ID LENGTH 2 Byte
* 1st PART ID variable
* 1st PART USERNAME LENGTH 2 Byte
* 1st PART USERNAME variable
* 1st PART DSA SIGNATURE LENGTH 2 Byte
* 1st PART DSA SIGNATURE variable
* 1st PART DH PUBLIC PART LENGTH 2 Byte
* 1st PART DH PUBLIC PART variable
* 1st PART PUBLIC PART SIGNATURE L. 2 Byte
* 1st PART PUBLIC PART SIGNATURE variable...
* ... and so on for every active participant.
*
* @param accepted
* accepted / rejected
* @param workcycleNumber
* the work cycle number in which the participant is expected to
* participate.
* @param timeout
* timeout in ms
*/
public ManagementMessageWelcome2WorkCycle(byte[] payload) {
int pc = 0;
int ul = 13;
ArrayList<byte[]> p = new ArrayList<byte[]>(5);
if (payload.length < 13) {
log.warn(
"Payload does not correspond to the required min size");
errorProcessing = true;
}
message = payload;
accepted = payload[0];
workcycle = Util.stuffBytesIntoLongUnsigned(Util.getBytesByOffset(payload, 1, 8));
timeout = Util.stuffBytesIntoUInt(Util.getBytesByOffset(payload, 9, 2));
pc = Util.stuffBytesIntoUInt(Util.getBytesByOffset(payload, 11, 2));
for (int i = 0; i < pc; i++) {
for (int j = 0; j < 5; j++) {
if (payload.length >= ul + 2) {
int pl = Util.stuffBytesIntoUInt(Util.getBytesByOffset(payload, ul, 2));
ul = ul + 2;
if (payload.length >= ul + pl) {
p.add(Util.getBytesByOffset(payload, ul, pl));
ul = ul + pl;
} else {
log.warn("Payload has strange differences between indicated and effective length: wrong information about id lengths");
errorProcessing = true;
}
} else {
log.warn("Payload has strange differences between indicated and effective length: not enough data for the indicated number of users");
errorProcessing = true;
}
}
activeParticipant.add(new Participant(new String(p.get(0)),
new String(p.get(1)), p.get(2), p.get(3), p.get(4)));
p.clear();
}
if(log.isDebugEnabled()){
log.debug("Decoding WELCOME2WORKCYCLE MESSAGE");
log.debug(" Server accpeted / rejected reason number: "
+ String.valueOf(accepted));
log.debug(" Server want participant in work cycle number: "
+ String.valueOf(workcycle));
log.debug(" Timeout in ms has been set to: " + String.valueOf(timeout));
}
}
/**
* getter for the accepted variable.
*
* @return 0, or >
*/
public boolean isAccepted() {
if(accepted == ACCEPTED)
return true;
return false;
}
public LinkedList<Participant> getActiveParticipantIDs() {
return activeParticipant;
}
/**
* @return the work cycle
*/
public long getWorkCycle() {
return workcycle;
}
/**
* @return the timeout
*/
public int getTimeout() {
return timeout;
}
}