/*
 * GNU.FREE 2002
 *
 * Copyright (c) 1999, 2000, 2001, 2002
 * The Free Software Foundation (www.fsf.org)
 *
 * GNU.FREE Co-ordinator: Jason Kitcat <jeep@free-project.org>
 *
 * GNU site: http://www.gnu.org/software/free/
 * 
 * FREE e-democracy site: http://www.free-project.org
 *
 * 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 2
 * 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 (COPYING); if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 */
 
/**
 * Comms Class
 * @version 0.7 23 July 2001
 * @author Jason Kitcat
 */
 
package FreeTest;

import java.io.*;
import java.net.*;
import java.util.*;

public class Comms {

	private Thread talker;

	// constant to hold address of regional server
	protected static final String R_address = "stephenson.swingdigital.com";
	// constant to hold address of electoral roll server
	protected static final String ER_address = "gibson.swingdigital.com";
	// constant to store value being used as FREE port number
	// For security reasons I recommend this is changed regularly
	protected static final int freePort = 1111;
	/** public and private keys for communications */
//#ifdef INSTALL
	protected static final String rt_public_key = "001101000108008193745AA3A2733EF1140758495439CB4CD188C4F2B5D2FA84C3C533465991257EAFC2BCAC0AC07F1531C97489723A353E7A1C911E687A5E834CD872B534480D8B4F9107E48C994A0D5B68870DE4DC3A51C604572446F166E02B8F234C44158FD373A06CFF30E3BBA2F1E670743D7B855CC2D3EF395D440A702D57013A5146171E4B7C78343FB2DAA47E56C63A2B5CFA57FF8892399F0A7D8E47A0203C687A158D3E0802AE02D3C1EA4AC625B641430FA9A1A50FC095461EED1DF401F93365CD650D02CFD4392BE1349B29900A0DCA648658FAFA3E8C3300E44C705AF3930F5EDF28B5D40C89251F440C9038DD9F533A849965EB71617D91A5CFD5621ED6A5D1";
//#ifdef INSTALL
	protected static final String er_public_key = "001101000108009539E6A8D4A7F01D33BBF0E9E273373874AC8A3D226FC75E7F8C464B673E0DF6BEA371B169EC1EDA382A4D5BBD1973963C0B57BE8B0EE16ADF3194D2EAE630B15E2E1BEF2AC34AA8061341D3F6D6010F72210A671F8653A3FC0B03F6F31FB0E480444AE98658D95404EE62C2A5C063F830A4DB52EEB2E02EE6E9310C2A95875CE1D8A1DE8BA03271198A15076F1D65574C1A8C1FF39FAEE8A43EDE11DE22E41ED8E3B1DBC57E58C978259B7A846998E5CFCEDF1EB75F12A6481FD86AA29E2F9184F0BF522F0553EF806927D167187F4F3A7233EB6F3080A7E131C0911EF82C08A86FE4C0F0B6F53E580F81568C59BFE4C131B78F1E66B879858D6C05060058B1";
//#ifdef INSTALL
	protected static final String fc_private_key = "";
	
	/** Holds the session key for GNU.FREE security protocol */
	private String session_key;
	
	private String fromServer;
	private Date check;
	private String message;
	private char type;
	protected int stressResult;
	protected Date stressBefore;
	protected Date stressAfter;
	protected boolean isStress;
	protected int stressClients;
	protected int stressCount;
	protected Vector checkStack;

	/* constructor */
	protected Comms() {
	
		checkStack = new Vector(1000);
		// unneccessary but just in case!
		message = "";
		fromServer = "";
		stressResult = 0;
		stressClients = 0;
		stressCount = 0;
		isStress = false;
	
	}

	/* simple acessor method */
	protected void setFromServer(String x) {
	
		fromServer = x;
	
	}
	
	/* simple acessor method */
	protected String getFromServer() {
	
		return fromServer;
	
	}
	
	/* simple acessor method */
	protected String getsession_key() {
	
		return session_key;
	
	}
	
	/* simple acessor method */
	protected void setsession_key(String x) {
	
		session_key = x;
	
	}
	
	/* simple acessor method */
	protected Date getCheck() {
	
		return check;
	
	}
	
	/* simple acessor method */
	protected void setCheck(Date t) {
	
		check = t;
	
	}
	
	/* simple acessor method */
	protected String getMessage() {
	
		return message;
	
	}

	/* simple acessor method */
	protected void setMessage(String t) {
	
		message = t;
	
	}

	/* simple acessor method */
	protected char getType() {
	
		return type;
	
	}

	/* simple acessor method */
	protected void setType(char t) {
	
		type = t;
	
	}
	
	protected void doneStress() {

		long elapsed;

		stressAfter = new Date();

		stressCount += 1;
		elapsed = stressAfter.getTime() - stressBefore.getTime();

		FTest.frame.showInfo2("Client " + stressCount + "/" + stressClients + " has been successful.");
		FTest.frame.showInfo2("Time taken so far: " + Long.toString(elapsed) + " ms");
	}
	

	/**
	 * sendVote creates check date for security and sends vote packet
	 *
	 * @param party  String to hold voter's choice
	 */
	 protected void sendVote(String party) {	 
		
		Runnable tk = new TCPClient(0);
		talker = new Thread(tk);

		String reply;
		String data;
		
		check = new Date();
		data = check.toString() + "-" + party;

		try {
			
			message = "V|" + data + "|" + AuthSys.makeDigest("V|" + data);

			type = 'V';
		
	 		talker.start();

			reply = fromServer;
			
	 	} catch (Exception e) {
	 		FTest.frame.showError("sendVote IO Error: " + e.getMessage());
	 	}
	 			
	 }  //EOF sendVote


