Interim merge for branch 'master' into crypto-primitives
commit
c76724f599
|
@ -13,3 +13,4 @@ out
|
|||
*.prefs
|
||||
*.project
|
||||
*.classpath
|
||||
bulletin-board-server/local-instances/meerkat.db
|
||||
|
|
|
@ -57,6 +57,21 @@ dependencies {
|
|||
|
||||
/*==== You probably don't have to edit below this line =======*/
|
||||
|
||||
// Setup test configuration that can appear as a dependency in
|
||||
// other subprojects
|
||||
configurations {
|
||||
testOutput.extendsFrom (testCompile)
|
||||
}
|
||||
|
||||
task testJar(type: Jar, dependsOn: testClasses) {
|
||||
classifier = 'tests'
|
||||
from sourceSets.test.output
|
||||
}
|
||||
|
||||
artifacts {
|
||||
testOutput testJar
|
||||
}
|
||||
|
||||
// The run task added by the application plugin
|
||||
// is also of type JavaExec.
|
||||
tasks.withType(JavaExec) {
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
/bin/
|
|
@ -9,8 +9,10 @@ apply plugin: 'java'
|
|||
apply plugin: 'eclipse'
|
||||
apply plugin: 'idea'
|
||||
|
||||
//apply plugin: 'application'
|
||||
|
||||
//apply plugin: 'jetty'
|
||||
//mainClassName = 'Demo'
|
||||
//mainClassName = 'SQLiteIntegrationTest'
|
||||
|
||||
apply plugin: 'maven-publish'
|
||||
|
||||
|
@ -42,6 +44,8 @@ dependencies {
|
|||
|
||||
// Jersey for RESTful API
|
||||
compile 'org.glassfish.jersey.containers:jersey-container-servlet:2.22.+'
|
||||
compile 'org.xerial:sqlite-jdbc:3.7.+'
|
||||
|
||||
|
||||
// Logging
|
||||
compile 'org.slf4j:slf4j-api:1.7.7'
|
||||
|
@ -51,6 +55,9 @@ dependencies {
|
|||
// Google protobufs
|
||||
compile 'com.google.protobuf:protobuf-java:3.+'
|
||||
|
||||
// Depend on test resources from meerkat-common
|
||||
testCompile project(path: ':meerkat-common', configuration: 'testOutput')
|
||||
|
||||
testCompile 'junit:junit:4.+'
|
||||
|
||||
runtime 'org.codehaus.groovy:groovy:2.4.+'
|
||||
|
@ -61,6 +68,10 @@ test {
|
|||
exclude '**/*IntegrationTest*'
|
||||
}
|
||||
|
||||
task debugIntegrationTest(type: Test){
|
||||
include '**/*IntegrationTest*'
|
||||
debug = true
|
||||
}
|
||||
|
||||
task integrationTest(type: Test) {
|
||||
include '**/*IntegrationTest*'
|
||||
|
@ -68,7 +79,9 @@ task integrationTest(type: Test) {
|
|||
|
||||
gretty {
|
||||
httpPort = 8081
|
||||
contextPath = '/'
|
||||
integrationTestTask = 'integrationTest'
|
||||
loggingLevel = 'TRACE'
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ import javax.servlet.http.HttpServletResponse;
|
|||
import meerkat.bulletinboard.BulletinBoardServer;
|
||||
import meerkat.bulletinboard.sqlserver.SQLiteBulletinBoardServer;
|
||||
import meerkat.comm.CommunicationException;
|
||||
import meerkat.protobuf.Voting.BulletinBoardMessage;
|
||||
import meerkat.protobuf.BulletinBoardAPI.*;
|
||||
|
||||
public class BulletinBoardHttpServer extends HttpServlet {
|
||||
|
||||
|
|
|
@ -3,8 +3,7 @@ package meerkat.bulletinboard.service;
|
|||
import com.google.protobuf.ByteString;
|
||||
import com.google.protobuf.Message;
|
||||
import meerkat.protobuf.Crypto;
|
||||
import meerkat.protobuf.Voting;
|
||||
import meerkat.protobuf.Voting.BulletinBoardMessage;
|
||||
import meerkat.protobuf.BulletinBoardAPI.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
@ -16,7 +15,7 @@ public class HelloProtoBuf {
|
|||
public Message sayHello() {
|
||||
BulletinBoardMessage.Builder msg = BulletinBoardMessage.newBuilder();
|
||||
|
||||
Voting.UnsignedBulletinBoardMessage.Builder unsigned = Voting.UnsignedBulletinBoardMessage.newBuilder();
|
||||
UnsignedBulletinBoardMessage.Builder unsigned = UnsignedBulletinBoardMessage.newBuilder();
|
||||
unsigned.setData(ByteString.copyFromUtf8("Hello World!"));
|
||||
List<String> tags = Arrays.asList("Greetings", "FirstPrograms");
|
||||
unsigned.addAllTags(tags);
|
||||
|
@ -24,7 +23,7 @@ public class HelloProtoBuf {
|
|||
|
||||
Crypto.Signature.Builder sig = Crypto.Signature.newBuilder();
|
||||
sig.setData(ByteString.copyFromUtf8("deadbeef"));
|
||||
msg.setSig(sig);
|
||||
msg.addSig(sig);
|
||||
|
||||
return msg.build();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package meerkat.bulletinboard.sqlserver;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.protobuf.ProtocolStringList;
|
||||
|
@ -11,13 +12,12 @@ import java.sql.SQLException;
|
|||
import java.sql.Statement;
|
||||
|
||||
import meerkat.bulletinboard.BulletinBoardServer;
|
||||
import meerkat.bulletinboard.MessageFilter;
|
||||
import meerkat.comm.CommunicationException;
|
||||
import meerkat.protobuf.BulletinBoardAPI.*;
|
||||
import meerkat.protobuf.Crypto.Signature;
|
||||
import meerkat.protobuf.Crypto.SignatureVerificationKey;
|
||||
import meerkat.protobuf.Voting.BulletinBoardMessage;
|
||||
import meerkat.crypto.Digest;
|
||||
import meerkat.crypto.concrete.SHA256Digest;
|
||||
import meerkat.protobuf.Voting.MessageID;
|
||||
|
||||
public abstract class BulletinBoardSQLServer implements BulletinBoardServer{
|
||||
|
||||
|
@ -53,53 +53,109 @@ public abstract class BulletinBoardSQLServer implements BulletinBoardServer{
|
|||
* @return TRUE if the message is authenticated and FALSE otherwise.
|
||||
*/
|
||||
private boolean verifyMessage(BulletinBoardMessage msg) {
|
||||
//TODO: Replace with actual verification.
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This procedure makes sure that all tags in the given list have an entry in the tags list.
|
||||
* @param tagIterator
|
||||
* This procedure makes sure that all tags in the given list have an entry in the tags table.
|
||||
* @param tags
|
||||
*/
|
||||
protected abstract void insertNewTags(String[] tags) throws CommunicationException;
|
||||
protected abstract void insertNewTags(String[] tags) throws SQLException;
|
||||
|
||||
/**
|
||||
* This procedure is used to convert a boolean to a BoolMsg.
|
||||
* @param b is the boolean to convert.
|
||||
* @return a ProtoBuf message with boolean payload.
|
||||
*/
|
||||
private BoolMsg boolToBoolMsg(boolean b){
|
||||
return BoolMsg.newBuilder()
|
||||
.setValue(b)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean postMessage(BulletinBoardMessage msg) throws CommunicationException {
|
||||
public BoolMsg postMessage(BulletinBoardMessage msg) throws CommunicationException {
|
||||
|
||||
if (!verifyMessage(msg)) {
|
||||
return false;
|
||||
return boolToBoolMsg(false);
|
||||
}
|
||||
|
||||
PreparedStatement pstmt;
|
||||
ResultSet rs;
|
||||
String sql;
|
||||
byte[] msgID;
|
||||
long entryNum;
|
||||
|
||||
ProtocolStringList tagList;
|
||||
String[] tags;
|
||||
|
||||
List<Signature> signatureList;
|
||||
Signature[] signatures;
|
||||
|
||||
// Calculate message ID (depending only on the the unsigned message)
|
||||
|
||||
digest.reset();
|
||||
digest.update(msg);
|
||||
digest.update(msg.getMsg());
|
||||
|
||||
msgID = digest.digest();
|
||||
|
||||
// Add message to table if needed and store entry number of message.
|
||||
|
||||
try {
|
||||
|
||||
sql = "INSERT INTO MsgTable (Id, Data, Signature) VALUES(?,?,?)";
|
||||
pstmt = connection.prepareStatement(sql);
|
||||
pstmt.setBytes(1, msgID);
|
||||
pstmt.setBytes(2,msg.getMsg().getData().toByteArray());
|
||||
pstmt.setBytes(3,msg.getSig().toByteArray());
|
||||
pstmt.executeUpdate();
|
||||
sql = "SELECT EntryNum From MsgTable WHERE MsgId = ?";
|
||||
pstmt = connection.prepareStatement(sql);
|
||||
pstmt.setBytes(1, msgID);
|
||||
rs = pstmt.executeQuery();
|
||||
|
||||
if (rs.next()){
|
||||
|
||||
entryNum = rs.getLong(1);
|
||||
|
||||
} else{
|
||||
|
||||
sql = "INSERT INTO MsgTable (MsgId, Msg) VALUES(?,?)";
|
||||
pstmt = connection.prepareStatement(sql);
|
||||
pstmt.setBytes(1, msgID);
|
||||
pstmt.setBytes(2, msg.toByteArray());
|
||||
pstmt.executeUpdate();
|
||||
|
||||
rs = pstmt.getGeneratedKeys();
|
||||
rs.next();
|
||||
entryNum = rs.getLong(1);
|
||||
|
||||
}
|
||||
|
||||
pstmt.close();
|
||||
|
||||
} catch (SQLException e) {
|
||||
throw new CommunicationException("Error inserting into MsgTable: " + e.getMessage());
|
||||
}
|
||||
|
||||
// Retrieve tags and store new ones in tag table.
|
||||
|
||||
try {
|
||||
|
||||
tagList = msg.getMsg().getTagsList();
|
||||
tags = new String[tagList.size()];
|
||||
tags = tagList.toArray(tags);
|
||||
|
||||
insertNewTags(tags);
|
||||
|
||||
sql = "INSERT INTO MsgTagTable (MsgId, TagId) SELECT (?, TagId) FROM TagTable WHERE tag=?";
|
||||
} catch (SQLException e) {
|
||||
throw new CommunicationException(e.getMessage());
|
||||
}
|
||||
|
||||
// Connect message to tags.
|
||||
|
||||
try{
|
||||
sql = "INSERT OR IGNORE INTO MsgTagTable (TagId, EntryNum) SELECT TagTable.TagId, ? AS EntryNum FROM TagTable WHERE Tag = ?";
|
||||
pstmt = connection.prepareStatement(sql);
|
||||
|
||||
pstmt.setLong(1, entryNum);
|
||||
|
||||
for (String tag : tags){
|
||||
pstmt.setBytes(1, msgID);
|
||||
pstmt.setString(2, tag);
|
||||
pstmt.addBatch();
|
||||
}
|
||||
|
@ -108,19 +164,43 @@ public abstract class BulletinBoardSQLServer implements BulletinBoardServer{
|
|||
pstmt.close();
|
||||
|
||||
} catch (SQLException e) {
|
||||
throw new CommunicationException("Error accessing DB: " + e.getMessage());
|
||||
throw new CommunicationException("Error Linking tags: " + e.getMessage());
|
||||
}
|
||||
|
||||
// Retrieve signatures.
|
||||
|
||||
signatureList = msg.getSigList();
|
||||
signatures = new Signature[signatureList.size()];
|
||||
signatures = signatureList.toArray(signatures);
|
||||
|
||||
// Connect message to signatures.
|
||||
|
||||
try{
|
||||
sql = "INSERT OR IGNORE INTO SignatureTable (EntryNum, SignerId, Signature) VALUES (?,?,?)";
|
||||
pstmt = connection.prepareStatement(sql);
|
||||
|
||||
pstmt.setLong(1, entryNum);
|
||||
|
||||
for (Signature sig : signatures){
|
||||
|
||||
pstmt.setBytes(2, sig.getSignerId().toByteArray());
|
||||
pstmt.setBytes(3, sig.toByteArray());
|
||||
pstmt.addBatch();
|
||||
}
|
||||
|
||||
pstmt.executeBatch();
|
||||
pstmt.close();
|
||||
|
||||
} catch (SQLException e) {
|
||||
throw new CommunicationException("Error Linking tags: " + e.getMessage());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BulletinBoardMessage> readMessages(MessageFilter filter, int max) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
return boolToBoolMsg(true);
|
||||
}
|
||||
|
||||
public void testPrint(){
|
||||
public String testPrint(){
|
||||
|
||||
String s = "";
|
||||
|
||||
try {
|
||||
|
||||
|
@ -128,20 +208,30 @@ public abstract class BulletinBoardSQLServer implements BulletinBoardServer{
|
|||
ResultSet rs = statement.executeQuery("select * from MsgTable");
|
||||
while (rs.next()) {
|
||||
// read the result set
|
||||
System.out.println("data = " + rs.getString("Data"));
|
||||
System.out.println("id = " + rs.getInt("Id"));
|
||||
s += "entry = " + rs.getInt("EntryNum") + " \n";
|
||||
s += "id = " + Arrays.toString(rs.getBytes("MsgId")) + " \n";
|
||||
s += "msg = " + Arrays.toString(rs.getBytes("Msg")) + " \n";
|
||||
s += "signer ID = " + Arrays.toString(rs.getBytes("SignerId")) + "\t\n<BR>";
|
||||
}
|
||||
|
||||
rs = statement.executeQuery("select * from TagTable");
|
||||
while (rs.next()) {
|
||||
// read the result set
|
||||
s += "Tag = " + rs.getString("Tag") + " \n";
|
||||
s += "TagId = " + rs.getInt("TagId") + "\t\n<BR>";
|
||||
}
|
||||
|
||||
rs = statement.executeQuery("select * from MsgTagTable");
|
||||
while (rs.next()) {
|
||||
// read the result set
|
||||
System.out.println("MsgId = " + rs.getInt("MsgId"));
|
||||
System.out.println("TagId = " + rs.getString("TagId"));
|
||||
s += "MsgId = " + Arrays.toString(rs.getBytes("MsgId")) + " \n";
|
||||
s += "TagId = " + rs.getInt("TagId") + "\t\n<BR>";
|
||||
}
|
||||
} catch(SQLException e){
|
||||
System.out.println("Error reading from DB");
|
||||
s += "Error reading from DB";
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,15 +2,17 @@ package meerkat.bulletinboard.sqlserver;
|
|||
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.List;
|
||||
|
||||
import meerkat.bulletinboard.MessageFilter;
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
|
||||
import meerkat.protobuf.BulletinBoardAPI.*;
|
||||
import meerkat.protobuf.Crypto.Signature;
|
||||
import meerkat.bulletinboard.sqlserver.BulletinBoardSQLServer;
|
||||
import meerkat.comm.CommunicationException;
|
||||
import meerkat.protobuf.Voting.BulletinBoardMessage;
|
||||
|
||||
|
||||
public class SQLiteBulletinBoardServer extends BulletinBoardSQLServer {
|
||||
|
||||
|
@ -20,20 +22,24 @@ public class SQLiteBulletinBoardServer extends BulletinBoardSQLServer {
|
|||
* This procedure initializes:
|
||||
* 1. The database connection
|
||||
* 2. The database tables (if they do not yet exist).
|
||||
* 3.
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void init() throws CommunicationException {
|
||||
|
||||
try{
|
||||
|
||||
connection = DriverManager.getConnection("jdbc:sqlite:./local-instances/meerkat.db");
|
||||
connection = DriverManager.getConnection("jdbc:sqlite:local-instances/meerkat.db");
|
||||
Statement statement = connection.createStatement();
|
||||
statement.setQueryTimeout(TIMEOUT);
|
||||
|
||||
statement.executeUpdate("CREATE TABLE IF NOT EXISTS MsgTable (EntryNum INTEGER, Id varbinary(1000) UNIQUE, Data varbinary(1000), Signature varbinary(1000), PRIMARY KEY (EntryNum ASC))");
|
||||
statement.executeUpdate("CREATE TABLE IF NOT EXISTS TagTable (Id int, Tag v archar(50) UNIQUE, PRIMARY KEY (Id ASC))");
|
||||
statement.executeUpdate("CREATE TABLE IF NOT EXISTS MsgTagTable (MsgId varbinary(1000), TagId int, FOREIGN KEY (MsgId) REFERENCES MsgTable(Id), FOREIGN KEY (TagId) REFERENCES TagTable(Id))");
|
||||
|
||||
statement.executeUpdate("CREATE TABLE IF NOT EXISTS MsgTable (EntryNum INTEGER PRIMARY KEY, MsgId BLOB UNIQUE, Msg BLOB)");
|
||||
|
||||
statement.executeUpdate("CREATE TABLE IF NOT EXISTS TagTable (TagId INTEGER PRIMARY KEY, Tag varchar(50) UNIQUE)");
|
||||
statement.executeUpdate("CREATE TABLE IF NOT EXISTS MsgTagTable (EntryNum BLOB, TagId INTEGER, FOREIGN KEY (EntryNum) REFERENCES MsgTable(EntryNum), FOREIGN KEY (TagId) REFERENCES TagTable(TagId), UNIQUE (EntryNum, TagID))");
|
||||
|
||||
statement.executeUpdate("CREATE TABLE IF NOT EXISTS SignatureTable (EntryNum BLOB, SignerId BLOB, Signature BLOB UNIQUE, FOREIGN KEY (EntryNum) REFERENCES MsgTable(EntryNum))");
|
||||
statement.executeUpdate("CREATE INDEX IF NOT EXISTS SignerIndex ON SignatureTable(SignerId)");
|
||||
|
||||
statement.close();
|
||||
|
||||
|
@ -41,18 +47,11 @@ public class SQLiteBulletinBoardServer extends BulletinBoardSQLServer {
|
|||
|
||||
} catch (SQLException e) {
|
||||
|
||||
throw new CommunicationException("Couldn't form a connection with the database");
|
||||
throw new CommunicationException("Couldn't form a connection with the database" + e.getMessage());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<BulletinBoardMessage> readMessages(MessageFilter filter, int max) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
public void close() throws CommunicationException{
|
||||
|
||||
|
@ -66,9 +65,8 @@ public class SQLiteBulletinBoardServer extends BulletinBoardSQLServer {
|
|||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void insertNewTags(String[] tags) throws CommunicationException {
|
||||
protected void insertNewTags(String[] tags) throws SQLException {
|
||||
|
||||
PreparedStatement pstmt;
|
||||
String sql;
|
||||
|
@ -87,9 +85,178 @@ public class SQLiteBulletinBoardServer extends BulletinBoardSQLServer {
|
|||
pstmt.close();
|
||||
|
||||
} catch (SQLException e){
|
||||
throw new CommunicationException("Error adding new tags to table");
|
||||
throw new SQLException("Error adding new tags to table: " + e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public BoolMsg postMessage(BulletinBoardMessage msg) throws CommunicationException {
|
||||
return super.postMessage(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BulletinBoardMessageList readMessages(MessageFilterList filterList) throws CommunicationException{
|
||||
|
||||
PreparedStatement pstmt;
|
||||
ResultSet messages, signatures;
|
||||
|
||||
long entryNum;
|
||||
BulletinBoardMessageList.Builder resultListBuilder = BulletinBoardMessageList.newBuilder();
|
||||
BulletinBoardMessage.Builder messageBuilder;
|
||||
|
||||
String sql;
|
||||
String sqlSuffix = "";
|
||||
|
||||
List<MessageFilter> filters = filterList.getFilterList();
|
||||
int i;
|
||||
|
||||
boolean tagsRequired = false;
|
||||
boolean signaturesRequired = false;
|
||||
|
||||
boolean isFirstFilter = true;
|
||||
|
||||
// Check if Tag/Signature tables are required for filtering purposes.
|
||||
|
||||
for (MessageFilter filter : filters){
|
||||
if (filter.getType() == FilterType.TAG){
|
||||
tagsRequired = true;
|
||||
} else if (filter.getType() == FilterType.SIGNER_ID){
|
||||
signaturesRequired = true;
|
||||
}
|
||||
}
|
||||
|
||||
sql = "SELECT MsgTable.EntryNum, MsgTable.Msg FROM MsgTable";
|
||||
|
||||
if (tagsRequired){
|
||||
sql += " INNER JOIN MsgTagTable ON MsgTable.EntryNum = MsgTagTable.EntryNum";
|
||||
sql += " INNER JOIN TagTable ON TagTable.TagId = MsgTagTable.TagId";
|
||||
}
|
||||
|
||||
if (signaturesRequired){
|
||||
sql += " INNER JOIN SignatureTable ON SignatureTable.EntryNum = MsgTable.EntryNum";
|
||||
}
|
||||
|
||||
// Add conditions.
|
||||
|
||||
if (!filters.isEmpty()){
|
||||
sql += " WHERE";
|
||||
|
||||
for (MessageFilter filter : filters){
|
||||
|
||||
if (filter.getType().getNumber() != FilterType.MAX_MESSAGES_VALUE){
|
||||
if (isFirstFilter){
|
||||
isFirstFilter = false;
|
||||
} else{
|
||||
sql += " AND";
|
||||
}
|
||||
}
|
||||
|
||||
switch (filter.getType().getNumber()){
|
||||
case FilterType.EXACT_ENTRY_VALUE:
|
||||
sql += " MsgTable.EntryNum = ?";
|
||||
break;
|
||||
case FilterType.MAX_ENTRY_VALUE:
|
||||
sql += " MsgTable.EntryNum <= ?";
|
||||
break;
|
||||
case FilterType.MAX_MESSAGES_VALUE:
|
||||
sqlSuffix += " LIMIT = ?";
|
||||
break;
|
||||
case FilterType.MSG_ID_VALUE:
|
||||
sql += " MsgTableMsgId = ?";
|
||||
break;
|
||||
case FilterType.SIGNER_ID_VALUE:
|
||||
sql += " SignatureTable.SignerId = ?";
|
||||
break;
|
||||
case FilterType.TAG_VALUE:
|
||||
sql += " TagTable.Tag = ?";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sql += sqlSuffix;
|
||||
}
|
||||
|
||||
// Make query.
|
||||
|
||||
try {
|
||||
pstmt = connection.prepareStatement(sql);
|
||||
|
||||
// Specify values for filters.
|
||||
|
||||
i = 1;
|
||||
for (MessageFilter filter : filters){
|
||||
|
||||
switch (filter.getType().getNumber()){
|
||||
|
||||
case FilterType.EXACT_ENTRY_VALUE: // Go through.
|
||||
case FilterType.MAX_ENTRY_VALUE:
|
||||
pstmt.setLong(i, filter.getEntry());
|
||||
i++;
|
||||
break;
|
||||
|
||||
case FilterType.MSG_ID_VALUE: // Go through.
|
||||
case FilterType.SIGNER_ID_VALUE:
|
||||
pstmt.setBytes(i, filter.getId().toByteArray());
|
||||
i++;
|
||||
break;
|
||||
|
||||
case FilterType.TAG_VALUE:
|
||||
pstmt.setString(i, filter.getTag());
|
||||
break;
|
||||
|
||||
// The max-messages condition is applied as a suffix. Therefore, it is treated differently.
|
||||
case FilterType.MAX_MESSAGES_VALUE:
|
||||
pstmt.setLong(filters.size(), filter.getMaxMessages());
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Run query.
|
||||
|
||||
messages = pstmt.executeQuery();
|
||||
|
||||
// Compile list of messages.
|
||||
|
||||
sql = "SELECT Signature FROM SignatureTable WHERE EntryNum = ?";
|
||||
pstmt = connection.prepareStatement(sql);
|
||||
|
||||
while (messages.next()){
|
||||
|
||||
// Get entry number and retrieve signatures.
|
||||
|
||||
entryNum = messages.getLong(1);
|
||||
pstmt.setLong(1, entryNum);
|
||||
signatures = pstmt.executeQuery();
|
||||
|
||||
// Create message and append signatures.
|
||||
|
||||
messageBuilder = BulletinBoardMessage.newBuilder()
|
||||
.setEntryNum(entryNum)
|
||||
.setMsg(UnsignedBulletinBoardMessage.parseFrom(messages.getBytes(2)));
|
||||
|
||||
while (signatures.next()){
|
||||
messageBuilder.addSig(Signature.parseFrom(signatures.getBytes(1)));
|
||||
}
|
||||
|
||||
// Finalize message and add to message list.
|
||||
|
||||
resultListBuilder.addMessage(messageBuilder.build());
|
||||
|
||||
}
|
||||
|
||||
pstmt.close();
|
||||
|
||||
} catch (SQLException e){
|
||||
throw new CommunicationException("Error reading messages from DB: " + e.getMessage());
|
||||
} catch (InvalidProtocolBufferException e) {
|
||||
throw new CommunicationException("Invalid data from DB: " + e.getMessage());
|
||||
}
|
||||
|
||||
//Combine results and return.
|
||||
|
||||
return resultListBuilder.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
package meerkat.bulletinboard.webapp;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import meerkat.bulletinboard.BulletinBoardServer;
|
||||
import meerkat.bulletinboard.sqlserver.SQLiteBulletinBoardServer;
|
||||
import meerkat.comm.CommunicationException;
|
||||
import meerkat.protobuf.BulletinBoardAPI.BoolMsg;
|
||||
import meerkat.protobuf.BulletinBoardAPI.BulletinBoardMessage;
|
||||
import meerkat.protobuf.BulletinBoardAPI.BulletinBoardMessageList;
|
||||
import meerkat.protobuf.BulletinBoardAPI.MessageFilterList;
|
||||
import meerkat.rest.Constants;
|
||||
|
||||
@Path("/sqlserver")
|
||||
public class BulletinBoardWebApp implements BulletinBoardServer{
|
||||
|
||||
BulletinBoardServer bulletinBoard;
|
||||
|
||||
@PostConstruct
|
||||
@Override
|
||||
public void init() throws CommunicationException {
|
||||
bulletinBoard = new SQLiteBulletinBoardServer();
|
||||
bulletinBoard.init();
|
||||
}
|
||||
|
||||
@Path("postmessage")
|
||||
@POST
|
||||
@Consumes(Constants.MEDIATYPE_PROTOBUF)
|
||||
@Produces(Constants.MEDIATYPE_PROTOBUF)
|
||||
@Override
|
||||
public BoolMsg postMessage(BulletinBoardMessage msg) throws CommunicationException {
|
||||
return bulletinBoard.postMessage(msg);
|
||||
}
|
||||
|
||||
@Path("readmessages")
|
||||
@POST
|
||||
@Consumes(Constants.MEDIATYPE_PROTOBUF)
|
||||
@Produces(Constants.MEDIATYPE_PROTOBUF)
|
||||
@Override
|
||||
public BulletinBoardMessageList readMessages(MessageFilterList filterList) throws CommunicationException {
|
||||
return bulletinBoard.readMessages(filterList);
|
||||
}
|
||||
|
||||
@Override
|
||||
@PreDestroy
|
||||
public void close() throws CommunicationException {
|
||||
bulletinBoard.close();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.TEXT_PLAIN)
|
||||
public String test() {
|
||||
return "This BulletinBoard is up and running!\n Please consult the API documents to perform queries.";
|
||||
}
|
||||
|
||||
}
|
|
@ -1,22 +1,50 @@
|
|||
package meerkat.bulletinboard.webapp;
|
||||
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import com.google.protobuf.Message;
|
||||
import meerkat.bulletinboard.service.HelloProtoBuf;
|
||||
import meerkat.protobuf.Crypto.*;
|
||||
import meerkat.protobuf.BulletinBoardAPI.*;
|
||||
import meerkat.rest.Constants;
|
||||
import service.HelloWorldService;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
|
||||
@Path("/proto")
|
||||
public class HelloProtoWebApp {
|
||||
private static HelloProtoBuf helloProtoBuf = new HelloProtoBuf();
|
||||
private HelloProtoBuf helloProtoBuf;
|
||||
|
||||
@GET
|
||||
@Produces(Constants.MEDIATYPE_PROTOBUF)
|
||||
public Message hello() {
|
||||
return helloProtoBuf.sayHello();
|
||||
}
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
helloProtoBuf = new HelloProtoBuf();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Produces(Constants.MEDIATYPE_PROTOBUF)
|
||||
public Message hello() {
|
||||
byte[] b1 = { (byte) 1, (byte) 2, (byte) 3, (byte) 4 };
|
||||
byte[] b2 = { (byte) 11, (byte) 12, (byte) 13, (byte) 14 };
|
||||
byte[] b3 = {(byte) 21, (byte)22, (byte) 23, (byte) 24};
|
||||
|
||||
Message msg;
|
||||
|
||||
if (helloProtoBuf != null) {
|
||||
msg = helloProtoBuf.sayHello();
|
||||
} else {
|
||||
msg = BulletinBoardMessage.newBuilder()
|
||||
.setMsg(UnsignedBulletinBoardMessage.newBuilder()
|
||||
.addTags("Signature")
|
||||
.addTags("Trustee")
|
||||
.setData(ByteString.copyFrom(b1)).build())
|
||||
.addSig(Signature.newBuilder()
|
||||
.setType(SignatureType.DSA)
|
||||
.setData(ByteString.copyFrom(b2))
|
||||
.setSignerId(ByteString.copyFrom(b3)).build())
|
||||
.build();
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
package service;
|
||||
|
||||
|
||||
|
||||
public class HelloWorldService {
|
||||
public String sayHello() {
|
||||
return "Hello, World!";
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
package webapp;
|
||||
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
|
||||
import service.HelloWorldService;
|
||||
|
||||
@Path("/hello")
|
||||
public class HelloWebApp {
|
||||
private static HelloWorldService helloWorldService = new HelloWorldService();
|
||||
|
||||
@GET
|
||||
public String hello() {
|
||||
return helloWorldService.sayHello();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
syntax = "proto3";
|
||||
|
||||
package meerkat;
|
||||
|
||||
option java_package = "meerkat.protobuf";
|
||||
|
||||
message Boolean {
|
||||
bool value = 1;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
<Call name="setAttribute">
|
||||
<Arg>org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern</Arg>
|
||||
<Arg>none</Arg>
|
||||
</Call>
|
||||
<Call name="setAttribute">
|
||||
<Arg>org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern</Arg>
|
||||
<Arg>none</Arg>
|
||||
</Call>
|
||||
</Configure>
|
|
@ -6,7 +6,7 @@
|
|||
</servlet-class>
|
||||
<init-param>
|
||||
<param-name>jersey.config.server.provider.packages</param-name>
|
||||
<param-value>webapp, meerkat</param-value>
|
||||
<param-value>meerkat</param-value>
|
||||
</init-param>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
import javax.ws.rs.client.Client;
|
||||
import javax.ws.rs.client.ClientBuilder;
|
||||
import javax.ws.rs.client.WebTarget;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import org.junit.Test;
|
||||
|
||||
public class HelloIntegrationTest {
|
||||
|
||||
private static String PROP_GETTY_URL = "gretty.httpBaseURI";
|
||||
private static String BASE_URL = System.getProperty(PROP_GETTY_URL);
|
||||
private static String HELLO_URL = BASE_URL + "/hello";
|
||||
|
||||
@Test
|
||||
public void testHello() throws Exception {
|
||||
Client client = ClientBuilder.newClient();
|
||||
WebTarget webTarget = client.target(HELLO_URL);
|
||||
String response = webTarget.request().get(String.class);
|
||||
System.out.println(response);
|
||||
assertThat(response, is("Hello, World!"));
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
package meerkat.bulletinboard;
|
||||
|
||||
import meerkat.protobuf.Voting;
|
||||
import meerkat.protobuf.BulletinBoardAPI.*;
|
||||
import meerkat.rest.Constants;
|
||||
import meerkat.rest.ProtobufMessageBodyReader;
|
||||
import meerkat.rest.ProtobufMessageBodyWriter;
|
||||
|
@ -17,10 +17,10 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
|||
* Created by talm on 10/11/15.
|
||||
*/
|
||||
public class HelloProtoIntegrationTest {
|
||||
|
||||
private static String PROP_GETTY_URL = "gretty.httpBaseURI";
|
||||
private static String BASE_URL = System.getProperty(PROP_GETTY_URL);
|
||||
private static String HELLO_URL = BASE_URL + "/proto";
|
||||
private static String DEFAULT_BASE_URL = "http://localhost:8081/";
|
||||
private static String BASE_URL = System.getProperty(PROP_GETTY_URL, DEFAULT_BASE_URL);
|
||||
private static String HELLO_URL = "proto";
|
||||
|
||||
@Test
|
||||
public void testHello() throws Exception {
|
||||
|
@ -28,8 +28,9 @@ public class HelloProtoIntegrationTest {
|
|||
client.register(ProtobufMessageBodyReader.class);
|
||||
client.register(ProtobufMessageBodyWriter.class);
|
||||
|
||||
WebTarget webTarget = client.target(HELLO_URL);
|
||||
Voting.BulletinBoardMessage response = webTarget.request(Constants.MEDIATYPE_PROTOBUF).get(Voting.BulletinBoardMessage.class);
|
||||
WebTarget webTarget = client.target(BASE_URL).path(HELLO_URL);
|
||||
BulletinBoardMessage response = webTarget.request(Constants.MEDIATYPE_PROTOBUF)
|
||||
.get(BulletinBoardMessage.class);
|
||||
|
||||
System.out.println(response.getMsg().getData());
|
||||
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
package meerkat.bulletinboard;
|
||||
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
|
||||
import meerkat.bulletinboard.sqlserver.SQLiteBulletinBoardServer;
|
||||
import meerkat.comm.CommunicationException;
|
||||
import meerkat.protobuf.Crypto.*;
|
||||
import meerkat.protobuf.Voting.*;
|
||||
|
||||
public class SQLiteIntegrationTest {
|
||||
public static void main(){
|
||||
byte[] b1 = {(byte) 1, (byte)2, (byte) 3, (byte) 4};
|
||||
byte[] b2 = {(byte) 11, (byte)12, (byte) 13, (byte) 14};
|
||||
|
||||
BulletinBoardMessage msg = BulletinBoardMessage.newBuilder()
|
||||
.setMsg(UnsignedBulletinBoardMessage.newBuilder()
|
||||
.setTags(0, "signature")
|
||||
.setTags(1, "Trustee")
|
||||
.setData(ByteString.copyFrom(b1))
|
||||
.build())
|
||||
.setSig(Signature.newBuilder()
|
||||
.setType(SignatureType.DSA)
|
||||
.setData(ByteString.copyFrom(b2))
|
||||
.build())
|
||||
.build();
|
||||
|
||||
SQLiteBulletinBoardServer bbs = new SQLiteBulletinBoardServer();
|
||||
|
||||
try{
|
||||
bbs.init();
|
||||
|
||||
bbs.postMessage(msg);
|
||||
bbs.testPrint();
|
||||
|
||||
bbs.close();
|
||||
} catch(CommunicationException e){
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
package meerkat.bulletinboard;
|
||||
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import com.google.protobuf.TextFormat;
|
||||
|
||||
import meerkat.protobuf.Crypto.*;
|
||||
import meerkat.protobuf.BulletinBoardAPI.*;
|
||||
import meerkat.rest.Constants;
|
||||
import meerkat.rest.ProtobufMessageBodyReader;
|
||||
import meerkat.rest.ProtobufMessageBodyWriter;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
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;
|
||||
|
||||
public class SQLiteServerIntegrationTest {
|
||||
|
||||
private static String PROP_GETTY_URL = "gretty.httpBaseURI";
|
||||
private static String DEFAULT_BASE_URL = "localhost:8081";
|
||||
private static String BASE_URL = System.getProperty(PROP_GETTY_URL, DEFAULT_BASE_URL);
|
||||
private static String SQL_SERVER_POST = "sqlserver/postmessage";
|
||||
private static String SQL_SERVER_GET = "sqlserver/readmessages";
|
||||
|
||||
Client client;
|
||||
// Connection connection;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
client = ClientBuilder.newClient();
|
||||
client.register(ProtobufMessageBodyReader.class);
|
||||
client.register(ProtobufMessageBodyWriter.class);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPost() throws Exception {
|
||||
byte[] b1 = {(byte) 1, (byte) 2, (byte) 3, (byte) 4};
|
||||
byte[] b2 = {(byte) 11, (byte) 12, (byte) 13, (byte) 14};
|
||||
byte[] b3 = {(byte) 21, (byte) 22, (byte) 23, (byte) 24};
|
||||
byte[] b4 = {(byte) 4, (byte) 5, (byte) 100, (byte) -50, (byte) 0};
|
||||
|
||||
WebTarget webTarget;
|
||||
Response response;
|
||||
BoolMsg bool;
|
||||
|
||||
BulletinBoardMessage msg;
|
||||
|
||||
MessageFilterList filterList;
|
||||
BulletinBoardMessageList msgList;
|
||||
|
||||
// try{
|
||||
// connection = DriverManager.getConnection("jdbc:sqlite:d:/arbel/projects/meerkat-java/bulletin-board-server/local-instances/meerkat.db");
|
||||
// } catch (SQLException e) {
|
||||
// System.err.println(e.getMessage());
|
||||
// assert false;
|
||||
// }
|
||||
|
||||
// Test writing mechanism
|
||||
|
||||
System.err.println("******** Testing: " + SQL_SERVER_POST);
|
||||
webTarget = client.target(BASE_URL).path(SQL_SERVER_POST);
|
||||
|
||||
msg = BulletinBoardMessage.newBuilder()
|
||||
.setMsg(UnsignedBulletinBoardMessage.newBuilder()
|
||||
.addTags("Signature")
|
||||
.addTags("Trustee")
|
||||
.setData(ByteString.copyFrom(b1))
|
||||
.build())
|
||||
.addSig(Signature.newBuilder()
|
||||
.setType(SignatureType.DSA)
|
||||
.setData(ByteString.copyFrom(b2))
|
||||
.setSignerId(ByteString.copyFrom(b3))
|
||||
.build())
|
||||
.addSig(Signature.newBuilder()
|
||||
.setType(SignatureType.ECDSA)
|
||||
.setData(ByteString.copyFrom(b3))
|
||||
.setSignerId(ByteString.copyFrom(b2))
|
||||
.build())
|
||||
.build();
|
||||
|
||||
response = webTarget.request(Constants.MEDIATYPE_PROTOBUF).post(Entity.entity(msg, Constants.MEDIATYPE_PROTOBUF));
|
||||
System.err.println(response);
|
||||
bool = response.readEntity(BoolMsg.class);
|
||||
assert bool.getValue();
|
||||
|
||||
msg = BulletinBoardMessage.newBuilder()
|
||||
.setMsg(UnsignedBulletinBoardMessage.newBuilder()
|
||||
.addTags("Vote")
|
||||
.addTags("Trustee")
|
||||
.setData(ByteString.copyFrom(b4))
|
||||
.build())
|
||||
.addSig(Signature.newBuilder()
|
||||
.setType(SignatureType.ECDSA)
|
||||
.setData(ByteString.copyFrom(b4))
|
||||
.setSignerId(ByteString.copyFrom(b2))
|
||||
.build())
|
||||
.build();
|
||||
|
||||
response = webTarget.request(Constants.MEDIATYPE_PROTOBUF).post(Entity.entity(msg, Constants.MEDIATYPE_PROTOBUF));
|
||||
System.err.println(response);
|
||||
bool = response.readEntity(BoolMsg.class);
|
||||
assert bool.getValue();
|
||||
|
||||
// Test reading mechanism
|
||||
|
||||
System.err.println("******** Testing: " + SQL_SERVER_GET);
|
||||
webTarget = client.target(BASE_URL).path(SQL_SERVER_GET);
|
||||
|
||||
filterList = MessageFilterList.newBuilder()
|
||||
.addFilter(
|
||||
MessageFilter.newBuilder()
|
||||
.setType(FilterType.TAG)
|
||||
.setTag("Vote")
|
||||
.build()
|
||||
)
|
||||
.build();
|
||||
|
||||
// String sql = "SELECT MsgTable.EntryNum, MsgTable.Msg FROM MsgTable INNER JOIN SignatureTable ON SignatureTable.EntryNum = MsgTable.EntryNum WHERE SignatureTable.SignerId = ?";
|
||||
// PreparedStatement pstmt = connection.prepareStatement(sql);
|
||||
// int i=1;
|
||||
// for (MessageFilter filter : filterList.getFilterList()){
|
||||
//
|
||||
// switch (filter.getType().getNumber()){
|
||||
//
|
||||
// case FilterType.EXACT_ENTRY_VALUE: // Go through.
|
||||
// case FilterType.MAX_ENTRY_VALUE:
|
||||
// pstmt.setLong(i, filter.getEntry());
|
||||
// i++;
|
||||
// break;
|
||||
//
|
||||
// case FilterType.MSG_ID_VALUE: // Go through.
|
||||
// case FilterType.SIGNER_ID_VALUE:
|
||||
// pstmt.setBytes(i, filter.getId().toByteArray());
|
||||
// i++;
|
||||
// break;
|
||||
//
|
||||
// case FilterType.TAG_VALUE:
|
||||
// pstmt.setString(i, filter.getTag());
|
||||
// break;
|
||||
//
|
||||
// // The max-messages condition is applied as a suffix. Therefore, it is treated differently.
|
||||
// case FilterType.MAX_MESSAGES_VALUE:
|
||||
// pstmt.setLong(filterList.getFilterList().size(), filter.getMaxMessages());
|
||||
// break;
|
||||
//
|
||||
// }
|
||||
// }
|
||||
// ResultSet rs = pstmt.executeQuery();
|
||||
//
|
||||
// i = 0;
|
||||
// while (rs.next()){
|
||||
// i++;
|
||||
// assert rs.getBytes(2)
|
||||
// }
|
||||
// System.err.println("Local DB size = " + i);
|
||||
// pstmt.close();
|
||||
|
||||
response = webTarget.request(Constants.MEDIATYPE_PROTOBUF).post(Entity.entity(filterList, Constants.MEDIATYPE_PROTOBUF));
|
||||
System.err.println(response);
|
||||
msgList = response.readEntity(BulletinBoardMessageList.class);
|
||||
System.err.println("List size: " + msgList.getMessageCount());
|
||||
System.err.println("This is the list:");
|
||||
System.err.println(TextFormat.printToString(msgList));
|
||||
assert msgList.getMessageCount() == 1;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
/bin/
|
|
@ -59,6 +59,23 @@ dependencies {
|
|||
/*==== You probably don't have to edit below this line =======*/
|
||||
|
||||
|
||||
// Setup test configuration that can appear as a dependency in
|
||||
// other subprojects
|
||||
configurations {
|
||||
testOutput.extendsFrom (testCompile)
|
||||
}
|
||||
|
||||
task testJar(type: Jar, dependsOn: testClasses) {
|
||||
classifier = 'tests'
|
||||
from sourceSets.test.output
|
||||
}
|
||||
|
||||
artifacts {
|
||||
testOutput testJar
|
||||
}
|
||||
|
||||
|
||||
|
||||
// The run task added by the application plugin
|
||||
// is also of type JavaExec.
|
||||
tasks.withType(JavaExec) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import com.google.protobuf.ByteString;
|
||||
import static meerkat.protobuf.Voting.*;
|
||||
import static meerkat.protobuf.BulletinBoardAPI.*;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package meerkat.bulletinboard;
|
||||
|
||||
import meerkat.comm.*;
|
||||
import static meerkat.protobuf.Voting.*;
|
||||
import static meerkat.protobuf.BulletinBoardAPI.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
package meerkat.bulletinboard;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import meerkat.comm.CommunicationException;
|
||||
import meerkat.protobuf.Voting.BulletinBoardMessage;
|
||||
import meerkat.protobuf.BulletinBoardAPI.*;
|
||||
|
||||
/**
|
||||
* Created by Arbel on 07/11/15.
|
||||
|
@ -24,18 +22,17 @@ public interface BulletinBoardServer{
|
|||
/**
|
||||
* Post a message to bulletin board.
|
||||
* @param msg is the actual (signed) message
|
||||
* @return TRUE if the message has been authenticated and FALSE otherwise.
|
||||
* @return TRUE if the message has been authenticated and FALSE otherwise (in ProtoBuf form).
|
||||
* @throws CommunicationException on DB connection error.
|
||||
*/
|
||||
public boolean postMessage(BulletinBoardMessage msg) throws CommunicationException;
|
||||
public BoolMsg postMessage(BulletinBoardMessage msg) throws CommunicationException;
|
||||
|
||||
/**
|
||||
* Read all messages posted matching the given filter.
|
||||
* @param filter return only messages that match the filter (null means no filtering).
|
||||
* @param max maximum number of messages to return (0=no limit)
|
||||
* @param filter return only messages that match the filter (empty list means no filtering).
|
||||
* @return
|
||||
*/
|
||||
List<BulletinBoardMessage> readMessages(MessageFilter filter, int max);
|
||||
BulletinBoardMessageList readMessages(MessageFilterList filterList) throws CommunicationException;
|
||||
|
||||
/**
|
||||
* This method closes the connection to the DB.
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
package meerkat.bulletinboard;
|
||||
|
||||
/**
|
||||
* Created by talm on 25/10/15.
|
||||
*
|
||||
* A filter for messages (run on the BB server side).
|
||||
*
|
||||
* TODO: define a limited filter language (e.g., by tag, by signer, by time, etc.) that can
|
||||
* be efficiently run on the BB database.
|
||||
*
|
||||
*/
|
||||
public abstract class MessageFilter {
|
||||
public enum FilterType{
|
||||
ENTRY_NUM,
|
||||
ID,
|
||||
TAG,
|
||||
SIGNER,
|
||||
TIME
|
||||
}
|
||||
|
||||
FilterType filterType;
|
||||
|
||||
public MessageFilter(FilterType filterType){
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -17,7 +17,7 @@ import static meerkat.protobuf.Crypto.*;
|
|||
/**
|
||||
* Created by talm on 25/10/15.
|
||||
*
|
||||
* Sign and verifyarrays of messages
|
||||
* Sign and verify arrays of messages
|
||||
*/
|
||||
public interface DigitalSignature {
|
||||
final public static String CERTIFICATE_ENCODING_X509 = "X.509";
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
syntax = "proto3";
|
||||
|
||||
package meerkat;
|
||||
|
||||
option java_package = "meerkat.protobuf";
|
||||
|
||||
import 'meerkat/crypto.proto';
|
||||
|
||||
message BoolMsg {
|
||||
bool value = 1;
|
||||
}
|
||||
|
||||
|
||||
message MessageID {
|
||||
// The ID of a message for unique retrieval.
|
||||
// Note that it is assumed that this ID is a function of the message itself.
|
||||
bytes ID = 1;
|
||||
}
|
||||
|
||||
message UnsignedBulletinBoardMessage {
|
||||
// Optional tags describing message
|
||||
repeated string tags = 1;
|
||||
|
||||
// The actual content of the message
|
||||
bytes data = 2;
|
||||
}
|
||||
|
||||
message BulletinBoardMessage {
|
||||
|
||||
// Serial entry number of message in database
|
||||
int64 entryNum = 1;
|
||||
|
||||
// Unsigned raw data of message
|
||||
UnsignedBulletinBoardMessage msg = 2;
|
||||
|
||||
// Signature of message (and tags), excluding the entry number.
|
||||
repeated meerkat.Signature sig = 3;
|
||||
}
|
||||
|
||||
message BulletinBoardMessageList {
|
||||
|
||||
repeated BulletinBoardMessage message = 1;
|
||||
|
||||
}
|
||||
|
||||
enum FilterType {
|
||||
MSG_ID = 0; // Match exact message ID
|
||||
EXACT_ENTRY = 1; // Match exact entry number in database (chronological)
|
||||
MAX_ENTRY = 2; // Find all entries in database up to specified entry number (chronological)
|
||||
SIGNER_ID = 3; // Find all entries in database that correspond to specific signature (signer)
|
||||
TAG = 4; // Find all entries in database that have a specific tag
|
||||
MAX_MESSAGES = 5; // Return at most some specified number of messages
|
||||
}
|
||||
|
||||
message MessageFilter {
|
||||
|
||||
FilterType type = 1;
|
||||
|
||||
oneof filter{
|
||||
bytes id = 2;
|
||||
int64 entry = 3;
|
||||
string tag = 4;
|
||||
int64 maxMessages = 5;
|
||||
}
|
||||
}
|
||||
|
||||
message MessageFilterList {
|
||||
|
||||
// Combination of filters.
|
||||
// To be implemented using intersection ("AND") operations.
|
||||
repeated MessageFilter filter = 1;
|
||||
|
||||
}
|
|
@ -6,28 +6,6 @@ import 'meerkat/crypto.proto';
|
|||
|
||||
option java_package = "meerkat.protobuf";
|
||||
|
||||
message MessageID {
|
||||
// The ID of a message for unique retrieval.
|
||||
// Note that it is assumed that this ID is a function of the message itself.
|
||||
bytes ID = 1;
|
||||
}
|
||||
|
||||
message UnsignedBulletinBoardMessage {
|
||||
// Optional tags describing message
|
||||
repeated string tags = 1;
|
||||
|
||||
// The actual content of the message
|
||||
bytes data = 2;
|
||||
}
|
||||
|
||||
message BulletinBoardMessage {
|
||||
|
||||
UnsignedBulletinBoardMessage msg = 1;
|
||||
|
||||
// Signature of message (and tags)
|
||||
meerkat.Signature sig = 2;
|
||||
}
|
||||
|
||||
// A ballot question. This is an opaque
|
||||
// data type that is parsed by the UI to display
|
||||
// the question.
|
||||
|
|
|
@ -2,7 +2,7 @@ package meerkat.crypto.concrete;
|
|||
|
||||
import com.google.protobuf.ByteString;
|
||||
import meerkat.protobuf.Crypto;
|
||||
import meerkat.protobuf.Voting;
|
||||
import meerkat.protobuf.BulletinBoardAPI.*;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
@ -149,13 +149,13 @@ public class TestECDSASignature {
|
|||
signer.loadSigningCertificate(keyStore);
|
||||
|
||||
|
||||
Voting.UnsignedBulletinBoardMessage.Builder unsignedMsgBuilder = Voting.UnsignedBulletinBoardMessage.newBuilder();
|
||||
UnsignedBulletinBoardMessage.Builder unsignedMsgBuilder = UnsignedBulletinBoardMessage.newBuilder();
|
||||
unsignedMsgBuilder.setData(ByteString.copyFromUtf8(HELLO_WORLD));
|
||||
unsignedMsgBuilder.addTags("Tag1");
|
||||
unsignedMsgBuilder.addTags("Tag2");
|
||||
unsignedMsgBuilder.addTags("Tag3");
|
||||
|
||||
Voting.UnsignedBulletinBoardMessage usMsg = unsignedMsgBuilder.build();
|
||||
UnsignedBulletinBoardMessage usMsg = unsignedMsgBuilder.build();
|
||||
|
||||
signer.updateContent(usMsg);
|
||||
Crypto.Signature sig = signer.sign();
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
0D r=¥|n“Ò2ɪ‰!S»®[gCŸ$ä°Ž/ Ê”(Âò½ ^esüHLŸ½o,oV®”§ce²p0(èXÆ]&@
|
|
@ -0,0 +1 @@
|
|||
/bin/
|
Loading…
Reference in New Issue