A simple command line application (WIP), and a few tests. Unfotrunately, receiving messages doesn't seem to work yet.

This commit is contained in:
2015-05-22 20:51:57 +02:00
parent 648afbbc75
commit 6b3b361aa3
36 changed files with 757 additions and 298 deletions

View File

@ -18,12 +18,16 @@ package ch.dissem.bitmessage.repository;
import ch.dissem.bitmessage.entity.BitmessageAddress;
import ch.dissem.bitmessage.entity.payload.Pubkey;
import ch.dissem.bitmessage.entity.payload.V3Pubkey;
import ch.dissem.bitmessage.entity.payload.V4Pubkey;
import ch.dissem.bitmessage.entity.valueobject.PrivateKey;
import ch.dissem.bitmessage.factory.Factory;
import ch.dissem.bitmessage.ports.AddressRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.sql.*;
import java.util.Arrays;
@ -62,7 +66,7 @@ public class JdbcAddressRepository extends JdbcHelper implements AddressReposito
@Override
public List<BitmessageAddress> getIdentities() {
return find("private_signing_key IS NOT NULL");
return find("private_key IS NOT NULL");
}
@Override
@ -72,7 +76,7 @@ public class JdbcAddressRepository extends JdbcHelper implements AddressReposito
@Override
public List<BitmessageAddress> getContacts() {
return find("private_signing_key IS NULL");
return find("private_key IS NULL");
}
private List<BitmessageAddress> find(String where) {
@ -91,7 +95,10 @@ public class JdbcAddressRepository extends JdbcHelper implements AddressReposito
Blob publicKeyBlob = rs.getBlob("public_key");
if (publicKeyBlob != null) {
Pubkey pubkey = Factory.readPubkey(address.getVersion(), address.getStream(),
publicKeyBlob.getBinaryStream(), (int) publicKeyBlob.length());
publicKeyBlob.getBinaryStream(), (int) publicKeyBlob.length(), false);
if (address.getVersion() == 4) {
pubkey = new V4Pubkey((V3Pubkey) pubkey);
}
address.setPubkey(pubkey);
}
}
@ -111,7 +118,7 @@ public class JdbcAddressRepository extends JdbcHelper implements AddressReposito
Statement stmt = getConnection().createStatement();
ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM Address WHERE address='" + address.getAddress() + "'");
rs.next();
return rs.getInt(0) > 0;
return rs.getInt(1) > 0;
} catch (SQLException e) {
LOG.error(e.getMessage(), e);
}
@ -136,21 +143,32 @@ public class JdbcAddressRepository extends JdbcHelper implements AddressReposito
"UPDATE Address SET address=?, alias=?, public_key=?, private_key=?");
ps.setString(1, address.getAddress());
ps.setString(2, address.getAlias());
writeBlob(ps, 3, address.getPubkey());
writePubkey(ps, 3, address.getPubkey());
writeBlob(ps, 4, address.getPrivateKey());
ps.executeUpdate();
}
private void insert(BitmessageAddress address) throws IOException, SQLException {
PreparedStatement ps = getConnection().prepareStatement(
"INSERT INTO Address (address, alias, public_key, private_key) VALUES (?, ?, ?, ?, ?)");
"INSERT INTO Address (address, alias, public_key, private_key) VALUES (?, ?, ?, ?)");
ps.setString(1, address.getAddress());
ps.setString(2, address.getAlias());
writeBlob(ps, 3, address.getPubkey());
writePubkey(ps, 3, address.getPubkey());
writeBlob(ps, 4, address.getPrivateKey());
ps.executeUpdate();
}
protected void writePubkey(PreparedStatement ps, int parameterIndex, Pubkey data) throws SQLException, IOException {
if (data != null) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
data.writeUnencrypted(out);
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
ps.setBlob(parameterIndex, in);
} else {
ps.setBlob(parameterIndex, (Blob) null);
}
}
@Override
public void remove(BitmessageAddress address) {
try {

View File

@ -24,10 +24,7 @@ import org.slf4j.LoggerFactory;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.*;
/**
* Helper class that does Flyway migration, provides JDBC connections and some helper methods.
@ -47,10 +44,14 @@ abstract class JdbcHelper {
}
protected void writeBlob(PreparedStatement ps, int parameterIndex, Streamable data) throws SQLException, IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream();
data.write(os);
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
ps.setBlob(parameterIndex, is);
if (data != null) {
ByteArrayOutputStream os = new ByteArrayOutputStream();
data.write(os);
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
ps.setBlob(parameterIndex, is);
} else {
ps.setBlob(parameterIndex, (Blob) null);
}
}
protected Connection getConnection() {

View File

@ -52,10 +52,23 @@ public class JdbcInventory extends JdbcHelper implements Inventory {
}
return result;
}
private List<InventoryVector> getFullInventory(long... streams) {
List<InventoryVector> result = new LinkedList<>();
try {
Statement stmt = getConnection().createStatement();
ResultSet rs = stmt.executeQuery("SELECT hash FROM Inventory WHERE stream IN (" + join(streams) + ")");
while (rs.next()) {
result.add(new InventoryVector(rs.getBytes("hash")));
}
} catch (SQLException e) {
LOG.error(e.getMessage(), e);
}
return result;
}
@Override
public List<InventoryVector> getMissing(List<InventoryVector> offer, long... streams) {
offer.removeAll(getInventory(streams));
offer.removeAll(getFullInventory(streams));
return offer;
}
@ -78,17 +91,17 @@ public class JdbcInventory extends JdbcHelper implements Inventory {
}
@Override
public List<ObjectMessage> getObjects(long stream, long version, ObjectType type) {
public List<ObjectMessage> getObjects(long stream, long version, ObjectType... types) {
try {
StringBuilder query = new StringBuilder("SELECT data, version FROM Inventory WHERE 1=1");
if (stream >= 0) {
if (stream > 0) {
query.append(" AND stream = ").append(stream);
}
if (version >= 0) {
if (version > 0) {
query.append(" AND version = ").append(version);
}
if (type != null) {
query.append(" AND type = ").append(type.getNumber());
if (types.length > 0) {
query.append(" AND type IN (").append(join(types)).append(")");
}
Statement stmt = getConnection().createStatement();
ResultSet rs = stmt.executeQuery(query.toString());

View File

@ -41,7 +41,7 @@ public class JdbcMessageRepository extends JdbcHelper implements MessageReposito
List<String> result = new LinkedList<>();
try {
Statement stmt = getConnection().createStatement();
ResultSet rs = stmt.executeQuery("SELECT label FROM Label ORDER BY order");
ResultSet rs = stmt.executeQuery("SELECT label FROM Label ORDER BY ord");
while (rs.next()) {
result.add(rs.getString("label"));
}
@ -58,7 +58,7 @@ public class JdbcMessageRepository extends JdbcHelper implements MessageReposito
@Override
public List<Plaintext> findMessages(Plaintext.Status status, BitmessageAddress recipient) {
return find("status='" + status.name() + "' AND to='" + recipient.getAddress() + "'");
return find("status='" + status.name() + "' AND recipient='" + recipient.getAddress() + "'");
}
@Override
@ -70,14 +70,14 @@ public class JdbcMessageRepository extends JdbcHelper implements MessageReposito
List<Plaintext> result = new LinkedList<>();
try {
Statement stmt = getConnection().createStatement();
ResultSet rs = stmt.executeQuery("SELECT \"id\", \"from\", \"to\", \"data\", \"sent\", \"received\", \"status\" FROM Message WHERE " + where);
ResultSet rs = stmt.executeQuery("SELECT id, sender, recipient, data, sent, received, status FROM Message WHERE " + where);
while (rs.next()) {
Blob data = rs.getBlob("data");
Plaintext.Builder builder = Plaintext.readWithoutSignature(data.getBinaryStream());
long id = rs.getLong("id");
builder.id(id);
builder.from(ctx.getAddressRepo().getAddress(rs.getString("from")));
builder.to(ctx.getAddressRepo().getAddress(rs.getString("to")));
builder.from(ctx.getAddressRepo().getAddress(rs.getString("sender")));
builder.to(ctx.getAddressRepo().getAddress(rs.getString("recipient")));
builder.sent(rs.getLong("sent"));
builder.received(rs.getLong("received"));
builder.status(Plaintext.Status.valueOf(rs.getString("status")));
@ -94,7 +94,7 @@ public class JdbcMessageRepository extends JdbcHelper implements MessageReposito
List<Label> result = new ArrayList<>();
try {
Statement stmt = getConnection().createStatement();
ResultSet rs = stmt.executeQuery("SELECT \"label\", \"color\" FROM Label WHERE id IN SELECT label_id FROM Message_Label WHERE message_id=" + messageId);
ResultSet rs = stmt.executeQuery("SELECT label, color FROM Label WHERE id IN SELECT label_id FROM Message_Label WHERE message_id=" + messageId);
while (rs.next()) {
result.add(new Label(rs.getString("label"), rs.getInt("color")));
}
@ -151,7 +151,7 @@ public class JdbcMessageRepository extends JdbcHelper implements MessageReposito
private void insert(Connection connection, Plaintext message) throws SQLException, IOException {
PreparedStatement ps = connection.prepareStatement(
"INSERT INTO Message (\"from\", \"to\", \"data\", \"sent\", \"received\", \"status\") VALUES (?, ?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS);
"INSERT INTO Message (sender, recipient, data, sent, received, status) VALUES (?, ?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS);
ps.setString(1, message.getFrom().getAddress());
ps.setString(2, message.getTo().getAddress());
writeBlob(ps, 3, message);
@ -168,7 +168,7 @@ public class JdbcMessageRepository extends JdbcHelper implements MessageReposito
private void update(Connection connection, Plaintext message) throws SQLException, IOException {
PreparedStatement ps = connection.prepareStatement(
"UPDATE Message SET \"sent\"=?, \"received\"=?, \"status\"=?");
"UPDATE Message SET sent=?, received=?, status=?");
ps.setLong(1, message.getSent());
ps.setLong(2, message.getReceived());
ps.setString(3, message.getStatus().name());

View File

@ -38,7 +38,7 @@ public class JdbcNodeRegistry extends JdbcHelper implements NodeRegistry {
List<NetworkAddress> result = new LinkedList<>();
try {
Statement stmt = getConnection().createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM Node WHERE Stream IN (" + join(streams) + ")");
ResultSet rs = stmt.executeQuery("SELECT * FROM Node WHERE stream IN (" + join(streams) + ")");
while (rs.next()) {
// result.add(new NetworkAddress.Builder()
// .ipv6(rs.getBytes("ip"))

View File

@ -1,61 +0,0 @@
/*
* Copyright 2015 Christian Basler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.dissem.bitmessage.repository;
import ch.dissem.bitmessage.entity.ObjectMessage;
import ch.dissem.bitmessage.entity.payload.ObjectType;
import ch.dissem.bitmessage.entity.valueobject.InventoryVector;
import ch.dissem.bitmessage.ports.Inventory;
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
import java.util.LinkedList;
import java.util.List;
/**
* Created by chris on 06.04.15.
*/
public class SimpleInventory implements Inventory {
@Override
public List<InventoryVector> getInventory(long... streams) {
return new LinkedList<>();
}
@Override
public List<InventoryVector> getMissing(List<InventoryVector> offer, long... streams) {
return offer;
}
@Override
public ObjectMessage getObject(InventoryVector vector) {
throw new NotImplementedException();
}
@Override
public List<ObjectMessage> getObjects(long stream, long version, ObjectType type) {
return new LinkedList<>();
}
@Override
public void storeObject(ObjectMessage object) {
throw new NotImplementedException();
}
@Override
public void cleanup() {
throw new NotImplementedException();
}
}

View File

@ -1,37 +0,0 @@
/*
* Copyright 2015 Christian Basler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.dissem.bitmessage.repository;
import ch.dissem.bitmessage.entity.valueobject.NetworkAddress;
import ch.dissem.bitmessage.ports.NodeRegistry;
import java.util.Collections;
import java.util.List;
/**
* Created by chris on 06.04.15.
*/
public class SimpleNodeRegistry implements NodeRegistry {
@Override
public List<NetworkAddress> getKnownAddresses(int limit, long... streams) {
return Collections.singletonList(new NetworkAddress.Builder().ipv4(127, 0, 0, 1).port(8444).build());
}
@Override
public void offerAddresses(List<NetworkAddress> addresses) {
}
}

View File

@ -1,9 +1,9 @@
CREATE TABLE Node (
"ip" BINARY(16) NOT NULL,
"port" INT NOT NULL,
"stream" BIGINT NOT NULL,
"services" BIGINT NOT NULL,
"time" BIGINT NOT NULL,
ip BINARY(16) NOT NULL,
port INT NOT NULL,
stream BIGINT NOT NULL,
services BIGINT NOT NULL,
time BIGINT NOT NULL,
PRIMARY KEY ("ip", "port", "stream")
PRIMARY KEY (ip, port, stream)
);

View File

@ -1,8 +1,8 @@
CREATE TABLE Inventory (
"hash" BINARY(32) NOT NULL PRIMARY KEY,
"stream" BIGINT NOT NULL,
"expires" BIGINT NOT NULL,
"data" BLOB NOT NULL,
"type" BIGINT NOT NULL,
"version" BIGINT NOT NULL
hash BINARY(32) NOT NULL PRIMARY KEY,
stream BIGINT NOT NULL,
expires BIGINT NOT NULL,
data BLOB NOT NULL,
type BIGINT NOT NULL,
version BIGINT NOT NULL
);

View File

@ -1,7 +1,7 @@
CREATE TABLE Address (
"address" VARCHAR(40) NOT NULL PRIMARY KEY,
"alias" VARCHAR(255),
"public_key" BLOB,
"private_key" BLOB,
"subscribed" BIT DEFAULT '0'
address VARCHAR(40) NOT NULL PRIMARY KEY,
alias VARCHAR(255),
public_key BLOB,
private_key BLOB,
subscribed BIT DEFAULT '0'
);

View File

@ -1,32 +1,35 @@
CREATE TABLE Message (
"id" BIGINT AUTO_INCREMENT PRIMARY KEY,
"from" VARCHAR(40) NOT NULL,
"to" VARCHAR(40) NOT NULL,
"data" BLOB NOT NULL,
"sent" BIGINT,
"received" BIGINT,
"status" VARCHAR(20) NOT NULL
id BIGINT AUTO_INCREMENT PRIMARY KEY,
sender VARCHAR(40) NOT NULL,
recipient VARCHAR(40) NOT NULL,
data BLOB NOT NULL,
sent BIGINT,
received BIGINT,
status VARCHAR(20) NOT NULL,
FOREIGN KEY (sender) REFERENCES Address (address),
FOREIGN KEY (recipient) REFERENCES Address (address)
);
CREATE TABLE Label (
"id" BIGINT AUTO_INCREMENT PRIMARY KEY,
"label" VARCHAR(255) NOT NULL,
"color" INT,
"order" BIGINT,
CONSTRAINT UC_label UNIQUE ("label"),
CONSTRAINT UC_order UNIQUE ("order")
id BIGINT AUTO_INCREMENT PRIMARY KEY,
label VARCHAR(255) NOT NULL,
color INT,
ord BIGINT,
CONSTRAINT UC_label UNIQUE (label),
CONSTRAINT UC_order UNIQUE (ord)
);
CREATE TABLE Message_Label (
"message_id" BIGINT NOT NULL,
"label_id" BIGINT NOT NULL,
message_id BIGINT NOT NULL,
label_id BIGINT NOT NULL,
PRIMARY KEY ("message_id", "label_id"),
FOREIGN KEY ("message_id") REFERENCES Message ("id"),
FOREIGN KEY ("label_id") REFERENCES Label ("id")
PRIMARY KEY (message_id, label_id),
FOREIGN KEY (message_id) REFERENCES Message (id),
FOREIGN KEY (label_id) REFERENCES Label (id)
);
INSERT INTO Label("label", "order") VALUES ('Inbox', 0);
INSERT INTO Label("label", "order") VALUES ('Sent', 10);
INSERT INTO Label("label", "order") VALUES ('Drafts', 20);
INSERT INTO Label("label", "order") VALUES ('Trash', 100);
INSERT INTO Label(label, ord) VALUES ('Inbox', 0);
INSERT INTO Label(label, ord) VALUES ('Sent', 10);
INSERT INTO Label(label, ord) VALUES ('Drafts', 20);
INSERT INTO Label(label, ord) VALUES ('Trash', 100);