Fixed a few problems:
- some bugs that creeped in when I moved security into its own adapter - improved some DB code as it doesn't work in Android anyway - all entities should be serializable (very useful in Android)
This commit is contained in:
parent
4911c268c2
commit
f89d1a342e
@ -22,8 +22,10 @@ dependencies {
|
||||
compile project(':domain')
|
||||
compile project(':networking')
|
||||
compile project(':repositories')
|
||||
compile project(':security-bc')
|
||||
compile project(':wif')
|
||||
compile 'org.slf4j:slf4j-simple:1.7.12'
|
||||
compile 'args4j:args4j:2.32'
|
||||
compile 'com.h2database:h2:1.4.187'
|
||||
testCompile 'junit:junit:4.11'
|
||||
}
|
||||
|
@ -21,7 +21,9 @@ import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||
import ch.dissem.bitmessage.entity.Plaintext;
|
||||
import ch.dissem.bitmessage.entity.payload.Pubkey;
|
||||
import ch.dissem.bitmessage.networking.DefaultNetworkHandler;
|
||||
import ch.dissem.bitmessage.ports.MemoryNodeRegistry;
|
||||
import ch.dissem.bitmessage.repository.*;
|
||||
import ch.dissem.bitmessage.security.bc.BouncySecurity;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -46,6 +48,7 @@ public class Application {
|
||||
.nodeRegistry(new MemoryNodeRegistry())
|
||||
.messageRepo(new JdbcMessageRepository(jdbcConfig))
|
||||
.networkHandler(new DefaultNetworkHandler())
|
||||
.security(new BouncySecurity())
|
||||
.port(48444)
|
||||
.build();
|
||||
|
||||
|
@ -18,7 +18,9 @@ package ch.dissem.bitmessage.demo;
|
||||
|
||||
import ch.dissem.bitmessage.BitmessageContext;
|
||||
import ch.dissem.bitmessage.networking.DefaultNetworkHandler;
|
||||
import ch.dissem.bitmessage.ports.MemoryNodeRegistry;
|
||||
import ch.dissem.bitmessage.repository.*;
|
||||
import ch.dissem.bitmessage.security.bc.BouncySecurity;
|
||||
import ch.dissem.bitmessage.wif.WifExporter;
|
||||
import ch.dissem.bitmessage.wif.WifImporter;
|
||||
import org.kohsuke.args4j.CmdLineException;
|
||||
@ -50,6 +52,7 @@ public class Main {
|
||||
.nodeRegistry(new MemoryNodeRegistry())
|
||||
.messageRepo(new JdbcMessageRepository(jdbcConfig))
|
||||
.networkHandler(new DefaultNetworkHandler())
|
||||
.security(new BouncySecurity())
|
||||
.port(48444)
|
||||
.build();
|
||||
|
||||
|
@ -81,7 +81,7 @@ public class InternalContext {
|
||||
streams.add(1L);
|
||||
}
|
||||
|
||||
init(inventory, nodeRegistry, networkHandler, addressRepository, messageRepository, proofOfWorkEngine);
|
||||
init(inventory, nodeRegistry, networkHandler, addressRepository, messageRepository, proofOfWorkEngine, security);
|
||||
}
|
||||
|
||||
private void init(Object... objects) {
|
||||
|
@ -19,9 +19,9 @@ package ch.dissem.bitmessage.entity;
|
||||
import ch.dissem.bitmessage.entity.valueobject.InventoryVector;
|
||||
import ch.dissem.bitmessage.entity.valueobject.Label;
|
||||
import ch.dissem.bitmessage.factory.Factory;
|
||||
import ch.dissem.bitmessage.ports.Security;
|
||||
import ch.dissem.bitmessage.utils.Decode;
|
||||
import ch.dissem.bitmessage.utils.Encode;
|
||||
import ch.dissem.bitmessage.utils.UnixTime;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
@ -29,7 +29,7 @@ import java.util.*;
|
||||
/**
|
||||
* The unencrypted message to be sent by 'msg' or 'broadcast'.
|
||||
*/
|
||||
public class Plaintext implements Streamable, Serializable {
|
||||
public class Plaintext implements Streamable {
|
||||
private final Type type;
|
||||
private final BitmessageAddress from;
|
||||
private final long encoding;
|
||||
@ -64,6 +64,7 @@ public class Plaintext implements Streamable, Serializable {
|
||||
public static Plaintext read(Type type, InputStream in) throws IOException {
|
||||
return readWithoutSignature(type, in)
|
||||
.signature(Decode.varBytes(in))
|
||||
.received(UnixTime.now())
|
||||
.build();
|
||||
}
|
||||
|
||||
@ -132,6 +133,15 @@ public class Plaintext implements Streamable, Serializable {
|
||||
this.signature = signature;
|
||||
}
|
||||
|
||||
public boolean isUnread() {
|
||||
for (Label label : labels) {
|
||||
if (label.getType() == Label.Type.UNREAD) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void write(OutputStream out, boolean includeSignature) throws IOException {
|
||||
Encode.varInt(from.getVersion(), out);
|
||||
Encode.varInt(from.getStream(), out);
|
||||
|
@ -16,14 +16,13 @@
|
||||
|
||||
package ch.dissem.bitmessage.entity;
|
||||
|
||||
import ch.dissem.bitmessage.ports.Security;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* An object that can be written to an {@link OutputStream}
|
||||
*/
|
||||
public interface Streamable {
|
||||
public interface Streamable extends Serializable {
|
||||
void write(OutputStream stream) throws IOException;
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import ch.dissem.bitmessage.entity.Streamable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* The payload of an 'object' command. This is shared by the network.
|
||||
|
@ -16,9 +16,10 @@
|
||||
|
||||
package ch.dissem.bitmessage.entity.valueobject;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
public class Label {
|
||||
public class Label implements Serializable {
|
||||
private Object id;
|
||||
private String label;
|
||||
private Type type;
|
||||
|
@ -14,10 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.bitmessage.repository;
|
||||
package ch.dissem.bitmessage.ports;
|
||||
|
||||
import ch.dissem.bitmessage.entity.valueobject.NetworkAddress;
|
||||
import ch.dissem.bitmessage.ports.NodeRegistry;
|
||||
import ch.dissem.bitmessage.utils.UnixTime;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
@ -21,6 +21,7 @@ import ch.dissem.bitmessage.entity.valueobject.InventoryVector;
|
||||
import ch.dissem.bitmessage.utils.Property;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
|
||||
/**
|
||||
* Handles incoming messages
|
||||
@ -30,6 +31,8 @@ public interface NetworkHandler {
|
||||
|
||||
void stop();
|
||||
|
||||
void synchronize(InetAddress trustedHost, int port, MessageListener listener) throws IOException;
|
||||
|
||||
void offer(InventoryVector iv);
|
||||
|
||||
Property getNetworkStatus();
|
||||
|
@ -16,12 +16,6 @@
|
||||
|
||||
package ch.dissem.bitmessage.utils;
|
||||
|
||||
import ch.dissem.bitmessage.entity.Streamable;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* A helper class for working with byte arrays interpreted as unsigned big endian integers.
|
||||
* This is one part due to the fact that Java doesn't support unsigned numbers, and another
|
||||
@ -91,6 +85,8 @@ public class Bytes {
|
||||
if (a < 0) return b < 0 && a < b;
|
||||
if (b < 0) return a >= 0 || a < b;
|
||||
return a < b;
|
||||
// This would be easier to understand, but is (slightly) slower:
|
||||
// return (a & 0xff) < (b & 0xff);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -117,6 +117,8 @@ public class Encode {
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
public static byte[] bytes(Streamable streamable) throws IOException {
|
||||
if (streamable == null) return null;
|
||||
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
streamable.write(stream);
|
||||
return stream.toByteArray();
|
||||
|
@ -17,21 +17,21 @@
|
||||
package ch.dissem.bitmessage.entity;
|
||||
|
||||
import ch.dissem.bitmessage.entity.payload.*;
|
||||
import ch.dissem.bitmessage.entity.valueobject.Label;
|
||||
import ch.dissem.bitmessage.exception.DecryptionFailedException;
|
||||
import ch.dissem.bitmessage.factory.Factory;
|
||||
import ch.dissem.bitmessage.utils.TestBase;
|
||||
import ch.dissem.bitmessage.utils.TestUtils;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static ch.dissem.bitmessage.entity.Plaintext.Type.MSG;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class SerializationTest {
|
||||
public class SerializationTest extends TestBase {
|
||||
@Test
|
||||
public void ensureGetPubkeyIsDeserializedAndSerializedCorrectly() throws IOException {
|
||||
doTest("V2GetPubkey.payload", 2, GetPubkey.class);
|
||||
@ -75,7 +75,7 @@ public class SerializationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensurePlaintextIsSerializedAndDeserializedCorrectly() throws IOException, DecryptionFailedException {
|
||||
public void ensurePlaintextIsSerializedAndDeserializedCorrectly() throws Exception {
|
||||
Plaintext p1 = new Plaintext.Builder(MSG)
|
||||
.from(TestUtils.loadIdentity("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8"))
|
||||
.to(TestUtils.loadContact())
|
||||
@ -99,4 +99,21 @@ public class SerializationTest {
|
||||
assertArrayEquals(data, out.toByteArray());
|
||||
assertEquals(expectedPayloadType.getCanonicalName(), object.getPayload().getClass().getCanonicalName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureSystemSerializationWorks() throws Exception {
|
||||
Plaintext plaintext = new Plaintext.Builder(MSG)
|
||||
.from(TestUtils.loadContact())
|
||||
.to(TestUtils.loadIdentity("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8"))
|
||||
.labels(Arrays.asList(new Label("Test", Label.Type.INBOX, 0)))
|
||||
.message("Test", "Test Test.\nTest")
|
||||
.build();
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(out);
|
||||
oos.writeObject(plaintext);
|
||||
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
|
||||
ObjectInputStream ois = new ObjectInputStream(in);
|
||||
assertEquals(plaintext, ois.readObject());
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.*;
|
||||
@ -149,6 +150,11 @@ public class DefaultNetworkHandler implements NetworkHandler, ContextHolder {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void synchronize(InetAddress trustedHost, int port, MessageListener listener) throws IOException {
|
||||
startConnection(new Connection(ctx, CLIENT, new Socket(trustedHost, port), listener, requestedObjects));
|
||||
}
|
||||
|
||||
private void startConnection(Connection c) {
|
||||
synchronized (connections) {
|
||||
// prevent connecting twice to the same node
|
||||
|
@ -29,6 +29,7 @@ import org.slf4j.LoggerFactory;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.sql.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
@ -97,16 +98,16 @@ public class JdbcAddressRepository extends JdbcHelper implements AddressReposito
|
||||
while (rs.next()) {
|
||||
BitmessageAddress address;
|
||||
|
||||
byte[] privateKeyBytes = rs.getBytes("private_key");
|
||||
if (privateKeyBytes != null) {
|
||||
PrivateKey privateKey = PrivateKey.read(new ByteArrayInputStream(privateKeyBytes));
|
||||
InputStream privateKeyStream = rs.getBinaryStream("private_key");
|
||||
if (privateKeyStream != null) {
|
||||
PrivateKey privateKey = PrivateKey.read(privateKeyStream);
|
||||
address = new BitmessageAddress(privateKey);
|
||||
} else {
|
||||
address = new BitmessageAddress(rs.getString("address"));
|
||||
byte[] publicKeyBytes = rs.getBytes("public_key");
|
||||
if (publicKeyBytes != null) {
|
||||
Blob publicKeyBlob = rs.getBlob("public_key");
|
||||
if (publicKeyBlob != null) {
|
||||
Pubkey pubkey = Factory.readPubkey(address.getVersion(), address.getStream(),
|
||||
new ByteArrayInputStream(publicKeyBytes), publicKeyBytes.length, false);
|
||||
publicKeyBlob.getBinaryStream(), (int) publicKeyBlob.length(), false);
|
||||
if (address.getVersion() == 4 && pubkey instanceof V3Pubkey) {
|
||||
pubkey = new V4Pubkey((V3Pubkey) pubkey);
|
||||
}
|
||||
@ -182,7 +183,7 @@ public class JdbcAddressRepository extends JdbcHelper implements AddressReposito
|
||||
data.writeUnencrypted(out);
|
||||
ps.setBytes(parameterIndex, out.toByteArray());
|
||||
} else {
|
||||
ps.setBlob(parameterIndex, (Blob) null);
|
||||
ps.setBytes(parameterIndex, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,10 +21,8 @@ import ch.dissem.bitmessage.entity.payload.ObjectType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.sql.Blob;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
@ -84,7 +82,7 @@ abstract class JdbcHelper {
|
||||
data.write(os);
|
||||
ps.setBytes(parameterIndex, os.toByteArray());
|
||||
} else {
|
||||
ps.setBlob(parameterIndex, (Blob) null);
|
||||
ps.setBytes(parameterIndex, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -53,6 +53,7 @@ public class JdbcInventory extends JdbcHelper implements Inventory {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<InventoryVector> getFullInventory(long... streams) {
|
||||
List<InventoryVector> result = new LinkedList<>();
|
||||
try (Connection connection = config.getConnection()) {
|
||||
@ -79,8 +80,8 @@ public class JdbcInventory extends JdbcHelper implements Inventory {
|
||||
Statement stmt = connection.createStatement();
|
||||
ResultSet rs = stmt.executeQuery("SELECT data, version FROM Inventory WHERE hash = X'" + vector + "'");
|
||||
if (rs.next()) {
|
||||
byte[] data = rs.getBytes("data");
|
||||
return Factory.getObjectMessage(rs.getInt("version"), new ByteArrayInputStream(data), data.length);
|
||||
Blob data = rs.getBlob("data");
|
||||
return Factory.getObjectMessage(rs.getInt("version"), data.getBinaryStream(), (int) data.length());
|
||||
} else {
|
||||
LOG.info("Object requested that we don't have. IV: " + vector);
|
||||
return null;
|
||||
@ -108,8 +109,8 @@ public class JdbcInventory extends JdbcHelper implements Inventory {
|
||||
ResultSet rs = stmt.executeQuery(query.toString());
|
||||
List<ObjectMessage> result = new LinkedList<>();
|
||||
while (rs.next()) {
|
||||
byte[] data = rs.getBytes("data");
|
||||
result.add(Factory.getObjectMessage(rs.getInt("version"), new ByteArrayInputStream(data), data.length));
|
||||
Blob data = rs.getBlob("data");
|
||||
result.add(Factory.getObjectMessage(rs.getInt("version"), data.getBinaryStream(), (int) data.length()));
|
||||
}
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
|
@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.sql.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@ -107,9 +108,9 @@ public class JdbcMessageRepository extends JdbcHelper implements MessageReposito
|
||||
ResultSet rs = stmt.executeQuery("SELECT id, iv, type, sender, recipient, data, sent, received, status FROM Message WHERE " + where);
|
||||
while (rs.next()) {
|
||||
byte[] iv = rs.getBytes("iv");
|
||||
byte[] data = rs.getBytes("data");
|
||||
InputStream data = rs.getBinaryStream("data");
|
||||
Plaintext.Type type = Plaintext.Type.valueOf(rs.getString("type"));
|
||||
Plaintext.Builder builder = Plaintext.readWithoutSignature(type, new ByteArrayInputStream(data));
|
||||
Plaintext.Builder builder = Plaintext.readWithoutSignature(type, data);
|
||||
long id = rs.getLong("id");
|
||||
builder.id(id);
|
||||
builder.IV(new InventoryVector(iv));
|
||||
@ -191,7 +192,8 @@ public class JdbcMessageRepository extends JdbcHelper implements MessageReposito
|
||||
|
||||
private void insert(Connection connection, Plaintext message) throws SQLException, IOException {
|
||||
PreparedStatement ps = connection.prepareStatement(
|
||||
"INSERT INTO Message (iv, type, sender, recipient, data, sent, received, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS);
|
||||
"INSERT INTO Message (iv, type, sender, recipient, data, sent, received, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
Statement.RETURN_GENERATED_KEYS);
|
||||
ps.setBytes(1, message.getInventoryVector() != null ? message.getInventoryVector().getHash() : null);
|
||||
ps.setString(2, message.getType().name());
|
||||
ps.setString(3, message.getFrom().getAddress());
|
||||
|
@ -17,6 +17,7 @@
|
||||
package ch.dissem.bitmessage.repository;
|
||||
|
||||
import ch.dissem.bitmessage.entity.valueobject.NetworkAddress;
|
||||
import ch.dissem.bitmessage.ports.MemoryNodeRegistry;
|
||||
import ch.dissem.bitmessage.ports.NodeRegistry;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
Loading…
Reference in New Issue
Block a user