diff --git a/src/main/java/org/qortal/controller/Synchronizer.java b/src/main/java/org/qortal/controller/Synchronizer.java index d574ef87..27106186 100644 --- a/src/main/java/org/qortal/controller/Synchronizer.java +++ b/src/main/java/org/qortal/controller/Synchronizer.java @@ -33,7 +33,7 @@ import org.qortal.network.message.GetBlockSummariesMessage; import org.qortal.network.message.GetSignaturesV2Message; import org.qortal.network.message.Message; import org.qortal.network.message.SignaturesMessage; -import org.qortal.network.message.Message.MessageType; +import org.qortal.network.message.MessageType; import org.qortal.repository.DataException; import org.qortal.repository.Repository; import org.qortal.repository.RepositoryManager; diff --git a/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataFileManager.java b/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataFileManager.java index e8b161a2..977f6215 100644 --- a/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataFileManager.java +++ b/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataFileManager.java @@ -7,7 +7,6 @@ import org.qortal.controller.Controller; import org.qortal.data.arbitrary.ArbitraryDirectConnectionInfo; import org.qortal.data.arbitrary.ArbitraryFileListResponseInfo; import org.qortal.data.arbitrary.ArbitraryRelayInfo; -import org.qortal.data.network.ArbitraryPeerData; import org.qortal.data.network.PeerData; import org.qortal.data.transaction.ArbitraryTransactionData; import org.qortal.network.Network; @@ -210,7 +209,7 @@ public class ArbitraryDataFileManager extends Thread { LOGGER.debug("Received null message from peer {}", peer); return null; } - if (message.getType() != Message.MessageType.ARBITRARY_DATA_FILE) { + if (message.getType() != MessageType.ARBITRARY_DATA_FILE) { LOGGER.debug("Received message with invalid type: {} from peer {}", message.getType(), peer); return null; } diff --git a/src/main/java/org/qortal/network/Handshake.java b/src/main/java/org/qortal/network/Handshake.java index cdcff1d7..22354cc4 100644 --- a/src/main/java/org/qortal/network/Handshake.java +++ b/src/main/java/org/qortal/network/Handshake.java @@ -13,7 +13,7 @@ import org.qortal.crypto.MemoryPoW; import org.qortal.network.message.ChallengeMessage; import org.qortal.network.message.HelloMessage; import org.qortal.network.message.Message; -import org.qortal.network.message.Message.MessageType; +import org.qortal.network.message.MessageType; import org.qortal.settings.Settings; import org.qortal.network.message.ResponseMessage; import org.qortal.utils.DaemonThreadFactory; diff --git a/src/main/java/org/qortal/network/Peer.java b/src/main/java/org/qortal/network/Peer.java index 21322e85..b1dd0ef5 100644 --- a/src/main/java/org/qortal/network/Peer.java +++ b/src/main/java/org/qortal/network/Peer.java @@ -11,8 +11,8 @@ import org.qortal.data.network.PeerChainTipData; import org.qortal.data.network.PeerData; import org.qortal.network.message.ChallengeMessage; import org.qortal.network.message.Message; -import org.qortal.network.message.Message.MessageException; -import org.qortal.network.message.Message.MessageType; +import org.qortal.network.message.MessageException; +import org.qortal.network.message.MessageType; import org.qortal.network.message.PingMessage; import org.qortal.settings.Settings; import org.qortal.utils.ExecuteProduceConsume; diff --git a/src/main/java/org/qortal/network/message/ArbitraryDataFileListMessage.java b/src/main/java/org/qortal/network/message/ArbitraryDataFileListMessage.java index 32ba3fa7..952010af 100644 --- a/src/main/java/org/qortal/network/message/ArbitraryDataFileListMessage.java +++ b/src/main/java/org/qortal/network/message/ArbitraryDataFileListMessage.java @@ -9,17 +9,12 @@ import org.qortal.utils.Serialization; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; public class ArbitraryDataFileListMessage extends Message { - private static final int SIGNATURE_LENGTH = Transformer.SIGNATURE_LENGTH; - private static final int HASH_LENGTH = Transformer.SHA256_LENGTH; - private static final int MAX_PEER_ADDRESS_LENGTH = PeerData.MAX_PEER_ADDRESS_SIZE; - private final byte[] signature; private final List hashes; private Long requestTime; @@ -60,16 +55,15 @@ public class ArbitraryDataFileListMessage extends Message { return this.signature; } - public static Message fromByteBuffer(int id, ByteBuffer bytes) throws UnsupportedEncodingException, TransformationException { - byte[] signature = new byte[SIGNATURE_LENGTH]; + public static Message fromByteBuffer(int id, ByteBuffer bytes) throws MessageException { + byte[] signature = new byte[Transformer.SIGNATURE_LENGTH]; bytes.get(signature); int count = bytes.getInt(); List hashes = new ArrayList<>(); for (int i = 0; i < count; ++i) { - - byte[] hash = new byte[HASH_LENGTH]; + byte[] hash = new byte[Transformer.SHA256_LENGTH]; bytes.get(hash); hashes.add(hash); } @@ -82,51 +76,49 @@ public class ArbitraryDataFileListMessage extends Message { // The remaining fields are optional if (bytes.hasRemaining()) { + try { + requestTime = bytes.getLong(); - requestTime = bytes.getLong(); + requestHops = bytes.getInt(); - requestHops = bytes.getInt(); - - peerAddress = Serialization.deserializeSizedStringV2(bytes, MAX_PEER_ADDRESS_LENGTH); - - isRelayPossible = bytes.getInt() > 0; + peerAddress = Serialization.deserializeSizedStringV2(bytes, PeerData.MAX_PEER_ADDRESS_SIZE); + isRelayPossible = bytes.getInt() > 0; + } catch (TransformationException e) { + throw new MessageException(e.getMessage(), e); + } } return new ArbitraryDataFileListMessage(id, signature, hashes, requestTime, requestHops, peerAddress, isRelayPossible); } @Override - protected byte[] toData() { - try { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + protected byte[] toData() throws IOException { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - bytes.write(this.signature); + bytes.write(this.signature); - bytes.write(Ints.toByteArray(this.hashes.size())); + bytes.write(Ints.toByteArray(this.hashes.size())); - for (byte[] hash : this.hashes) { - bytes.write(hash); - } - - if (this.requestTime == null) { // To maintain backwards support - return bytes.toByteArray(); - } - - // The remaining fields are optional - - bytes.write(Longs.toByteArray(this.requestTime)); - - bytes.write(Ints.toByteArray(this.requestHops)); - - Serialization.serializeSizedStringV2(bytes, this.peerAddress); - - bytes.write(Ints.toByteArray(this.isRelayPossible ? 1 : 0)); - - return bytes.toByteArray(); - } catch (IOException e) { - return null; + for (byte[] hash : this.hashes) { + bytes.write(hash); } + + if (this.requestTime == null) { // To maintain backwards support + return bytes.toByteArray(); + } + + // The remaining fields are optional + + bytes.write(Longs.toByteArray(this.requestTime)); + + bytes.write(Ints.toByteArray(this.requestHops)); + + Serialization.serializeSizedStringV2(bytes, this.peerAddress); + + bytes.write(Ints.toByteArray(this.isRelayPossible ? 1 : 0)); + + return bytes.toByteArray(); } public ArbitraryDataFileListMessage cloneWithNewId(int newId) { diff --git a/src/main/java/org/qortal/network/message/ArbitraryDataFileMessage.java b/src/main/java/org/qortal/network/message/ArbitraryDataFileMessage.java index b9f24e29..62c5e4d4 100644 --- a/src/main/java/org/qortal/network/message/ArbitraryDataFileMessage.java +++ b/src/main/java/org/qortal/network/message/ArbitraryDataFileMessage.java @@ -9,15 +9,13 @@ import org.qortal.transform.Transformer; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; +import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; public class ArbitraryDataFileMessage extends Message { private static final Logger LOGGER = LogManager.getLogger(ArbitraryDataFileMessage.class); - private static final int SIGNATURE_LENGTH = Transformer.SIGNATURE_LENGTH; - private final byte[] signature; private final ArbitraryDataFile arbitraryDataFile; @@ -39,14 +37,14 @@ public class ArbitraryDataFileMessage extends Message { return this.arbitraryDataFile; } - public static Message fromByteBuffer(int id, ByteBuffer byteBuffer) throws UnsupportedEncodingException { - byte[] signature = new byte[SIGNATURE_LENGTH]; + public static Message fromByteBuffer(int id, ByteBuffer byteBuffer) throws MessageException { + byte[] signature = new byte[Transformer.SIGNATURE_LENGTH]; byteBuffer.get(signature); int dataLength = byteBuffer.getInt(); - if (byteBuffer.remaining() != dataLength) - return null; + if (byteBuffer.remaining() < dataLength) + throw new BufferUnderflowException(); byte[] data = new byte[dataLength]; byteBuffer.get(data); @@ -54,15 +52,14 @@ public class ArbitraryDataFileMessage extends Message { try { ArbitraryDataFile arbitraryDataFile = new ArbitraryDataFile(data, signature); return new ArbitraryDataFileMessage(id, signature, arbitraryDataFile); - } - catch (DataException e) { + } catch (DataException e) { LOGGER.info("Unable to process received file: {}", e.getMessage()); - return null; + throw new MessageException("Unable to process received file: " + e.getMessage(), e); } } @Override - protected byte[] toData() { + protected byte[] toData() throws IOException { if (this.arbitraryDataFile == null) { return null; } @@ -72,19 +69,15 @@ public class ArbitraryDataFileMessage extends Message { return null; } - try { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - bytes.write(signature); + bytes.write(signature); - bytes.write(Ints.toByteArray(data.length)); + bytes.write(Ints.toByteArray(data.length)); - bytes.write(data); + bytes.write(data); - return bytes.toByteArray(); - } catch (IOException e) { - return null; - } + return bytes.toByteArray(); } public ArbitraryDataFileMessage cloneWithNewId(int newId) { diff --git a/src/main/java/org/qortal/network/message/ArbitraryDataMessage.java b/src/main/java/org/qortal/network/message/ArbitraryDataMessage.java index 1ce149f7..b0c42942 100644 --- a/src/main/java/org/qortal/network/message/ArbitraryDataMessage.java +++ b/src/main/java/org/qortal/network/message/ArbitraryDataMessage.java @@ -2,7 +2,7 @@ package org.qortal.network.message; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; +import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import org.qortal.transform.Transformer; @@ -11,10 +11,8 @@ import com.google.common.primitives.Ints; public class ArbitraryDataMessage extends Message { - private static final int SIGNATURE_LENGTH = Transformer.SIGNATURE_LENGTH; - - private byte[] signature; - private byte[] data; + private final byte[] signature; + private final byte[] data; public ArbitraryDataMessage(byte[] signature, byte[] data) { this(-1, signature, data); @@ -35,14 +33,14 @@ public class ArbitraryDataMessage extends Message { return this.data; } - public static Message fromByteBuffer(int id, ByteBuffer byteBuffer) throws UnsupportedEncodingException { - byte[] signature = new byte[SIGNATURE_LENGTH]; + public static Message fromByteBuffer(int id, ByteBuffer byteBuffer) { + byte[] signature = new byte[Transformer.SIGNATURE_LENGTH]; byteBuffer.get(signature); int dataLength = byteBuffer.getInt(); - if (byteBuffer.remaining() != dataLength) - return null; + if (byteBuffer.remaining() < dataLength) + throw new BufferUnderflowException(); byte[] data = new byte[dataLength]; byteBuffer.get(data); @@ -51,23 +49,19 @@ public class ArbitraryDataMessage extends Message { } @Override - protected byte[] toData() { + protected byte[] toData() throws IOException { if (this.data == null) return null; - try { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - bytes.write(this.signature); + bytes.write(this.signature); - bytes.write(Ints.toByteArray(this.data.length)); + bytes.write(Ints.toByteArray(this.data.length)); - bytes.write(this.data); + bytes.write(this.data); - return bytes.toByteArray(); - } catch (IOException e) { - return null; - } + return bytes.toByteArray(); } } diff --git a/src/main/java/org/qortal/network/message/ArbitraryMetadataMessage.java b/src/main/java/org/qortal/network/message/ArbitraryMetadataMessage.java index 9228d458..fb9a3790 100644 --- a/src/main/java/org/qortal/network/message/ArbitraryMetadataMessage.java +++ b/src/main/java/org/qortal/network/message/ArbitraryMetadataMessage.java @@ -7,13 +7,11 @@ import org.qortal.transform.Transformer; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; +import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; public class ArbitraryMetadataMessage extends Message { - private static final int SIGNATURE_LENGTH = Transformer.SIGNATURE_LENGTH; - private final byte[] signature; private final ArbitraryDataFile arbitraryMetadataFile; @@ -39,14 +37,14 @@ public class ArbitraryMetadataMessage extends Message { return this.arbitraryMetadataFile; } - public static Message fromByteBuffer(int id, ByteBuffer byteBuffer) throws UnsupportedEncodingException { - byte[] signature = new byte[SIGNATURE_LENGTH]; + public static Message fromByteBuffer(int id, ByteBuffer byteBuffer) throws MessageException { + byte[] signature = new byte[Transformer.SIGNATURE_LENGTH]; byteBuffer.get(signature); int dataLength = byteBuffer.getInt(); - if (byteBuffer.remaining() != dataLength) - return null; + if (byteBuffer.remaining() < dataLength) + throw new BufferUnderflowException(); byte[] data = new byte[dataLength]; byteBuffer.get(data); @@ -54,14 +52,13 @@ public class ArbitraryMetadataMessage extends Message { try { ArbitraryDataFile arbitraryMetadataFile = new ArbitraryDataFile(data, signature); return new ArbitraryMetadataMessage(id, signature, arbitraryMetadataFile); - } - catch (DataException e) { - return null; + } catch (DataException e) { + throw new MessageException("Unable to process arbitrary metadata message: " + e.getMessage(), e); } } @Override - protected byte[] toData() { + protected byte[] toData() throws IOException { if (this.arbitraryMetadataFile == null) { return null; } @@ -71,19 +68,15 @@ public class ArbitraryMetadataMessage extends Message { return null; } - try { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - bytes.write(signature); + bytes.write(signature); - bytes.write(Ints.toByteArray(data.length)); + bytes.write(Ints.toByteArray(data.length)); - bytes.write(data); + bytes.write(data); - return bytes.toByteArray(); - } catch (IOException e) { - return null; - } + return bytes.toByteArray(); } public ArbitraryMetadataMessage cloneWithNewId(int newId) { diff --git a/src/main/java/org/qortal/network/message/ArbitrarySignaturesMessage.java b/src/main/java/org/qortal/network/message/ArbitrarySignaturesMessage.java index 1f980b3c..93c7d5e8 100644 --- a/src/main/java/org/qortal/network/message/ArbitrarySignaturesMessage.java +++ b/src/main/java/org/qortal/network/message/ArbitrarySignaturesMessage.java @@ -8,15 +8,13 @@ import org.qortal.utils.Serialization; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; +import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; public class ArbitrarySignaturesMessage extends Message { - private static final int SIGNATURE_LENGTH = Transformer.SIGNATURE_LENGTH; - private String peerAddress; private int requestHops; private List signatures; @@ -49,19 +47,24 @@ public class ArbitrarySignaturesMessage extends Message { this.requestHops = requestHops; } - public static Message fromByteBuffer(int id, ByteBuffer bytes) throws UnsupportedEncodingException, TransformationException { - String peerAddress = Serialization.deserializeSizedStringV2(bytes, PeerData.MAX_PEER_ADDRESS_SIZE); + public static Message fromByteBuffer(int id, ByteBuffer bytes) throws MessageException { + String peerAddress; + try { + peerAddress = Serialization.deserializeSizedStringV2(bytes, PeerData.MAX_PEER_ADDRESS_SIZE); + } catch (TransformationException e) { + throw new MessageException(e.getMessage(), e); + } int requestHops = bytes.getInt(); int signatureCount = bytes.getInt(); - if (bytes.remaining() != signatureCount * SIGNATURE_LENGTH) - return null; + if (bytes.remaining() < signatureCount * Transformer.SIGNATURE_LENGTH) + throw new BufferUnderflowException(); List signatures = new ArrayList<>(); for (int i = 0; i < signatureCount; ++i) { - byte[] signature = new byte[SIGNATURE_LENGTH]; + byte[] signature = new byte[Transformer.SIGNATURE_LENGTH]; bytes.get(signature); signatures.add(signature); } @@ -70,23 +73,19 @@ public class ArbitrarySignaturesMessage extends Message { } @Override - protected byte[] toData() { - try { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + protected byte[] toData() throws IOException { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - Serialization.serializeSizedStringV2(bytes, this.peerAddress); + Serialization.serializeSizedStringV2(bytes, this.peerAddress); - bytes.write(Ints.toByteArray(this.requestHops)); + bytes.write(Ints.toByteArray(this.requestHops)); - bytes.write(Ints.toByteArray(this.signatures.size())); + bytes.write(Ints.toByteArray(this.signatures.size())); - for (byte[] signature : this.signatures) - bytes.write(signature); + for (byte[] signature : this.signatures) + bytes.write(signature); - return bytes.toByteArray(); - } catch (IOException e) { - return null; - } + return bytes.toByteArray(); } } diff --git a/src/main/java/org/qortal/network/message/BlockMessage.java b/src/main/java/org/qortal/network/message/BlockMessage.java index b07dc8b1..8e66257f 100644 --- a/src/main/java/org/qortal/network/message/BlockMessage.java +++ b/src/main/java/org/qortal/network/message/BlockMessage.java @@ -2,7 +2,6 @@ package org.qortal.network.message; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.util.List; @@ -28,7 +27,7 @@ public class BlockMessage extends Message { private List transactions = null; private List atStates = null; - private int height; + private final int height; public BlockMessage(Block block) { super(MessageType.BLOCK); @@ -60,7 +59,7 @@ public class BlockMessage extends Message { return this.atStates; } - public static Message fromByteBuffer(int id, ByteBuffer byteBuffer) throws UnsupportedEncodingException { + public static Message fromByteBuffer(int id, ByteBuffer byteBuffer) throws MessageException { try { int height = byteBuffer.getInt(); @@ -72,26 +71,22 @@ public class BlockMessage extends Message { return new BlockMessage(id, blockData, blockInfo.getB(), blockInfo.getC()); } catch (TransformationException e) { LOGGER.info(String.format("Received garbled BLOCK message: %s", e.getMessage())); - return null; + throw new MessageException(e.getMessage(), e); } } @Override - protected byte[] toData() { + protected byte[] toData() throws IOException, TransformationException { if (this.block == null) return null; - try { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - bytes.write(Ints.toByteArray(this.height)); + bytes.write(Ints.toByteArray(this.height)); - bytes.write(BlockTransformer.toBytes(this.block)); + bytes.write(BlockTransformer.toBytes(this.block)); - return bytes.toByteArray(); - } catch (TransformationException | IOException e) { - return null; - } + return bytes.toByteArray(); } public BlockMessage cloneWithNewId(int newId) { diff --git a/src/main/java/org/qortal/network/message/BlockSummariesMessage.java b/src/main/java/org/qortal/network/message/BlockSummariesMessage.java index 6a30608b..56cc24e3 100644 --- a/src/main/java/org/qortal/network/message/BlockSummariesMessage.java +++ b/src/main/java/org/qortal/network/message/BlockSummariesMessage.java @@ -2,7 +2,7 @@ package org.qortal.network.message; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; +import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; @@ -17,7 +17,7 @@ public class BlockSummariesMessage extends Message { private static final int BLOCK_SUMMARY_LENGTH = BlockTransformer.BLOCK_SIGNATURE_LENGTH + Transformer.INT_LENGTH + Transformer.PUBLIC_KEY_LENGTH + Transformer.INT_LENGTH; - private List blockSummaries; + private final List blockSummaries; public BlockSummariesMessage(List blockSummaries) { this(-1, blockSummaries); @@ -33,11 +33,11 @@ public class BlockSummariesMessage extends Message { return this.blockSummaries; } - public static Message fromByteBuffer(int id, ByteBuffer bytes) throws UnsupportedEncodingException { + public static Message fromByteBuffer(int id, ByteBuffer bytes) { int count = bytes.getInt(); - if (bytes.remaining() != count * BLOCK_SUMMARY_LENGTH) - return null; + if (bytes.remaining() < count * BLOCK_SUMMARY_LENGTH) + throw new BufferUnderflowException(); List blockSummaries = new ArrayList<>(); for (int i = 0; i < count; ++i) { @@ -59,23 +59,19 @@ public class BlockSummariesMessage extends Message { } @Override - protected byte[] toData() { - try { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + protected byte[] toData() throws IOException { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - bytes.write(Ints.toByteArray(this.blockSummaries.size())); + bytes.write(Ints.toByteArray(this.blockSummaries.size())); - for (BlockSummaryData blockSummary : this.blockSummaries) { - bytes.write(Ints.toByteArray(blockSummary.getHeight())); - bytes.write(blockSummary.getSignature()); - bytes.write(blockSummary.getMinterPublicKey()); - bytes.write(Ints.toByteArray(blockSummary.getOnlineAccountsCount())); - } - - return bytes.toByteArray(); - } catch (IOException e) { - return null; + for (BlockSummaryData blockSummary : this.blockSummaries) { + bytes.write(Ints.toByteArray(blockSummary.getHeight())); + bytes.write(blockSummary.getSignature()); + bytes.write(blockSummary.getMinterPublicKey()); + bytes.write(Ints.toByteArray(blockSummary.getOnlineAccountsCount())); } + + return bytes.toByteArray(); } } diff --git a/src/main/java/org/qortal/network/message/CachedBlockMessage.java b/src/main/java/org/qortal/network/message/CachedBlockMessage.java index e5029ab0..1a6d79d9 100644 --- a/src/main/java/org/qortal/network/message/CachedBlockMessage.java +++ b/src/main/java/org/qortal/network/message/CachedBlockMessage.java @@ -2,7 +2,6 @@ package org.qortal.network.message; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import org.qortal.block.Block; @@ -14,7 +13,7 @@ import com.google.common.primitives.Ints; // This is an OUTGOING-only Message which more readily lends itself to being cached public class CachedBlockMessage extends Message { - private Block block = null; + private Block block; private byte[] cachedBytes = null; public CachedBlockMessage(Block block) { @@ -30,12 +29,12 @@ public class CachedBlockMessage extends Message { this.cachedBytes = cachedBytes; } - public static Message fromByteBuffer(int id, ByteBuffer byteBuffer) throws UnsupportedEncodingException { + public static Message fromByteBuffer(int id, ByteBuffer byteBuffer) { throw new UnsupportedOperationException("CachedBlockMessage is for outgoing messages only"); } @Override - protected byte[] toData() { + protected byte[] toData() throws IOException, TransformationException { // Already serialized? if (this.cachedBytes != null) return cachedBytes; @@ -43,22 +42,18 @@ public class CachedBlockMessage extends Message { if (this.block == null) return null; - try { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - bytes.write(Ints.toByteArray(this.block.getBlockData().getHeight())); + bytes.write(Ints.toByteArray(this.block.getBlockData().getHeight())); - bytes.write(BlockTransformer.toBytes(this.block)); + bytes.write(BlockTransformer.toBytes(this.block)); - this.cachedBytes = bytes.toByteArray(); - // We no longer need source Block - // and Block contains repository handle which is highly likely to be invalid after this call - this.block = null; + this.cachedBytes = bytes.toByteArray(); + // We no longer need source Block + // and Block contains repository handle which is highly likely to be invalid after this call + this.block = null; - return this.cachedBytes; - } catch (TransformationException | IOException e) { - return null; - } + return this.cachedBytes; } public CachedBlockMessage cloneWithNewId(int newId) { diff --git a/src/main/java/org/qortal/network/message/GetArbitraryDataFileListMessage.java b/src/main/java/org/qortal/network/message/GetArbitraryDataFileListMessage.java index 542854a5..69668242 100644 --- a/src/main/java/org/qortal/network/message/GetArbitraryDataFileListMessage.java +++ b/src/main/java/org/qortal/network/message/GetArbitraryDataFileListMessage.java @@ -5,25 +5,16 @@ import com.google.common.primitives.Longs; import org.qortal.data.network.PeerData; import org.qortal.transform.TransformationException; import org.qortal.transform.Transformer; -import org.qortal.transform.transaction.TransactionTransformer; import org.qortal.utils.Serialization; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; -import static org.qortal.transform.Transformer.INT_LENGTH; -import static org.qortal.transform.Transformer.LONG_LENGTH; - public class GetArbitraryDataFileListMessage extends Message { - private static final int SIGNATURE_LENGTH = Transformer.SIGNATURE_LENGTH; - private static final int HASH_LENGTH = TransactionTransformer.SHA256_LENGTH; - private static final int MAX_PEER_ADDRESS_LENGTH = PeerData.MAX_PEER_ADDRESS_SIZE; - private final byte[] signature; private List hashes; private final long requestTime; @@ -52,8 +43,8 @@ public class GetArbitraryDataFileListMessage extends Message { return this.hashes; } - public static Message fromByteBuffer(int id, ByteBuffer bytes) throws UnsupportedEncodingException, TransformationException { - byte[] signature = new byte[SIGNATURE_LENGTH]; + public static Message fromByteBuffer(int id, ByteBuffer bytes) throws MessageException { + byte[] signature = new byte[Transformer.SIGNATURE_LENGTH]; bytes.get(signature); @@ -67,7 +58,7 @@ public class GetArbitraryDataFileListMessage extends Message { hashes = new ArrayList<>(); for (int i = 0; i < hashCount; ++i) { - byte[] hash = new byte[HASH_LENGTH]; + byte[] hash = new byte[Transformer.SHA256_LENGTH]; bytes.get(hash); hashes.add(hash); } @@ -75,42 +66,42 @@ public class GetArbitraryDataFileListMessage extends Message { String requestingPeer = null; if (bytes.hasRemaining()) { - requestingPeer = Serialization.deserializeSizedStringV2(bytes, MAX_PEER_ADDRESS_LENGTH); + try { + requestingPeer = Serialization.deserializeSizedStringV2(bytes, PeerData.MAX_PEER_ADDRESS_SIZE); + } catch (TransformationException e) { + throw new MessageException(e.getMessage(), e); + } } return new GetArbitraryDataFileListMessage(id, signature, hashes, requestTime, requestHops, requestingPeer); } @Override - protected byte[] toData() { - try { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + protected byte[] toData() throws IOException { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - bytes.write(this.signature); + bytes.write(this.signature); - bytes.write(Longs.toByteArray(this.requestTime)); + bytes.write(Longs.toByteArray(this.requestTime)); - bytes.write(Ints.toByteArray(this.requestHops)); + bytes.write(Ints.toByteArray(this.requestHops)); - if (this.hashes != null) { - bytes.write(Ints.toByteArray(this.hashes.size())); + if (this.hashes != null) { + bytes.write(Ints.toByteArray(this.hashes.size())); - for (byte[] hash : this.hashes) { - bytes.write(hash); - } + for (byte[] hash : this.hashes) { + bytes.write(hash); } - else { - bytes.write(Ints.toByteArray(0)); - } - - if (this.requestingPeer != null) { - Serialization.serializeSizedStringV2(bytes, this.requestingPeer); - } - - return bytes.toByteArray(); - } catch (IOException e) { - return null; } + else { + bytes.write(Ints.toByteArray(0)); + } + + if (this.requestingPeer != null) { + Serialization.serializeSizedStringV2(bytes, this.requestingPeer); + } + + return bytes.toByteArray(); } public long getRequestTime() { diff --git a/src/main/java/org/qortal/network/message/GetArbitraryDataFileMessage.java b/src/main/java/org/qortal/network/message/GetArbitraryDataFileMessage.java index 809b983d..5ec5aa82 100644 --- a/src/main/java/org/qortal/network/message/GetArbitraryDataFileMessage.java +++ b/src/main/java/org/qortal/network/message/GetArbitraryDataFileMessage.java @@ -1,18 +1,13 @@ package org.qortal.network.message; import org.qortal.transform.Transformer; -import org.qortal.transform.transaction.TransactionTransformer; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; public class GetArbitraryDataFileMessage extends Message { - private static final int SIGNATURE_LENGTH = Transformer.SIGNATURE_LENGTH; - private static final int HASH_LENGTH = TransactionTransformer.SHA256_LENGTH; - private final byte[] signature; private final byte[] hash; @@ -35,32 +30,25 @@ public class GetArbitraryDataFileMessage extends Message { return this.hash; } - public static Message fromByteBuffer(int id, ByteBuffer bytes) throws UnsupportedEncodingException { - if (bytes.remaining() != HASH_LENGTH + SIGNATURE_LENGTH) - return null; - - byte[] signature = new byte[SIGNATURE_LENGTH]; + public static Message fromByteBuffer(int id, ByteBuffer bytes) { + byte[] signature = new byte[Transformer.SIGNATURE_LENGTH]; bytes.get(signature); - byte[] hash = new byte[HASH_LENGTH]; + byte[] hash = new byte[Transformer.SHA256_LENGTH]; bytes.get(hash); return new GetArbitraryDataFileMessage(id, signature, hash); } @Override - protected byte[] toData() { - try { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + protected byte[] toData() throws IOException { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - bytes.write(this.signature); + bytes.write(this.signature); - bytes.write(this.hash); + bytes.write(this.hash); - return bytes.toByteArray(); - } catch (IOException e) { - return null; - } + return bytes.toByteArray(); } } diff --git a/src/main/java/org/qortal/network/message/GetArbitraryDataMessage.java b/src/main/java/org/qortal/network/message/GetArbitraryDataMessage.java index 689d704b..df437477 100644 --- a/src/main/java/org/qortal/network/message/GetArbitraryDataMessage.java +++ b/src/main/java/org/qortal/network/message/GetArbitraryDataMessage.java @@ -2,16 +2,13 @@ package org.qortal.network.message; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import org.qortal.transform.Transformer; public class GetArbitraryDataMessage extends Message { - private static final int SIGNATURE_LENGTH = Transformer.SIGNATURE_LENGTH; - - private byte[] signature; + private final byte[] signature; public GetArbitraryDataMessage(byte[] signature) { this(-1, signature); @@ -27,11 +24,8 @@ public class GetArbitraryDataMessage extends Message { return this.signature; } - public static Message fromByteBuffer(int id, ByteBuffer bytes) throws UnsupportedEncodingException { - if (bytes.remaining() != SIGNATURE_LENGTH) - return null; - - byte[] signature = new byte[SIGNATURE_LENGTH]; + public static Message fromByteBuffer(int id, ByteBuffer bytes) { + byte[] signature = new byte[Transformer.SIGNATURE_LENGTH]; bytes.get(signature); @@ -39,16 +33,12 @@ public class GetArbitraryDataMessage extends Message { } @Override - protected byte[] toData() { - try { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + protected byte[] toData() throws IOException { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - bytes.write(this.signature); + bytes.write(this.signature); - return bytes.toByteArray(); - } catch (IOException e) { - return null; - } + return bytes.toByteArray(); } } diff --git a/src/main/java/org/qortal/network/message/GetArbitraryMetadataMessage.java b/src/main/java/org/qortal/network/message/GetArbitraryMetadataMessage.java index 66c8f86c..a4b43e41 100644 --- a/src/main/java/org/qortal/network/message/GetArbitraryMetadataMessage.java +++ b/src/main/java/org/qortal/network/message/GetArbitraryMetadataMessage.java @@ -6,16 +6,10 @@ import org.qortal.transform.Transformer; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; -import static org.qortal.transform.Transformer.INT_LENGTH; -import static org.qortal.transform.Transformer.LONG_LENGTH; - public class GetArbitraryMetadataMessage extends Message { - private static final int SIGNATURE_LENGTH = Transformer.SIGNATURE_LENGTH; - private final byte[] signature; private final long requestTime; private int requestHops; @@ -36,12 +30,8 @@ public class GetArbitraryMetadataMessage extends Message { return this.signature; } - public static Message fromByteBuffer(int id, ByteBuffer bytes) throws UnsupportedEncodingException { - if (bytes.remaining() != SIGNATURE_LENGTH + LONG_LENGTH + INT_LENGTH) - return null; - - byte[] signature = new byte[SIGNATURE_LENGTH]; - + public static Message fromByteBuffer(int id, ByteBuffer bytes) { + byte[] signature = new byte[Transformer.SIGNATURE_LENGTH]; bytes.get(signature); long requestTime = bytes.getLong(); @@ -52,20 +42,16 @@ public class GetArbitraryMetadataMessage extends Message { } @Override - protected byte[] toData() { - try { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + protected byte[] toData() throws IOException { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - bytes.write(this.signature); + bytes.write(this.signature); - bytes.write(Longs.toByteArray(this.requestTime)); + bytes.write(Longs.toByteArray(this.requestTime)); - bytes.write(Ints.toByteArray(this.requestHops)); + bytes.write(Ints.toByteArray(this.requestHops)); - return bytes.toByteArray(); - } catch (IOException e) { - return null; - } + return bytes.toByteArray(); } public long getRequestTime() { diff --git a/src/main/java/org/qortal/network/message/GetBlockMessage.java b/src/main/java/org/qortal/network/message/GetBlockMessage.java index 43484e69..538c46cd 100644 --- a/src/main/java/org/qortal/network/message/GetBlockMessage.java +++ b/src/main/java/org/qortal/network/message/GetBlockMessage.java @@ -2,16 +2,13 @@ package org.qortal.network.message; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import org.qortal.transform.block.BlockTransformer; public class GetBlockMessage extends Message { - private static final int BLOCK_SIGNATURE_LENGTH = BlockTransformer.BLOCK_SIGNATURE_LENGTH; - - private byte[] signature; + private final byte[] signature; public GetBlockMessage(byte[] signature) { this(-1, signature); @@ -27,28 +24,20 @@ public class GetBlockMessage extends Message { return this.signature; } - public static Message fromByteBuffer(int id, ByteBuffer bytes) throws UnsupportedEncodingException { - if (bytes.remaining() != BLOCK_SIGNATURE_LENGTH) - return null; - - byte[] signature = new byte[BLOCK_SIGNATURE_LENGTH]; - + public static Message fromByteBuffer(int id, ByteBuffer bytes) { + byte[] signature = new byte[BlockTransformer.BLOCK_SIGNATURE_LENGTH]; bytes.get(signature); return new GetBlockMessage(id, signature); } @Override - protected byte[] toData() { - try { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + protected byte[] toData() throws IOException { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - bytes.write(this.signature); + bytes.write(this.signature); - return bytes.toByteArray(); - } catch (IOException e) { - return null; - } + return bytes.toByteArray(); } } diff --git a/src/main/java/org/qortal/network/message/GetBlockSummariesMessage.java b/src/main/java/org/qortal/network/message/GetBlockSummariesMessage.java index 148640fd..e398d532 100644 --- a/src/main/java/org/qortal/network/message/GetBlockSummariesMessage.java +++ b/src/main/java/org/qortal/network/message/GetBlockSummariesMessage.java @@ -2,20 +2,16 @@ package org.qortal.network.message; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; -import org.qortal.transform.Transformer; import org.qortal.transform.block.BlockTransformer; import com.google.common.primitives.Ints; public class GetBlockSummariesMessage extends Message { - private static final int BLOCK_SIGNATURE_LENGTH = BlockTransformer.BLOCK_SIGNATURE_LENGTH; - - private byte[] parentSignature; - private int numberRequested; + private final byte[] parentSignature; + private final int numberRequested; public GetBlockSummariesMessage(byte[] parentSignature, int numberRequested) { this(-1, parentSignature, numberRequested); @@ -36,11 +32,8 @@ public class GetBlockSummariesMessage extends Message { return this.numberRequested; } - public static Message fromByteBuffer(int id, ByteBuffer bytes) throws UnsupportedEncodingException { - if (bytes.remaining() != BLOCK_SIGNATURE_LENGTH + Transformer.INT_LENGTH) - return null; - - byte[] parentSignature = new byte[BLOCK_SIGNATURE_LENGTH]; + public static Message fromByteBuffer(int id, ByteBuffer bytes) { + byte[] parentSignature = new byte[BlockTransformer.BLOCK_SIGNATURE_LENGTH]; bytes.get(parentSignature); int numberRequested = bytes.getInt(); @@ -49,18 +42,14 @@ public class GetBlockSummariesMessage extends Message { } @Override - protected byte[] toData() { - try { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + protected byte[] toData() throws IOException { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - bytes.write(this.parentSignature); + bytes.write(this.parentSignature); - bytes.write(Ints.toByteArray(this.numberRequested)); + bytes.write(Ints.toByteArray(this.numberRequested)); - return bytes.toByteArray(); - } catch (IOException e) { - return null; - } + return bytes.toByteArray(); } } diff --git a/src/main/java/org/qortal/network/message/GetOnlineAccountsMessage.java b/src/main/java/org/qortal/network/message/GetOnlineAccountsMessage.java index 23c21bc5..9112ba1a 100644 --- a/src/main/java/org/qortal/network/message/GetOnlineAccountsMessage.java +++ b/src/main/java/org/qortal/network/message/GetOnlineAccountsMessage.java @@ -2,7 +2,6 @@ package org.qortal.network.message; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; @@ -17,7 +16,7 @@ import com.google.common.primitives.Longs; public class GetOnlineAccountsMessage extends Message { private static final int MAX_ACCOUNT_COUNT = 5000; - private List onlineAccounts; + private final List onlineAccounts; public GetOnlineAccountsMessage(List onlineAccounts) { this(-1, onlineAccounts); @@ -33,7 +32,7 @@ public class GetOnlineAccountsMessage extends Message { return this.onlineAccounts; } - public static Message fromByteBuffer(int id, ByteBuffer bytes) throws UnsupportedEncodingException { + public static Message fromByteBuffer(int id, ByteBuffer bytes) { final int accountCount = bytes.getInt(); List onlineAccounts = new ArrayList<>(accountCount); @@ -51,23 +50,18 @@ public class GetOnlineAccountsMessage extends Message { } @Override - protected byte[] toData() { - try { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + protected byte[] toData() throws IOException { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - bytes.write(Ints.toByteArray(this.onlineAccounts.size())); + bytes.write(Ints.toByteArray(this.onlineAccounts.size())); - for (int i = 0; i < this.onlineAccounts.size(); ++i) { - OnlineAccountData onlineAccountData = this.onlineAccounts.get(i); - bytes.write(Longs.toByteArray(onlineAccountData.getTimestamp())); + for (OnlineAccountData onlineAccountData : this.onlineAccounts) { + bytes.write(Longs.toByteArray(onlineAccountData.getTimestamp())); - bytes.write(onlineAccountData.getPublicKey()); - } - - return bytes.toByteArray(); - } catch (IOException e) { - return null; + bytes.write(onlineAccountData.getPublicKey()); } + + return bytes.toByteArray(); } } diff --git a/src/main/java/org/qortal/network/message/GetOnlineAccountsV2Message.java b/src/main/java/org/qortal/network/message/GetOnlineAccountsV2Message.java index 709f9782..bc820ff1 100644 --- a/src/main/java/org/qortal/network/message/GetOnlineAccountsV2Message.java +++ b/src/main/java/org/qortal/network/message/GetOnlineAccountsV2Message.java @@ -7,7 +7,6 @@ import org.qortal.transform.Transformer; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.HashMap; @@ -24,7 +23,7 @@ import java.util.Map; * Also V2 only builds online accounts message once! */ public class GetOnlineAccountsV2Message extends Message { - private List onlineAccounts; + private final List onlineAccounts; private byte[] cachedData; public GetOnlineAccountsV2Message(List onlineAccounts) { @@ -41,7 +40,7 @@ public class GetOnlineAccountsV2Message extends Message { return this.onlineAccounts; } - public static Message fromByteBuffer(int id, ByteBuffer bytes) throws UnsupportedEncodingException { + public static Message fromByteBuffer(int id, ByteBuffer bytes) { int accountCount = bytes.getInt(); List onlineAccounts = new ArrayList<>(accountCount); @@ -68,7 +67,7 @@ public class GetOnlineAccountsV2Message extends Message { } @Override - protected synchronized byte[] toData() { + protected synchronized byte[] toData() throws IOException { if (this.cachedData != null) return this.cachedData; @@ -81,8 +80,7 @@ public class GetOnlineAccountsV2Message extends Message { // How many of each timestamp Map countByTimestamp = new HashMap<>(); - for (int i = 0; i < this.onlineAccounts.size(); ++i) { - OnlineAccountData onlineAccountData = this.onlineAccounts.get(i); + for (OnlineAccountData onlineAccountData : this.onlineAccounts) { Long timestamp = onlineAccountData.getTimestamp(); countByTimestamp.compute(timestamp, (k, v) -> v == null ? 1 : ++v); } @@ -91,27 +89,21 @@ public class GetOnlineAccountsV2Message extends Message { int byteSize = countByTimestamp.size() * (Transformer.INT_LENGTH + Transformer.TIMESTAMP_LENGTH) + this.onlineAccounts.size() * Transformer.PUBLIC_KEY_LENGTH; - try { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(byteSize); + ByteArrayOutputStream bytes = new ByteArrayOutputStream(byteSize); - for (long timestamp : countByTimestamp.keySet()) { - bytes.write(Ints.toByteArray(countByTimestamp.get(timestamp))); + for (long timestamp : countByTimestamp.keySet()) { + bytes.write(Ints.toByteArray(countByTimestamp.get(timestamp))); - bytes.write(Longs.toByteArray(timestamp)); + bytes.write(Longs.toByteArray(timestamp)); - for (int i = 0; i < this.onlineAccounts.size(); ++i) { - OnlineAccountData onlineAccountData = this.onlineAccounts.get(i); - - if (onlineAccountData.getTimestamp() == timestamp) - bytes.write(onlineAccountData.getPublicKey()); - } + for (OnlineAccountData onlineAccountData : this.onlineAccounts) { + if (onlineAccountData.getTimestamp() == timestamp) + bytes.write(onlineAccountData.getPublicKey()); } - - this.cachedData = bytes.toByteArray(); - return this.cachedData; - } catch (IOException e) { - return null; } + + this.cachedData = bytes.toByteArray(); + return this.cachedData; } } diff --git a/src/main/java/org/qortal/network/message/GetPeersMessage.java b/src/main/java/org/qortal/network/message/GetPeersMessage.java index 21b06df5..4918b92d 100644 --- a/src/main/java/org/qortal/network/message/GetPeersMessage.java +++ b/src/main/java/org/qortal/network/message/GetPeersMessage.java @@ -1,6 +1,5 @@ package org.qortal.network.message; -import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; public class GetPeersMessage extends Message { @@ -13,7 +12,7 @@ public class GetPeersMessage extends Message { super(id, MessageType.GET_PEERS); } - public static Message fromByteBuffer(int id, ByteBuffer bytes) throws UnsupportedEncodingException { + public static Message fromByteBuffer(int id, ByteBuffer bytes) { return new GetPeersMessage(id); } diff --git a/src/main/java/org/qortal/network/message/GetSignaturesV2Message.java b/src/main/java/org/qortal/network/message/GetSignaturesV2Message.java index 2dc54365..f0ac2265 100644 --- a/src/main/java/org/qortal/network/message/GetSignaturesV2Message.java +++ b/src/main/java/org/qortal/network/message/GetSignaturesV2Message.java @@ -2,21 +2,16 @@ package org.qortal.network.message; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; -import org.qortal.transform.Transformer; import org.qortal.transform.block.BlockTransformer; import com.google.common.primitives.Ints; public class GetSignaturesV2Message extends Message { - private static final int BLOCK_SIGNATURE_LENGTH = BlockTransformer.BLOCK_SIGNATURE_LENGTH; - private static final int NUMBER_REQUESTED_LENGTH = Transformer.INT_LENGTH; - - private byte[] parentSignature; - private int numberRequested; + private final byte[] parentSignature; + private final int numberRequested; public GetSignaturesV2Message(byte[] parentSignature, int numberRequested) { this(-1, parentSignature, numberRequested); @@ -37,11 +32,8 @@ public class GetSignaturesV2Message extends Message { return this.numberRequested; } - public static Message fromByteBuffer(int id, ByteBuffer bytes) throws UnsupportedEncodingException { - if (bytes.remaining() != BLOCK_SIGNATURE_LENGTH + NUMBER_REQUESTED_LENGTH) - return null; - - byte[] parentSignature = new byte[BLOCK_SIGNATURE_LENGTH]; + public static Message fromByteBuffer(int id, ByteBuffer bytes) { + byte[] parentSignature = new byte[BlockTransformer.BLOCK_SIGNATURE_LENGTH]; bytes.get(parentSignature); int numberRequested = bytes.getInt(); @@ -50,18 +42,14 @@ public class GetSignaturesV2Message extends Message { } @Override - protected byte[] toData() { - try { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + protected byte[] toData() throws IOException { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - bytes.write(this.parentSignature); + bytes.write(this.parentSignature); - bytes.write(Ints.toByteArray(this.numberRequested)); + bytes.write(Ints.toByteArray(this.numberRequested)); - return bytes.toByteArray(); - } catch (IOException e) { - return null; - } + return bytes.toByteArray(); } } diff --git a/src/main/java/org/qortal/network/message/GetTradePresencesMessage.java b/src/main/java/org/qortal/network/message/GetTradePresencesMessage.java index d9be3c1b..27fd2f9d 100644 --- a/src/main/java/org/qortal/network/message/GetTradePresencesMessage.java +++ b/src/main/java/org/qortal/network/message/GetTradePresencesMessage.java @@ -7,7 +7,6 @@ import org.qortal.transform.Transformer; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.HashMap; @@ -20,7 +19,7 @@ import java.util.Map; * Groups of: number of entries, timestamp, then AT trade pubkey for each entry. */ public class GetTradePresencesMessage extends Message { - private List tradePresences; + private final List tradePresences; private byte[] cachedData; public GetTradePresencesMessage(List tradePresences) { @@ -37,7 +36,7 @@ public class GetTradePresencesMessage extends Message { return this.tradePresences; } - public static Message fromByteBuffer(int id, ByteBuffer bytes) throws UnsupportedEncodingException { + public static Message fromByteBuffer(int id, ByteBuffer bytes) { int groupedEntriesCount = bytes.getInt(); List tradePresences = new ArrayList<>(groupedEntriesCount); @@ -64,7 +63,7 @@ public class GetTradePresencesMessage extends Message { } @Override - protected synchronized byte[] toData() { + protected synchronized byte[] toData() throws IOException { if (this.cachedData != null) return this.cachedData; @@ -86,25 +85,21 @@ public class GetTradePresencesMessage extends Message { int byteSize = countByTimestamp.size() * (Transformer.INT_LENGTH + Transformer.TIMESTAMP_LENGTH) + this.tradePresences.size() * Transformer.PUBLIC_KEY_LENGTH; - try { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(byteSize); + ByteArrayOutputStream bytes = new ByteArrayOutputStream(byteSize); - for (long timestamp : countByTimestamp.keySet()) { - bytes.write(Ints.toByteArray(countByTimestamp.get(timestamp))); + for (long timestamp : countByTimestamp.keySet()) { + bytes.write(Ints.toByteArray(countByTimestamp.get(timestamp))); - bytes.write(Longs.toByteArray(timestamp)); + bytes.write(Longs.toByteArray(timestamp)); - for (TradePresenceData tradePresenceData : this.tradePresences) { - if (tradePresenceData.getTimestamp() == timestamp) - bytes.write(tradePresenceData.getPublicKey()); - } + for (TradePresenceData tradePresenceData : this.tradePresences) { + if (tradePresenceData.getTimestamp() == timestamp) + bytes.write(tradePresenceData.getPublicKey()); } - - this.cachedData = bytes.toByteArray(); - return this.cachedData; - } catch (IOException e) { - return null; } + + this.cachedData = bytes.toByteArray(); + return this.cachedData; } } diff --git a/src/main/java/org/qortal/network/message/GetTransactionMessage.java b/src/main/java/org/qortal/network/message/GetTransactionMessage.java index 2ea06580..a0153aed 100644 --- a/src/main/java/org/qortal/network/message/GetTransactionMessage.java +++ b/src/main/java/org/qortal/network/message/GetTransactionMessage.java @@ -2,16 +2,13 @@ package org.qortal.network.message; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import org.qortal.transform.Transformer; public class GetTransactionMessage extends Message { - private static final int TRANSACTION_SIGNATURE_LENGTH = Transformer.SIGNATURE_LENGTH; - - private byte[] signature; + private final byte[] signature; public GetTransactionMessage(byte[] signature) { this(-1, signature); @@ -27,11 +24,8 @@ public class GetTransactionMessage extends Message { return this.signature; } - public static Message fromByteBuffer(int id, ByteBuffer bytes) throws UnsupportedEncodingException { - if (bytes.remaining() != TRANSACTION_SIGNATURE_LENGTH) - return null; - - byte[] signature = new byte[TRANSACTION_SIGNATURE_LENGTH]; + public static Message fromByteBuffer(int id, ByteBuffer bytes) { + byte[] signature = new byte[Transformer.SIGNATURE_LENGTH]; bytes.get(signature); @@ -39,16 +33,12 @@ public class GetTransactionMessage extends Message { } @Override - protected byte[] toData() { - try { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + protected byte[] toData() throws IOException { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - bytes.write(this.signature); + bytes.write(this.signature); - return bytes.toByteArray(); - } catch (IOException e) { - return null; - } + return bytes.toByteArray(); } } diff --git a/src/main/java/org/qortal/network/message/GetUnconfirmedTransactionsMessage.java b/src/main/java/org/qortal/network/message/GetUnconfirmedTransactionsMessage.java index 18260568..fc018e6f 100644 --- a/src/main/java/org/qortal/network/message/GetUnconfirmedTransactionsMessage.java +++ b/src/main/java/org/qortal/network/message/GetUnconfirmedTransactionsMessage.java @@ -1,6 +1,5 @@ package org.qortal.network.message; -import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; public class GetUnconfirmedTransactionsMessage extends Message { @@ -13,7 +12,7 @@ public class GetUnconfirmedTransactionsMessage extends Message { super(id, MessageType.GET_UNCONFIRMED_TRANSACTIONS); } - public static Message fromByteBuffer(int id, ByteBuffer bytes) throws UnsupportedEncodingException { + public static Message fromByteBuffer(int id, ByteBuffer bytes) { return new GetUnconfirmedTransactionsMessage(id); } diff --git a/src/main/java/org/qortal/network/message/GoodbyeMessage.java b/src/main/java/org/qortal/network/message/GoodbyeMessage.java index 75864060..8c0c221e 100644 --- a/src/main/java/org/qortal/network/message/GoodbyeMessage.java +++ b/src/main/java/org/qortal/network/message/GoodbyeMessage.java @@ -22,7 +22,7 @@ public class GoodbyeMessage extends Message { private static final Map map = stream(Reason.values()) .collect(toMap(reason -> reason.value, reason -> reason)); - private Reason(int value) { + Reason(int value) { this.value = value; } @@ -47,12 +47,12 @@ public class GoodbyeMessage extends Message { return this.reason; } - public static Message fromByteBuffer(int id, ByteBuffer byteBuffer) { + public static Message fromByteBuffer(int id, ByteBuffer byteBuffer) throws MessageException { int reasonValue = byteBuffer.getInt(); Reason reason = Reason.valueOf(reasonValue); if (reason == null) - return null; + throw new MessageException("Invalid reason " + reasonValue + " in GOODBYE message"); return new GoodbyeMessage(id, reason); } diff --git a/src/main/java/org/qortal/network/message/HeightV2Message.java b/src/main/java/org/qortal/network/message/HeightV2Message.java index 4d6f3f21..3d6a310c 100644 --- a/src/main/java/org/qortal/network/message/HeightV2Message.java +++ b/src/main/java/org/qortal/network/message/HeightV2Message.java @@ -2,7 +2,6 @@ package org.qortal.network.message; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import org.qortal.transform.Transformer; @@ -13,10 +12,10 @@ import com.google.common.primitives.Longs; public class HeightV2Message extends Message { - private int height; - private byte[] signature; - private long timestamp; - private byte[] minterPublicKey; + private final int height; + private final byte[] signature; + private final long timestamp; + private final byte[] minterPublicKey; public HeightV2Message(int height, byte[] signature, long timestamp, byte[] minterPublicKey) { this(-1, height, signature, timestamp, minterPublicKey); @@ -47,7 +46,7 @@ public class HeightV2Message extends Message { return this.minterPublicKey; } - public static Message fromByteBuffer(int id, ByteBuffer bytes) throws UnsupportedEncodingException { + public static Message fromByteBuffer(int id, ByteBuffer bytes) { int height = bytes.getInt(); byte[] signature = new byte[BlockTransformer.BLOCK_SIGNATURE_LENGTH]; @@ -62,22 +61,18 @@ public class HeightV2Message extends Message { } @Override - protected byte[] toData() { - try { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + protected byte[] toData() throws IOException { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - bytes.write(Ints.toByteArray(this.height)); + bytes.write(Ints.toByteArray(this.height)); - bytes.write(this.signature); + bytes.write(this.signature); - bytes.write(Longs.toByteArray(this.timestamp)); + bytes.write(Longs.toByteArray(this.timestamp)); - bytes.write(this.minterPublicKey); + bytes.write(this.minterPublicKey); - return bytes.toByteArray(); - } catch (IOException e) { - return null; - } + return bytes.toByteArray(); } } diff --git a/src/main/java/org/qortal/network/message/HelloMessage.java b/src/main/java/org/qortal/network/message/HelloMessage.java index 1b6de17d..80314c2e 100644 --- a/src/main/java/org/qortal/network/message/HelloMessage.java +++ b/src/main/java/org/qortal/network/message/HelloMessage.java @@ -39,15 +39,20 @@ public class HelloMessage extends Message { return this.senderPeerAddress; } - public static Message fromByteBuffer(int id, ByteBuffer byteBuffer) throws TransformationException { + public static Message fromByteBuffer(int id, ByteBuffer byteBuffer) throws MessageException { long timestamp = byteBuffer.getLong(); - String versionString = Serialization.deserializeSizedString(byteBuffer, 255); - - // Sender peer address added in v3.0, so is an optional field. Older versions won't send it. + String versionString; String senderPeerAddress = null; - if (byteBuffer.hasRemaining()) { - senderPeerAddress = Serialization.deserializeSizedString(byteBuffer, 255); + try { + versionString = Serialization.deserializeSizedString(byteBuffer, 255); + + // Sender peer address added in v3.0, so is an optional field. Older versions won't send it. + if (byteBuffer.hasRemaining()) { + senderPeerAddress = Serialization.deserializeSizedString(byteBuffer, 255); + } + } catch (TransformationException e) { + throw new MessageException(e.getMessage(), e); } return new HelloMessage(id, timestamp, versionString, senderPeerAddress); diff --git a/src/main/java/org/qortal/network/message/Message.java b/src/main/java/org/qortal/network/message/Message.java index b06a5133..15e8cb4f 100644 --- a/src/main/java/org/qortal/network/message/Message.java +++ b/src/main/java/org/qortal/network/message/Message.java @@ -1,7 +1,5 @@ package org.qortal.network.message; -import java.util.Map; - import org.qortal.crypto.Crypto; import org.qortal.network.Network; import org.qortal.transform.TransformationException; @@ -13,8 +11,6 @@ import static java.util.stream.Collectors.toMap; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import java.util.Arrays; @@ -27,127 +23,6 @@ public abstract class Message { private static final int MAX_DATA_SIZE = 10 * 1024 * 1024; // 10MB - @SuppressWarnings("serial") - public static class MessageException extends Exception { - public MessageException() { - } - - public MessageException(String message) { - super(message); - } - - public MessageException(String message, Throwable cause) { - super(message, cause); - } - - public MessageException(Throwable cause) { - super(cause); - } - } - - public enum MessageType { - // Handshaking - HELLO(0), - GOODBYE(1), - CHALLENGE(2), - RESPONSE(3), - - // Status / notifications - HEIGHT_V2(10), - PING(11), - PONG(12), - - // Requesting data - PEERS_V2(20), - GET_PEERS(21), - - TRANSACTION(30), - GET_TRANSACTION(31), - - TRANSACTION_SIGNATURES(40), - GET_UNCONFIRMED_TRANSACTIONS(41), - - BLOCK(50), - GET_BLOCK(51), - - SIGNATURES(60), - GET_SIGNATURES_V2(61), - - BLOCK_SUMMARIES(70), - GET_BLOCK_SUMMARIES(71), - - ONLINE_ACCOUNTS(80), - GET_ONLINE_ACCOUNTS(81), - ONLINE_ACCOUNTS_V2(82), - GET_ONLINE_ACCOUNTS_V2(83), - - ARBITRARY_DATA(90), - GET_ARBITRARY_DATA(91), - - BLOCKS(100), - GET_BLOCKS(101), - - ARBITRARY_DATA_FILE(110), - GET_ARBITRARY_DATA_FILE(111), - - ARBITRARY_DATA_FILE_LIST(120), - GET_ARBITRARY_DATA_FILE_LIST(121), - - ARBITRARY_SIGNATURES(130), - - TRADE_PRESENCES(140), - GET_TRADE_PRESENCES(141), - - ARBITRARY_METADATA(150), - GET_ARBITRARY_METADATA(151); - - public final int value; - public final Method fromByteBufferMethod; - - private static final Map map = stream(MessageType.values()) - .collect(toMap(messageType -> messageType.value, messageType -> messageType)); - - private MessageType(int value) { - this.value = value; - - String[] classNameParts = this.name().toLowerCase().split("_"); - - for (int i = 0; i < classNameParts.length; ++i) - classNameParts[i] = classNameParts[i].substring(0, 1).toUpperCase().concat(classNameParts[i].substring(1)); - - String className = String.join("", classNameParts); - - Method method; - try { - Class subclass = Class.forName(String.join("", Message.class.getPackage().getName(), ".", className, "Message")); - - method = subclass.getDeclaredMethod("fromByteBuffer", int.class, ByteBuffer.class); - } catch (ClassNotFoundException | NoSuchMethodException | SecurityException e) { - method = null; - } - - this.fromByteBufferMethod = method; - } - - public static MessageType valueOf(int value) { - return map.get(value); - } - - public Message fromByteBuffer(int id, ByteBuffer byteBuffer) throws MessageException { - if (this.fromByteBufferMethod == null) - throw new MessageException("Unsupported message type [" + value + "] during conversion from bytes"); - - try { - return (Message) this.fromByteBufferMethod.invoke(null, id, byteBuffer); - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - if (e.getCause() instanceof BufferUnderflowException) - throw new MessageException("Byte data too short for " + name() + " message"); - - throw new MessageException("Internal error with " + name() + " message during conversion from bytes"); - } - } - } - private int id; private MessageType type; @@ -181,7 +56,7 @@ public abstract class Message { * * @param readOnlyBuffer * @return null if no complete message can be read - * @throws MessageException + * @throws MessageException if message could not be decoded or is invalid */ public static Message fromByteBuffer(ByteBuffer readOnlyBuffer) throws MessageException { try { @@ -293,6 +168,12 @@ public abstract class Message { } } + /** Serialize message into bytes. + * + * @return message as byte array, or null if message is missing payload data / uninitialized somehow + * @throws IOException if unable / failed to serialize + * @throws TransformationException if unable / failed to serialize + */ protected abstract byte[] toData() throws IOException, TransformationException; } diff --git a/src/main/java/org/qortal/network/message/MessageException.java b/src/main/java/org/qortal/network/message/MessageException.java new file mode 100644 index 00000000..97e8d0be --- /dev/null +++ b/src/main/java/org/qortal/network/message/MessageException.java @@ -0,0 +1,19 @@ +package org.qortal.network.message; + +@SuppressWarnings("serial") +public class MessageException extends Exception { + public MessageException() { + } + + public MessageException(String message) { + super(message); + } + + public MessageException(String message, Throwable cause) { + super(message, cause); + } + + public MessageException(Throwable cause) { + super(cause); + } +} diff --git a/src/main/java/org/qortal/network/message/MessageProducer.java b/src/main/java/org/qortal/network/message/MessageProducer.java new file mode 100644 index 00000000..7f203788 --- /dev/null +++ b/src/main/java/org/qortal/network/message/MessageProducer.java @@ -0,0 +1,8 @@ +package org.qortal.network.message; + +import java.nio.ByteBuffer; + +@FunctionalInterface +public interface MessageProducer { + Message fromByteBuffer(int id, ByteBuffer byteBuffer) throws MessageException; +} diff --git a/src/main/java/org/qortal/network/message/MessageType.java b/src/main/java/org/qortal/network/message/MessageType.java new file mode 100644 index 00000000..48039a4d --- /dev/null +++ b/src/main/java/org/qortal/network/message/MessageType.java @@ -0,0 +1,96 @@ +package org.qortal.network.message; + +import java.nio.BufferUnderflowException; +import java.nio.ByteBuffer; +import java.util.Map; + +import static java.util.Arrays.stream; +import static java.util.stream.Collectors.toMap; + +public enum MessageType { + // Handshaking + HELLO(0, HelloMessage::fromByteBuffer), + GOODBYE(1, GoodbyeMessage::fromByteBuffer), + CHALLENGE(2, ChallengeMessage::fromByteBuffer), + RESPONSE(3, ResponseMessage::fromByteBuffer), + + // Status / notifications + HEIGHT_V2(10, HeightV2Message::fromByteBuffer), + PING(11, PingMessage::fromByteBuffer), + PONG(12, PongMessage::fromByteBuffer), + + // Requesting data + PEERS_V2(20, PeersV2Message::fromByteBuffer), + GET_PEERS(21, GetPeersMessage::fromByteBuffer), + + TRANSACTION(30, TransactionMessage::fromByteBuffer), + GET_TRANSACTION(31, GetTransactionMessage::fromByteBuffer), + + TRANSACTION_SIGNATURES(40, TransactionSignaturesMessage::fromByteBuffer), + GET_UNCONFIRMED_TRANSACTIONS(41, GetUnconfirmedTransactionsMessage::fromByteBuffer), + + BLOCK(50, BlockMessage::fromByteBuffer), + GET_BLOCK(51, GetBlockMessage::fromByteBuffer), + + SIGNATURES(60, SignaturesMessage::fromByteBuffer), + GET_SIGNATURES_V2(61, GetSignaturesV2Message::fromByteBuffer), + + BLOCK_SUMMARIES(70, BlockSummariesMessage::fromByteBuffer), + GET_BLOCK_SUMMARIES(71, GetBlockSummariesMessage::fromByteBuffer), + + ONLINE_ACCOUNTS(80, OnlineAccountsMessage::fromByteBuffer), + GET_ONLINE_ACCOUNTS(81, GetOnlineAccountsMessage::fromByteBuffer), + ONLINE_ACCOUNTS_V2(82, OnlineAccountsV2Message::fromByteBuffer), + GET_ONLINE_ACCOUNTS_V2(83, GetOnlineAccountsV2Message::fromByteBuffer), + + ARBITRARY_DATA(90, ArbitraryDataMessage::fromByteBuffer), + GET_ARBITRARY_DATA(91, GetArbitraryDataMessage::fromByteBuffer), + + BLOCKS(100, null), // unsupported + GET_BLOCKS(101, null), // unsupported + + ARBITRARY_DATA_FILE(110, ArbitraryDataFileMessage::fromByteBuffer), + GET_ARBITRARY_DATA_FILE(111, GetArbitraryDataFileMessage::fromByteBuffer), + + ARBITRARY_DATA_FILE_LIST(120, ArbitraryDataFileListMessage::fromByteBuffer), + GET_ARBITRARY_DATA_FILE_LIST(121, GetArbitraryDataFileListMessage::fromByteBuffer), + + ARBITRARY_SIGNATURES(130, ArbitrarySignaturesMessage::fromByteBuffer), + + TRADE_PRESENCES(140, TradePresencesMessage::fromByteBuffer), + GET_TRADE_PRESENCES(141, GetTradePresencesMessage::fromByteBuffer), + + ARBITRARY_METADATA(150, ArbitraryMetadataMessage::fromByteBuffer), + GET_ARBITRARY_METADATA(151, GetArbitraryMetadataMessage::fromByteBuffer); + + public final int value; + public final MessageProducer fromByteBufferMethod; + + private static final Map map = stream(MessageType.values()) + .collect(toMap(messageType -> messageType.value, messageType -> messageType)); + + MessageType(int value, MessageProducer fromByteBufferMethod) { + this.value = value; + this.fromByteBufferMethod = fromByteBufferMethod; + } + + public static MessageType valueOf(int value) { + return map.get(value); + } + + /** + * Attempt to read a message from byte buffer. + * + * @param id message ID or -1 + * @param byteBuffer ByteBuffer source for message + * @return null if no complete message can be read + * @throws MessageException if message could not be decoded or is invalid + * @throws BufferUnderflowException if not enough bytes in buffer to read message + */ + public Message fromByteBuffer(int id, ByteBuffer byteBuffer) throws MessageException { + if (this.fromByteBufferMethod == null) + throw new MessageException("Message type " + this.name() + " unsupported"); + + return this.fromByteBufferMethod.fromByteBuffer(id, byteBuffer); + } +} diff --git a/src/main/java/org/qortal/network/message/OnlineAccountsMessage.java b/src/main/java/org/qortal/network/message/OnlineAccountsMessage.java index 02c46717..d7acb2fd 100644 --- a/src/main/java/org/qortal/network/message/OnlineAccountsMessage.java +++ b/src/main/java/org/qortal/network/message/OnlineAccountsMessage.java @@ -2,7 +2,6 @@ package org.qortal.network.message; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; @@ -17,7 +16,7 @@ import com.google.common.primitives.Longs; public class OnlineAccountsMessage extends Message { private static final int MAX_ACCOUNT_COUNT = 5000; - private List onlineAccounts; + private final List onlineAccounts; public OnlineAccountsMessage(List onlineAccounts) { this(-1, onlineAccounts); @@ -33,7 +32,7 @@ public class OnlineAccountsMessage extends Message { return this.onlineAccounts; } - public static Message fromByteBuffer(int id, ByteBuffer bytes) throws UnsupportedEncodingException { + public static Message fromByteBuffer(int id, ByteBuffer bytes) { final int accountCount = bytes.getInt(); List onlineAccounts = new ArrayList<>(accountCount); @@ -55,26 +54,20 @@ public class OnlineAccountsMessage extends Message { } @Override - protected byte[] toData() { - try { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + protected byte[] toData() throws IOException { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - bytes.write(Ints.toByteArray(this.onlineAccounts.size())); + bytes.write(Ints.toByteArray(this.onlineAccounts.size())); - for (int i = 0; i < this.onlineAccounts.size(); ++i) { - OnlineAccountData onlineAccountData = this.onlineAccounts.get(i); + for (OnlineAccountData onlineAccountData : this.onlineAccounts) { + bytes.write(Longs.toByteArray(onlineAccountData.getTimestamp())); - bytes.write(Longs.toByteArray(onlineAccountData.getTimestamp())); + bytes.write(onlineAccountData.getSignature()); - bytes.write(onlineAccountData.getSignature()); - - bytes.write(onlineAccountData.getPublicKey()); - } - - return bytes.toByteArray(); - } catch (IOException e) { - return null; + bytes.write(onlineAccountData.getPublicKey()); } + + return bytes.toByteArray(); } } diff --git a/src/main/java/org/qortal/network/message/OnlineAccountsV2Message.java b/src/main/java/org/qortal/network/message/OnlineAccountsV2Message.java index f0fce81e..955237fe 100644 --- a/src/main/java/org/qortal/network/message/OnlineAccountsV2Message.java +++ b/src/main/java/org/qortal/network/message/OnlineAccountsV2Message.java @@ -7,13 +7,11 @@ import org.qortal.transform.Transformer; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; /** * For sending online accounts info to remote peer. @@ -25,7 +23,7 @@ import java.util.stream.Collectors; * Also V2 only builds online accounts message once! */ public class OnlineAccountsV2Message extends Message { - private List onlineAccounts; + private final List onlineAccounts; private byte[] cachedData; public OnlineAccountsV2Message(List onlineAccounts) { @@ -42,7 +40,7 @@ public class OnlineAccountsV2Message extends Message { return this.onlineAccounts; } - public static Message fromByteBuffer(int id, ByteBuffer bytes) throws UnsupportedEncodingException { + public static Message fromByteBuffer(int id, ByteBuffer bytes) throws MessageException { int accountCount = bytes.getInt(); List onlineAccounts = new ArrayList<>(accountCount); @@ -72,7 +70,7 @@ public class OnlineAccountsV2Message extends Message { } @Override - protected synchronized byte[] toData() { + protected synchronized byte[] toData() throws IOException { if (this.cachedData != null) return this.cachedData; @@ -85,8 +83,7 @@ public class OnlineAccountsV2Message extends Message { // How many of each timestamp Map countByTimestamp = new HashMap<>(); - for (int i = 0; i < this.onlineAccounts.size(); ++i) { - OnlineAccountData onlineAccountData = this.onlineAccounts.get(i); + for (OnlineAccountData onlineAccountData : this.onlineAccounts) { Long timestamp = onlineAccountData.getTimestamp(); countByTimestamp.compute(timestamp, (k, v) -> v == null ? 1 : ++v); } @@ -95,30 +92,23 @@ public class OnlineAccountsV2Message extends Message { int byteSize = countByTimestamp.size() * (Transformer.INT_LENGTH + Transformer.TIMESTAMP_LENGTH) + this.onlineAccounts.size() * (Transformer.SIGNATURE_LENGTH + Transformer.PUBLIC_KEY_LENGTH); - try { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(byteSize); + ByteArrayOutputStream bytes = new ByteArrayOutputStream(byteSize); - for (long timestamp : countByTimestamp.keySet()) { - bytes.write(Ints.toByteArray(countByTimestamp.get(timestamp))); + for (long timestamp : countByTimestamp.keySet()) { + bytes.write(Ints.toByteArray(countByTimestamp.get(timestamp))); - bytes.write(Longs.toByteArray(timestamp)); + bytes.write(Longs.toByteArray(timestamp)); - for (int i = 0; i < this.onlineAccounts.size(); ++i) { - OnlineAccountData onlineAccountData = this.onlineAccounts.get(i); - - if (onlineAccountData.getTimestamp() == timestamp) { - bytes.write(onlineAccountData.getSignature()); - - bytes.write(onlineAccountData.getPublicKey()); - } + for (OnlineAccountData onlineAccountData : this.onlineAccounts) { + if (onlineAccountData.getTimestamp() == timestamp) { + bytes.write(onlineAccountData.getSignature()); + bytes.write(onlineAccountData.getPublicKey()); } } - - this.cachedData = bytes.toByteArray(); - return this.cachedData; - } catch (IOException e) { - return null; } + + this.cachedData = bytes.toByteArray(); + return this.cachedData; } } diff --git a/src/main/java/org/qortal/network/message/PeersV2Message.java b/src/main/java/org/qortal/network/message/PeersV2Message.java index bfea87c7..4166c37d 100644 --- a/src/main/java/org/qortal/network/message/PeersV2Message.java +++ b/src/main/java/org/qortal/network/message/PeersV2Message.java @@ -2,7 +2,6 @@ package org.qortal.network.message; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.ArrayList; @@ -16,7 +15,7 @@ import com.google.common.primitives.Ints; // NOTE: this message supports hostnames, literal IP addresses (IPv4 and IPv6) with port numbers public class PeersV2Message extends Message { - private List peerAddresses; + private final List peerAddresses; public PeersV2Message(List peerAddresses) { this(-1, peerAddresses); @@ -32,7 +31,7 @@ public class PeersV2Message extends Message { return this.peerAddresses; } - public static Message fromByteBuffer(int id, ByteBuffer byteBuffer) throws UnsupportedEncodingException { + public static Message fromByteBuffer(int id, ByteBuffer byteBuffer) throws MessageException { // Read entry count int count = byteBuffer.getInt(); @@ -49,7 +48,7 @@ public class PeersV2Message extends Message { PeerAddress peerAddress = PeerAddress.fromString(addressString); peerAddresses.add(peerAddress); } catch (IllegalArgumentException e) { - // Not valid - ignore + throw new MessageException("Invalid peer address in received PEERS_V2 message"); } } @@ -57,35 +56,31 @@ public class PeersV2Message extends Message { } @Override - protected byte[] toData() { - try { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + protected byte[] toData() throws IOException { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - List addresses = new ArrayList<>(); + List addresses = new ArrayList<>(); - // First entry represents sending node but contains only port number with empty address. - addresses.add(("0.0.0.0:" + Settings.getInstance().getListenPort()).getBytes(StandardCharsets.UTF_8)); + // First entry represents sending node but contains only port number with empty address. + addresses.add(("0.0.0.0:" + Settings.getInstance().getListenPort()).getBytes(StandardCharsets.UTF_8)); - for (PeerAddress peerAddress : this.peerAddresses) - addresses.add(peerAddress.toString().getBytes(StandardCharsets.UTF_8)); + for (PeerAddress peerAddress : this.peerAddresses) + addresses.add(peerAddress.toString().getBytes(StandardCharsets.UTF_8)); - // We can't send addresses that are longer than 255 bytes as length itself is encoded in one byte. - addresses.removeIf(addressString -> addressString.length > 255); + // We can't send addresses that are longer than 255 bytes as length itself is encoded in one byte. + addresses.removeIf(addressString -> addressString.length > 255); - // Serialize + // Serialize - // Number of entries - bytes.write(Ints.toByteArray(addresses.size())); + // Number of entries + bytes.write(Ints.toByteArray(addresses.size())); - for (byte[] address : addresses) { - bytes.write(address.length); - bytes.write(address); - } - - return bytes.toByteArray(); - } catch (IOException e) { - return null; + for (byte[] address : addresses) { + bytes.write(address.length); + bytes.write(address); } + + return bytes.toByteArray(); } } diff --git a/src/main/java/org/qortal/network/message/PingMessage.java b/src/main/java/org/qortal/network/message/PingMessage.java index ddec0fd7..fa04fdb6 100644 --- a/src/main/java/org/qortal/network/message/PingMessage.java +++ b/src/main/java/org/qortal/network/message/PingMessage.java @@ -1,6 +1,5 @@ package org.qortal.network.message; -import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; public class PingMessage extends Message { @@ -13,7 +12,7 @@ public class PingMessage extends Message { super(id, MessageType.PING); } - public static Message fromByteBuffer(int id, ByteBuffer bytes) throws UnsupportedEncodingException { + public static Message fromByteBuffer(int id, ByteBuffer bytes) { return new PingMessage(id); } diff --git a/src/main/java/org/qortal/network/message/PongMessage.java b/src/main/java/org/qortal/network/message/PongMessage.java new file mode 100644 index 00000000..4338aeac --- /dev/null +++ b/src/main/java/org/qortal/network/message/PongMessage.java @@ -0,0 +1,24 @@ +package org.qortal.network.message; + +import java.nio.ByteBuffer; + +public class PongMessage extends Message { + + public PongMessage() { + this(-1); + } + + private PongMessage(int id) { + super(id, MessageType.PONG); + } + + public static Message fromByteBuffer(int id, ByteBuffer bytes) { + return new PongMessage(id); + } + + @Override + protected byte[] toData() { + return new byte[0]; + } + +} diff --git a/src/main/java/org/qortal/network/message/SignaturesMessage.java b/src/main/java/org/qortal/network/message/SignaturesMessage.java index 008f4c1a..cbbaf790 100644 --- a/src/main/java/org/qortal/network/message/SignaturesMessage.java +++ b/src/main/java/org/qortal/network/message/SignaturesMessage.java @@ -2,7 +2,7 @@ package org.qortal.network.message; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; +import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; @@ -13,9 +13,7 @@ import com.google.common.primitives.Ints; public class SignaturesMessage extends Message { - private static final int BLOCK_SIGNATURE_LENGTH = BlockTransformer.BLOCK_SIGNATURE_LENGTH; - - private List signatures; + private final List signatures; public SignaturesMessage(List signatures) { this(-1, signatures); @@ -31,15 +29,15 @@ public class SignaturesMessage extends Message { return this.signatures; } - public static Message fromByteBuffer(int id, ByteBuffer bytes) throws UnsupportedEncodingException { + public static Message fromByteBuffer(int id, ByteBuffer bytes) { int count = bytes.getInt(); - if (bytes.remaining() != count * BLOCK_SIGNATURE_LENGTH) - return null; + if (bytes.remaining() < count * BlockTransformer.BLOCK_SIGNATURE_LENGTH) + throw new BufferUnderflowException(); List signatures = new ArrayList<>(); for (int i = 0; i < count; ++i) { - byte[] signature = new byte[BLOCK_SIGNATURE_LENGTH]; + byte[] signature = new byte[BlockTransformer.BLOCK_SIGNATURE_LENGTH]; bytes.get(signature); signatures.add(signature); } @@ -48,19 +46,15 @@ public class SignaturesMessage extends Message { } @Override - protected byte[] toData() { - try { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + protected byte[] toData() throws IOException { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - bytes.write(Ints.toByteArray(this.signatures.size())); + bytes.write(Ints.toByteArray(this.signatures.size())); - for (byte[] signature : this.signatures) - bytes.write(signature); + for (byte[] signature : this.signatures) + bytes.write(signature); - return bytes.toByteArray(); - } catch (IOException e) { - return null; - } + return bytes.toByteArray(); } } diff --git a/src/main/java/org/qortal/network/message/TradePresencesMessage.java b/src/main/java/org/qortal/network/message/TradePresencesMessage.java index 9d846722..20edfdaf 100644 --- a/src/main/java/org/qortal/network/message/TradePresencesMessage.java +++ b/src/main/java/org/qortal/network/message/TradePresencesMessage.java @@ -8,7 +8,6 @@ import org.qortal.utils.Base58; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.HashMap; @@ -21,7 +20,7 @@ import java.util.Map; * Groups of: number of entries, timestamp, then pubkey + sig + AT address for each entry. */ public class TradePresencesMessage extends Message { - private List tradePresences; + private final List tradePresences; private byte[] cachedData; public TradePresencesMessage(List tradePresences) { @@ -38,7 +37,7 @@ public class TradePresencesMessage extends Message { return this.tradePresences; } - public static Message fromByteBuffer(int id, ByteBuffer bytes) throws UnsupportedEncodingException { + public static Message fromByteBuffer(int id, ByteBuffer bytes) { int groupedEntriesCount = bytes.getInt(); List tradePresences = new ArrayList<>(groupedEntriesCount); @@ -72,7 +71,7 @@ public class TradePresencesMessage extends Message { } @Override - protected synchronized byte[] toData() { + protected synchronized byte[] toData() throws IOException { if (this.cachedData != null) return this.cachedData; @@ -94,30 +93,26 @@ public class TradePresencesMessage extends Message { int byteSize = countByTimestamp.size() * (Transformer.INT_LENGTH + Transformer.TIMESTAMP_LENGTH) + this.tradePresences.size() * (Transformer.PUBLIC_KEY_LENGTH + Transformer.SIGNATURE_LENGTH + Transformer.ADDRESS_LENGTH); - try { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(byteSize); + ByteArrayOutputStream bytes = new ByteArrayOutputStream(byteSize); - for (long timestamp : countByTimestamp.keySet()) { - bytes.write(Ints.toByteArray(countByTimestamp.get(timestamp))); + for (long timestamp : countByTimestamp.keySet()) { + bytes.write(Ints.toByteArray(countByTimestamp.get(timestamp))); - bytes.write(Longs.toByteArray(timestamp)); + bytes.write(Longs.toByteArray(timestamp)); - for (TradePresenceData tradePresenceData : this.tradePresences) { - if (tradePresenceData.getTimestamp() == timestamp) { - bytes.write(tradePresenceData.getPublicKey()); + for (TradePresenceData tradePresenceData : this.tradePresences) { + if (tradePresenceData.getTimestamp() == timestamp) { + bytes.write(tradePresenceData.getPublicKey()); - bytes.write(tradePresenceData.getSignature()); + bytes.write(tradePresenceData.getSignature()); - bytes.write(Base58.decode(tradePresenceData.getAtAddress())); - } + bytes.write(Base58.decode(tradePresenceData.getAtAddress())); } } - - this.cachedData = bytes.toByteArray(); - return this.cachedData; - } catch (IOException e) { - return null; } + + this.cachedData = bytes.toByteArray(); + return this.cachedData; } } diff --git a/src/main/java/org/qortal/network/message/TransactionMessage.java b/src/main/java/org/qortal/network/message/TransactionMessage.java index 92cce086..6aa3c96f 100644 --- a/src/main/java/org/qortal/network/message/TransactionMessage.java +++ b/src/main/java/org/qortal/network/message/TransactionMessage.java @@ -1,6 +1,5 @@ package org.qortal.network.message; -import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import org.qortal.data.transaction.TransactionData; @@ -25,26 +24,24 @@ public class TransactionMessage extends Message { return this.transactionData; } - public static Message fromByteBuffer(int id, ByteBuffer byteBuffer) throws UnsupportedEncodingException { - try { - TransactionData transactionData = TransactionTransformer.fromByteBuffer(byteBuffer); + public static Message fromByteBuffer(int id, ByteBuffer byteBuffer) throws MessageException { + TransactionData transactionData; - return new TransactionMessage(id, transactionData); + try { + transactionData = TransactionTransformer.fromByteBuffer(byteBuffer); } catch (TransformationException e) { - return null; + throw new MessageException(e.getMessage(), e); } + + return new TransactionMessage(id, transactionData); } @Override - protected byte[] toData() { + protected byte[] toData() throws TransformationException { if (this.transactionData == null) return null; - try { - return TransactionTransformer.toBytes(this.transactionData); - } catch (TransformationException e) { - return null; - } + return TransactionTransformer.toBytes(this.transactionData); } } diff --git a/src/main/java/org/qortal/network/message/TransactionSignaturesMessage.java b/src/main/java/org/qortal/network/message/TransactionSignaturesMessage.java index 082a7187..9d049e20 100644 --- a/src/main/java/org/qortal/network/message/TransactionSignaturesMessage.java +++ b/src/main/java/org/qortal/network/message/TransactionSignaturesMessage.java @@ -2,7 +2,7 @@ package org.qortal.network.message; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; +import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; @@ -13,9 +13,7 @@ import com.google.common.primitives.Ints; public class TransactionSignaturesMessage extends Message { - private static final int SIGNATURE_LENGTH = Transformer.SIGNATURE_LENGTH; - - private List signatures; + private final List signatures; public TransactionSignaturesMessage(List signatures) { this(-1, signatures); @@ -31,15 +29,15 @@ public class TransactionSignaturesMessage extends Message { return this.signatures; } - public static Message fromByteBuffer(int id, ByteBuffer bytes) throws UnsupportedEncodingException { + public static Message fromByteBuffer(int id, ByteBuffer bytes) { int count = bytes.getInt(); - if (bytes.remaining() != count * SIGNATURE_LENGTH) - return null; + if (bytes.remaining() < count * Transformer.SIGNATURE_LENGTH) + throw new BufferUnderflowException(); List signatures = new ArrayList<>(); for (int i = 0; i < count; ++i) { - byte[] signature = new byte[SIGNATURE_LENGTH]; + byte[] signature = new byte[Transformer.SIGNATURE_LENGTH]; bytes.get(signature); signatures.add(signature); } @@ -48,19 +46,15 @@ public class TransactionSignaturesMessage extends Message { } @Override - protected byte[] toData() { - try { - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + protected byte[] toData() throws IOException { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - bytes.write(Ints.toByteArray(this.signatures.size())); + bytes.write(Ints.toByteArray(this.signatures.size())); - for (byte[] signature : this.signatures) - bytes.write(signature); + for (byte[] signature : this.signatures) + bytes.write(signature); - return bytes.toByteArray(); - } catch (IOException e) { - return null; - } + return bytes.toByteArray(); } } diff --git a/src/test/java/org/qortal/test/network/OnlineAccountsTests.java b/src/test/java/org/qortal/test/network/OnlineAccountsTests.java index b1c5ec4f..4154121c 100644 --- a/src/test/java/org/qortal/test/network/OnlineAccountsTests.java +++ b/src/test/java/org/qortal/test/network/OnlineAccountsTests.java @@ -29,7 +29,7 @@ public class OnlineAccountsTests { @Test - public void testGetOnlineAccountsV2() throws Message.MessageException { + public void testGetOnlineAccountsV2() throws MessageException { List onlineAccountsOut = generateOnlineAccounts(false); Message messageOut = new GetOnlineAccountsV2Message(onlineAccountsOut); @@ -58,7 +58,7 @@ public class OnlineAccountsTests { } @Test - public void testOnlineAccountsV2() throws Message.MessageException { + public void testOnlineAccountsV2() throws MessageException { List onlineAccountsOut = generateOnlineAccounts(true); Message messageOut = new OnlineAccountsV2Message(onlineAccountsOut);