/** * This software is GPLv2. * Take a look at the LICENSE file for more info. */ package de.tu.dresden.dud.dc; import java.io.IOException; import java.net.Socket; import java.security.KeyPair; import java.util.ArrayList; import java.util.Arrays; import java.util.Observable; import java.util.Observer; import org.apache.log4j.Logger; import de.tu.dresden.dud.dc.InfoService.InfoService; import de.tu.dresden.dud.dc.ManagementMessage.ManagementMessage; /** * This class is the Participant with all the needed functionalities. * @author klobs */ public class Participant extends Observable implements Observer { // Logging private static Logger log = Logger.getLogger(Participant.class); private ArrayList<Connection> connections = new ArrayList<Connection>(); private InfoService infoService = null; private boolean isStopped = false; private KeyManager keyManager = null; private boolean manualSetup = false; private byte[] dh = null; private byte[] dhs = null; private String id = new String(); private byte[] signature = null; private String username = new String(); /** * Constructor for a new participant. * Use this constructor, if id, username and signature are already known. * * @param id participant's ID * @param u username * @param s signature * @param dh Diffie Hellman public part * @param dhs Diffie Hellman signed */ public Participant(String id, String u, byte[] s, byte[] dh, byte[] dhs) { this.dh = dh; this.dhs = dhs; this.id = id; this.username = u; this.signature = s; } /** * Constructor for a new participant. * Use this constructor, if a new DSA Keypair has to be generated. * * @param u */ public Participant(String u){ this.username = u; keyManager = new KeyManager(); this.signature = keyManager.getDSAPublicKey().getEncoded(); this.id = keyManager.getDSAPublicKeyID(); this.dh = keyManager.getDHPublicPart(); this.dhs = keyManager.getDHPublicPartSignature(); } public Connection doAllTheThingsToBecomeActive(String hostname, int port){ Connection c = establishNewConnection(hostname, port); if(manualSetup) registerAtService(c); return c; } /** * compares 2 participants, by comparing id, uname and sig. * @param p * @return whether compared parameters are equal */ public boolean equalsTo(Participant p){ if (this.id.equals(p.getId()) && this.username.equals(p.getUsername()) && Arrays.equals(this.signature,p.getDSAPublicSignature())) return true; return false; } /** * Establish a new Connection to the given host and specified port. * @param host * @param port * @return */ public Connection establishNewConnection(String host, int port){ try{ Socket e = new Socket(host, port); Connection c = new Connection(null, e, this); c.setParticipant(this); c.setAssocKeyManager(keyManager); c.addObserver(this); if(connections.size() != 0) connections.clear(); connections.add(c); new Thread(c, "connectionParticipant_"+ id).start(); infoService = new InfoService(); return c; } catch( IOException e){ log.error("Problems when establishing connection"); return new Connection(null,null, this); } } public void exchangeKeyWith(String id, Connection c){ c.requestKeyExchange(id); } /** * @return ArrayList with all Connections owned by the participant. */ public ArrayList<Connection> getConnections(){ return connections; } public byte[] getDHPublicPart(){ return dh; } public byte[] getDHPublicPartSignature(){ return dhs; } public byte[] getDSAPublicSignature() { return signature; } public String getId() { return id; } public InfoService getInfoService(){ return infoService; } public KeyPair getKeyPair(){ if (keyManager == null) return null; return keyManager.getDSAKeypair(); } public boolean getManualSetup(){ return manualSetup; } public String getUsername() { return username; } public boolean isStopped() { return isStopped; } public void joinWorkCycle(Connection c){ if(connections.contains(c)) c.joinWorkCycle(this); } /** * Tells the participant to join the service with a specific connection. * Only works for own connections. (i.e. owned by the participant instance) * @param c */ public void registerAtService(Connection c){ if(connections.contains(c)) c.registerAtService(this); } public void leaveWorkCycle(Connection c){ if(connections.contains(c)) c.leaveWorkCycle(this); } public void quitService(Connection c){ if(connections.contains(c)) c.quitService(this); } public void setManualSetup(boolean m){ manualSetup = m; } public void setId(String id) { this.id = id; } public void setSignature(byte[] signature) { this.signature = signature; } public void setStopped(boolean isStopped) { this.isStopped = isStopped; } public void setUsername(String username) { this.username = username; } public String toString(){ return "part:id=" + id; } public void update(Observable o, Object a){ // hand on all management messages to our observers // this is needed for the gui if (o instanceof Connection && a instanceof ManagementMessage){ setChanged(); notifyObservers(a); } else if (o instanceof Connection && ((Short) a).shortValue() == Connection.CONNECTION_CRASHED) { setChanged(); notifyObservers(new IOException("Connection Crashed")); } } }