	/**
	 * sendVote2 does not create check date for security sends vote packet
	 *
	 * @param party  String to hold voter's choice
	 */
	 protected void sendVote2(String data) {	 
		
		Runnable tk = new TCPClient(0);
		talker = new Thread(tk);

		String reply;

		try {
			
			setsession_key(RSAEncrypt.makeSessionKey());
			
			message = RSAEncrypt.pubEncrypt(rt_public_key,getsession_key()) + "-" + RSAEncrypt.blowEncrypt(getsession_key(),"V|" + data + "|" + AuthSys.makeDigest("V|" + data));

			type = 'V';
		
	 		talker.start();

			reply = fromServer;
			
	 	} catch (Exception e) {
	 		FTest.frame.showError("sendVote IO Error: " + e.getMessage());
	 	}
	 			
	 }  //EOF sendVote2


	/**
	 * sendVote3 creates check date for security and sends vote packet, but does not
	 * create MAC, this is supplied
	 *
	 * @param party  String to hold voter's choice
	 * @param MAC  Holds pseudo MAC to be sent
	 */
	 protected void sendVote3(String party, String MAC) {	 
		
		Runnable tk = new TCPClient(0);
		talker = new Thread(tk);

		String reply;
		String data;
		
		check = new Date();
		data = check.toString() + "-" + party;

		try {
			
			setsession_key(RSAEncrypt.makeSessionKey());
			
			message = RSAEncrypt.pubEncrypt(rt_public_key,getsession_key()) + "-" + RSAEncrypt.blowEncrypt(getsession_key(),"V|" + data + "|" + MAC);

			type = 'V';
		
	 		talker.start();

			reply = fromServer;
			
	 	} catch (Exception e) {
	 		FTest.frame.showError("sendVote IO Error: " + e.getMessage());
	 	}
	 			
	 }  //EOF sendVote3


	/* IMPORTANT NOTE: sendAuth is only a demo implementation and is not secure. This
	   method will need reimplementation depending on how you want to authorise voters.
	   In later versions of FREE I hope to make this more flexible.
	 */

	/**
	 * sendAuth dispatches a packet to the ERServer for voter authentication
	 *
	 * @param data  Carries username, code and password
	 */
	protected void sendAuth(String data) {
	
		Runnable tk = new TCPClient(0);
		Thread talker = new Thread(tk);

		String reply;
		
		type = 'E';
		message = "E|";
			
		try {
			setsession_key(RSAEncrypt.makeSessionKey());
			
			message = RSAEncrypt.pubEncrypt(er_public_key,getsession_key()) + "-" + RSAEncrypt.blowEncrypt(getsession_key(),message + data + "|" + AuthSys.makeDigest(message + data));
		
		 	talker.start();
		 	
		 	reply = fromServer;
		 	
	 	} catch (Exception e) {
	 		FTest.frame.showError("sendDiag IO Error: " + e.getMessage());
	 	}
	
	} //EOF sendAuth
	 

	/**
	 * sendAuth2 dispatches a packet to the ERServer for voter authentication
	 *   it also doesn't calculate a MAC
	 *
	 * @param data  Carries username, code and password
	 * @param MAC  Fake MAC for insertion
	 */
	protected void sendAuth2(String data, String MAC) {
	
		Runnable tk = new TCPClient(0);
		Thread talker = new Thread(tk);

		String reply;
		
		type = 'E';
		message = "E|";
			
		try {
			setsession_key(RSAEncrypt.makeSessionKey());
			
			message = RSAEncrypt.pubEncrypt(er_public_key,getsession_key()) + "-" + RSAEncrypt.blowEncrypt(getsession_key(),message + data + "|" + MAC);
		
		 	talker.start();
		 	
		 	reply = fromServer;
		 	
	 	} catch (Exception e) {
	 		FTest.frame.showError("sendDiag IO Error: " + e.getMessage());
	 	}
	
	} //EOF sendAuth2s
	 

	/**
	 * sendKey delivers a key to an ERServer for confirming someone has voted.
	 *
	 * @param akey  The key to send
	 */
	 protected void sendKey(String akey) throws Exception {
		
		Runnable tk = new TCPClient(0);
		Thread talker = new Thread(tk);

		String reply;
		
		type = 'K';

		try {
			setsession_key(RSAEncrypt.makeSessionKey());
			
			message = RSAEncrypt.pubEncrypt(er_public_key,getsession_key()) + "-" + RSAEncrypt.blowEncrypt(getsession_key(),"K|" + akey + "|" + AuthSys.makeDigest("K|" + akey));
			
			FTest.frame.showInfo("Sending AuthKey: " + message);
			
	 		talker.start();  // start communications

		 	reply = fromServer;
		 	
	 	} catch (Exception e) {
	 		FTest.frame.showError("sendKey IO Error: " + e.getMessage());
	 	}
	 			
	 }  //EOF sendKey


	/**
	 * sendDiag dispatches any diagnostic packets
	 *
	 * @param msg  Data for packet
	 */
	 protected void sendDiag(String msg) {	 
		
		Runnable tk = new TCPClient(0);
		Thread talker = new Thread(tk);

		String reply;
		String data;
		
		type = 'D';
		data = "D|" + msg;
	
		try {
			message = data + "|" + AuthSys.makeDigest(data);
		
		 	talker.start();
		 	
		 	reply = fromServer;
		 	
	 	} catch (Exception e) {
	 		FTest.frame.showError("sendDiag IO Error: " + e.getMessage());
	 	}
	 			
	 }  //EOF sendDiag

	
	
} //EOF Class