1. ScannedData now has a Channel and a SignedEncryptedBallot attributes,

rather than just 'data' attribute
2. Implemented a NetworkVirtualPrinter output device, and now both
   this class and the previous SystemConsoleOutputDevice extend the same
   new abstract class AsyncRunnableOutputDevice which supplies default
   implementations for the interface methods.
vbdev2
Hai Brenner 2016-06-28 11:32:00 +03:00
parent 3a5908ac49
commit 14fac728b3
5 changed files with 98 additions and 169 deletions

View File

@ -2,11 +2,16 @@ syntax = "proto3";
package meerkat;
import "meerkat/voting.proto";
option java_package = "meerkat.protobuf";
// Container for scanned data
message ScannedData {
bytes data = 1;
bytes channel = 1;
SignedEncryptedBallot signed_encrypted_ballot = 2;
}
// Container for error messages

View File

@ -2,7 +2,9 @@ package meerkat.pollingstation;
import com.google.common.util.concurrent.FutureCallback;
import com.google.protobuf.ByteString;
import meerkat.protobuf.Crypto.Signature;
import meerkat.protobuf.PollingStation.*;
import meerkat.protobuf.Voting.SignedEncryptedBallot;
import meerkat.rest.Constants;
import meerkat.rest.*;
@ -46,7 +48,7 @@ public class PollingStationWebScannerTest {
@Override
public void onSuccess(ScannedData result) {
dataIsAsExpected = result.getData().equals(expectedData.getData());
dataIsAsExpected = result.getChannel().equals(expectedData.getChannel());
semaphore.release();
}
@ -109,7 +111,7 @@ public class PollingStationWebScannerTest {
byte[] data = {(byte) 1, (byte) 2};
ScannedData scannedData = ScannedData.newBuilder()
.setData(ByteString.copyFrom(data))
.setChannel(ByteString.copyFrom(data))
.build();
scanner.subscribe(new ScanHandler(scannedData));

View File

@ -1,46 +1,30 @@
package meerkat.voting.output;
import com.google.common.util.concurrent.FutureCallback;
import com.google.protobuf.BoolValue;
import meerkat.protobuf.PollingStation.ScannedData;
import meerkat.protobuf.Voting.*;
import meerkat.rest.*;
import meerkat.protobuf.Voting.BallotSecrets;
import meerkat.protobuf.Voting.PlaintextBallot;
import meerkat.protobuf.Voting.SignedEncryptedBallot;
import meerkat.voting.controller.callbacks.ControllerCallback;
import meerkat.voting.output.outputcommands.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.client.*;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.util.concurrent.LinkedBlockingQueue;
import static meerkat.pollingstation.PollingStationConstants.*;
/**
* Created by hai on 27/06/16.
*/
public class AsyncRunnableOutputDevice implements BallotOutputDevice, Runnable {
public abstract class AsyncRunnableOutputDevice implements BallotOutputDevice, Runnable {
private Logger logger;
private LinkedBlockingQueue<OutputCommand> queue;
private volatile boolean shutDownHasBeenCalled;
private SignedEncryptedBallot signedEncryptedBallot;
private final WebTarget successfulPrintTarget;
public AsyncRunnableOutputDevice(String address) {
public AsyncRunnableOutputDevice() {
logger = LoggerFactory.getLogger(AsyncRunnableOutputDevice.class);
logger.info("A NetworkVirtualPrinter is constructed");
logger.info("AsyncRunnableOutputDevice is constructed");
queue = new LinkedBlockingQueue<>();
shutDownHasBeenCalled = false;
Client client = ClientBuilder.newClient();
client.register(ProtobufMessageBodyReader.class);
client.register(ProtobufMessageBodyWriter.class);
successfulPrintTarget = client.target(address).path(POLLING_STATION_WEB_SCANNER_SCAN_PATH);
}
@Override
@ -69,6 +53,15 @@ public class AsyncRunnableOutputDevice implements BallotOutputDevice, Runnable
}
abstract void doCommitToBallot(CommitOutputCommand command);
abstract void doAudit(AuditOutputCommand command);
abstract void doCastBallot(CastOutputCommand command);
abstract void doCancel(CancelOutputCommand command);
private void handleSingleCommand(OutputCommand command) {
if (command instanceof CommitOutputCommand) {
doCommitToBallot((CommitOutputCommand)command);
@ -118,44 +111,4 @@ public class AsyncRunnableOutputDevice implements BallotOutputDevice, Runnable
}
public void doCommitToBallot(CommitOutputCommand command) {
logger.debug("entered method doCommitToBallot");
signedEncryptedBallot = command.getSignedEncryptedBallot();
command.getCallback().onSuccess(null);
}
public void doAudit(AuditOutputCommand command) {
logger.debug("entered method doAudit");
signedEncryptedBallot = null;
command.getCallback().onSuccess(null);
}
public void doCastBallot(CastOutputCommand command) {
logger.debug("entered method doCastBallot");
ScannedData scannedData = ScannedData.newBuilder()
.setChannel(null) //TODO: fill the details for the channel to be able to send here
.setSignedEncryptedBallot(this.signedEncryptedBallot)
.build();
Response response = successfulPrintTarget.request(Constants.MEDIATYPE_PROTOBUF).post(Entity.entity(scannedData, Constants.MEDIATYPE_PROTOBUF));
BoolValue b = response.readEntity(BoolValue.class);
response.close();
if (b.getValue()) {
command.getCallback().onSuccess(null);
}
else {
command.getCallback().onFailure(new IOException());
}
}
public void doCancel(CancelOutputCommand command) {
logger.debug("entered method doCancel");
signedEncryptedBallot = null;
command.getCallback().onSuccess(null);
}
}

View File

@ -1,37 +1,84 @@
package meerkat.voting.output;
import com.google.protobuf.BoolValue;
import meerkat.pollingstation.PollingStationScanner;
import meerkat.protobuf.PollingStation.*;
import meerkat.rest.*;
import meerkat.protobuf.PollingStation.ScannedData;
import meerkat.protobuf.Voting.SignedEncryptedBallot;
import meerkat.rest.Constants;
import meerkat.rest.ProtobufMessageBodyReader;
import meerkat.rest.ProtobufMessageBodyWriter;
import meerkat.voting.output.outputcommands.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.client.*;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;
import java.io.IOException;
import static meerkat.pollingstation.PollingStationConstants.*;
import static meerkat.pollingstation.PollingStationConstants.POLLING_STATION_WEB_SCANNER_SCAN_PATH;
/**
* Created by hai on 27/06/16.
*/
public class NetworkVirtualPrinter implements PollingStationScanner.Producer {
public class NetworkVirtualPrinter extends AsyncRunnableOutputDevice {
WebTarget successfulScanPath;
WebTarget errorPath;
private Logger logger;
private SignedEncryptedBallot signedEncryptedBallot;
private final WebTarget successfulPrintTarget;
public NetworkVirtualPrinter(String address) {
super();
logger = LoggerFactory.getLogger(NetworkVirtualPrinter.class);
logger.info("A NetworkVirtualPrinter is constructed");
Client client = ClientBuilder.newClient();
client.register(ProtobufMessageBodyReader.class);
client.register(ProtobufMessageBodyWriter.class);
successfulScanPath = client.target(address).path(POLLING_STATION_WEB_SCANNER_SCAN_PATH);
errorPath = client.target(address).path(POLLING_STATION_WEB_SCANNER_ERROR_PATH);
successfulPrintTarget = client.target(address).path(POLLING_STATION_WEB_SCANNER_SCAN_PATH);
}
@Override
public BoolValue newScan(ScannedData scannedData) {
return null;
public void doCommitToBallot(CommitOutputCommand command) {
logger.debug("entered method doCommitToBallot");
signedEncryptedBallot = command.getSignedEncryptedBallot();
command.getCallback().onSuccess(null);
}
@Override
public BoolValue reportScanError(ErrorMsg errorMsg) {
return null;
public void doAudit(AuditOutputCommand command) {
logger.debug("entered method doAudit");
signedEncryptedBallot = null;
command.getCallback().onSuccess(null);
}
public void doCastBallot(CastOutputCommand command) {
logger.debug("entered method doCastBallot");
ScannedData scannedData = ScannedData.newBuilder()
.setChannel(null) //TODO: fill the details for the channel to be able to send here
.setSignedEncryptedBallot(this.signedEncryptedBallot)
.build();
Response response = successfulPrintTarget.request(Constants.MEDIATYPE_PROTOBUF).post(Entity.entity(scannedData, Constants.MEDIATYPE_PROTOBUF));
BoolValue b = response.readEntity(BoolValue.class);
response.close();
if (b.getValue()) {
command.getCallback().onSuccess(null);
}
else {
command.getCallback().onFailure(new IOException());
}
}
public void doCancel(CancelOutputCommand command) {
logger.debug("entered method doCancel");
signedEncryptedBallot = null;
command.getCallback().onSuccess(null);
}
}

View File

@ -1,96 +1,28 @@
package meerkat.voting.output;
import com.google.common.util.concurrent.FutureCallback;
import com.google.protobuf.ByteString;
import meerkat.protobuf.Crypto.*;
import meerkat.protobuf.Voting.*;
import meerkat.voting.controller.callbacks.ControllerCallback;
import meerkat.voting.output.outputcommands.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.LinkedBlockingQueue;
/**
* A toy OutputDevice class
* outputs everything simply to the System console
*/
public class SystemConsoleOutputDevice implements BallotOutputDevice, Runnable {
public class SystemConsoleOutputDevice extends AsyncRunnableOutputDevice {
private Logger logger;
private LinkedBlockingQueue<OutputCommand> queue;
private volatile boolean shutDownHasBeenCalled;
public SystemConsoleOutputDevice () {
super();
logger = LoggerFactory.getLogger(SystemConsoleOutputDevice.class);
logger.info("A SystemConsoleOutputDevice is constructed");
queue = new LinkedBlockingQueue<>();
shutDownHasBeenCalled = false;
}
/*
* Returns the UTF8 decoding of byte-string data
*/
private static String bytesToString(ByteString data) {
return data.toStringUtf8();
}
@Override
public void run () {
logger.info("UI starts running");
while (! wasShutDownCalled()) {
try {
OutputCommand command = queue.take();
handleSingleCommand(command);
}
catch (InterruptedException e) {
logger.warn ("Interrupted while reading from command queue " + e);
}
}
}
private boolean wasShutDownCalled () {
return shutDownHasBeenCalled;
}
@Override
public void callShutDown() {
logger.info("callShutDown command has been called");
shutDownHasBeenCalled = true;
queue.clear();
}
private void handleSingleCommand(OutputCommand command) {
if (command instanceof CommitOutputCommand) {
doCommitToBallot((CommitOutputCommand)command);
}
else if (command instanceof AuditOutputCommand) {
doAudit((AuditOutputCommand)command);
}
else if (command instanceof CastOutputCommand) {
doCastBallot((CastOutputCommand)command);
}
else if (command instanceof CancelOutputCommand) {
doCancel((CancelOutputCommand)command);
}
else {
String errorMessage = "handleSingleCommand: unknown type of OutputCommand received: " +
command.getClass().getName();
logger.error(errorMessage);
throw new RuntimeException(errorMessage);
}
}
@Override
public void commitToBallot(PlaintextBallot plaintextBallot,
SignedEncryptedBallot signedEncryptedBallot,
FutureCallback<Void> callback) {
logger.debug("Output interface call to commit to ballot");
queue.add(new CommitOutputCommand(plaintextBallot, signedEncryptedBallot, (ControllerCallback)callback));
}
public void doCommitToBallot(CommitOutputCommand command) {
logger.debug("entered method doCommitToBallot");
@ -111,12 +43,6 @@ public class SystemConsoleOutputDevice implements BallotOutputDevice, Runnable {
}
@Override
public void audit(BallotSecrets ballotSecrets, FutureCallback<Void> callback) {
logger.debug("an interface call to audit");
queue.add(new AuditOutputCommand(ballotSecrets, (ControllerCallback)callback));
}
public void doAudit(AuditOutputCommand command) {
logger.debug("entered method doAudit");
System.out.println("Auditing");
@ -127,12 +53,6 @@ public class SystemConsoleOutputDevice implements BallotOutputDevice, Runnable {
}
@Override
public void castBallot(FutureCallback<Void> callback) {
logger.debug("an interface call to cast ballot");
queue.add(new CastOutputCommand((ControllerCallback)callback));
}
public void doCastBallot(CastOutputCommand command) {
logger.debug("entered method doCastBallot");
System.out.println("Ballot finalized for casting!");
@ -140,12 +60,6 @@ public class SystemConsoleOutputDevice implements BallotOutputDevice, Runnable {
}
@Override
public void cancelBallot(FutureCallback<Void> callback) {
logger.debug("an interface call to cancel the output");
queue.add(new CancelOutputCommand((ControllerCallback)callback));
}
public void doCancel(CancelOutputCommand command) {
logger.debug("entered method doCancel");
System.out.println("Ballot cancelled!");
@ -165,4 +79,12 @@ public class SystemConsoleOutputDevice implements BallotOutputDevice, Runnable {
System.out.println(bytesToString(data));
}
/*
* Returns the UTF8 decoding of byte-string data
*/
private static String bytesToString(ByteString data) {
return data.toStringUtf8();
}
}