package org.bitseal.core;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import org.bitseal.crypt.SHA512;
import org.bitseal.util.ArrayCopier;
import org.bitseal.util.ByteFormatter;
import org.bitseal.util.ByteUtils;
public class MessageProcessor
{
/** A magic hexadecimal value used by Bitmessage to identify network packets. See https://bitmessage.org/wiki/Protocol_specification#Message_structure */
private static final String BITMESSAGE_MAGIC_IDENTIFIER = "E9BEB4D9";
/** Identifies the Message contents. See https://bitmessage.org/wiki/Protocol_specification#Message_structure */
private static final String BITMESSAGE_OBJECT_COMMAND = "object";
/** Padding for the command. See https://bitmessage.org/wiki/Protocol_specification#Message_structure */
private static final String BITMESSAGE_OBJECT_COMMAND_PADDING = "000000000000";
/** The character encoding used in the Bitmessage command data */
private static final String BITMESSAGE_COMMAND_ENCODING = "US-ASCII";
protected byte[] generateObjectHeader (byte[] payload)
{
return generateMessageHeader(BITMESSAGE_OBJECT_COMMAND, payload);
}
/**
* Creates the header for a Message to be sent between Bitmessage nodes. For a specification of the header see
* https://bitmessage.org/wiki/Protocol_specification#Message_structure
*
* @param - command - A String that identifies the Message type
* @param - payload - A byte[] containing the Message to construct a header for
*
* @return A byte[] containing the Message header
*/
private byte[] generateMessageHeader (String command, byte[] payload)
{
// Get the byte values of all the data that needs to go in the message header
byte[] magicBytes = ByteFormatter.hexStringToByteArray(BITMESSAGE_MAGIC_IDENTIFIER);
byte[] commandBytes = null;
try
{
commandBytes = command.getBytes(BITMESSAGE_COMMAND_ENCODING);
byte[] commandPadding = ByteFormatter.hexStringToByteArray(BITMESSAGE_OBJECT_COMMAND_PADDING);
commandBytes = ByteUtils.concatenateByteArrays(commandBytes, commandPadding);
}
catch (UnsupportedEncodingException e)
{
throw new RuntimeException("UnsupportedEncodingException occurred in OutgoingMessageProcessor.constructMsgHeader()", e);
}
int payloadLength = payload.length;
byte[] payloadLengthBytes = ByteUtils.intToBytes(payloadLength);
byte[] checksumFullHash = SHA512.sha512(payload);
byte[] checksum = ArrayCopier.copyOfRange(checksumFullHash, 0, 4);
// Now combine all the assembled data into a single byte[]. This is the message header.
byte[] msgHeader = null;
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try
{
outputStream.write(magicBytes);
outputStream.write(commandBytes);
outputStream.write(payloadLengthBytes);
outputStream.write(checksum);
msgHeader = outputStream.toByteArray();
outputStream.close();
}
catch (IOException e)
{
throw new RuntimeException("IOException occurred in DataProcessor.constructMsgHeader()", e);
}
return msgHeader;
}
}