gappleto97/p2p-project

View on GitHub
jv_src/InternalMessage.java

Summary

Maintainability
A
0 mins
Test Coverage
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.math.BigInteger;
import java.lang.StringBuilder;
import java.util.Arrays;
import java.util.ArrayList;

public class InternalMessage    {
    String msg_type;
    String sender;
    String[] payload;
    long time;
    byte[][] compression;

    public InternalMessage(String msg_type, String sender, String[] payload, byte[][] compression, long timestamp)   {
        this.msg_type = msg_type;
        this.sender = sender;
        this.payload = payload;
        this.compression = compression;
        this.time = timestamp;
    }

    public InternalMessage(String msg_type, String sender, String[] payload, byte[][] compression)  {
        this(msg_type, sender, payload, compression, base.getUTC());
    }

    public InternalMessage(String msg_type, String sender, String[] payload, long timestamp) {
        this(msg_type, sender, payload, new byte[0][0], timestamp);
    }

    public InternalMessage(String msg_type, String sender, String[] payload)    {
        this(msg_type, sender, payload, new byte[0][0], base.getUTC());
    }

    private static byte[] sanitize_string(byte[] fed_string, boolean sizeless) throws Exception    {
        if (!sizeless)  {
            if (base.unpack_value(fed_string, 4) != fed_string.length - 4)   {
                throw new Exception("Size header inaccurate " + Arrays.toString(Arrays.copyOfRange(fed_string, 0, 4)) + ", " + String.valueOf(fed_string.length - 4));
            }
            return Arrays.copyOfRange(fed_string, 4, fed_string.length);
        }
        return fed_string;
    }

    private static byte[] decompress_string(byte[] fed_string, byte[][] compressions)   {
        return fed_string;  //Eventually this will do decompression
    }

    private static String[] process_string(byte[] fed_string)   {
        int processed = 0;
        int expected = fed_string.length;
        ArrayList<String> packets = new ArrayList<String>();

        while (processed < expected)   {
            System.out.println(packets.size());
            byte[] pack_len = Arrays.copyOfRange(fed_string, processed, processed + 4);
            int new_len = (int) base.unpack_value(pack_len, 4);
            processed += 4;
            packets.add(new String(Arrays.copyOfRange(fed_string, processed, processed + new_len)));
            processed += new_len;
        }

        return packets.toArray(new String[packets.size()]);
    }

    public static InternalMessage feed_string(byte[] fed_string, boolean sizeless, byte[][] compressions) throws Exception     {
        byte[] sanitized_string = InternalMessage.sanitize_string(fed_string, sizeless);
        sanitized_string = InternalMessage.decompress_string(sanitized_string, compressions);
        String[] packets = InternalMessage.process_string(sanitized_string);

        String[] payload = new String[packets.length-4];
        for (int i = 0; i < payload.length; i++)    {
            payload[i] = packets[4 + i];
        }

        InternalMessage msg = new InternalMessage(packets[0], packets[1], payload);
        msg.time = base.from_base_58(packets[3]);

        if (!packets[2].equals(msg.id())) {
            throw new Exception("Checksum match failed");
        }

        return msg;
    }

    public static InternalMessage feed_string(byte[] fed_string, boolean sizeless) throws Exception     {
        return InternalMessage.feed_string(fed_string, sizeless, new byte[0][0]);
    }

    public static InternalMessage feed_string(byte[] fed_string, byte[][] compressions) throws Exception     {
        return InternalMessage.feed_string(fed_string, false, compressions);
    }

    public static InternalMessage feed_string(byte[] fed_string) throws Exception     {
        return InternalMessage.feed_string(fed_string, false, new byte[0][0]);
    }

    public String time_58() {
        return base.to_base_58(this.time);
    }

    public String id() throws java.security.NoSuchAlgorithmException    {
        StringBuilder builder = new StringBuilder();
        for(String s : this.payload) {
            builder.append(s);
        }
        String info = builder.toString() + this.time_58();
        MessageDigest md = MessageDigest.getInstance("SHA-384");
        byte[] digest = md.digest(info.getBytes());
        BigInteger i = new BigInteger(1, digest);
        return base.to_base_58(i);
    }

    public String[] getPackets() throws java.security.NoSuchAlgorithmException  {
        String[] packets = new String[4 + this.payload.length];
        packets[0] = this.msg_type;
        packets[1] = this.sender;
        packets[2] = this.id();
        packets[3] = this.time_58();
        for (int i = 0; i < this.payload.length; i++)   {
            packets[4 + i] = this.payload[i];
        }
        return packets;
    }

    public byte[] non_len_string() throws java.security.NoSuchAlgorithmException {
        String id = this.id();
        String[] packets = this.getPackets();
        byte[][] encoded_packets = new byte[packets.length][];
        byte[] encoded_lengths = new byte[4 * packets.length];
        int total_length = 4 * packets.length;

        for (int i = 0; i < packets.length; i++)    {
            encoded_packets[i] = packets[i].getBytes();
            total_length += encoded_packets[i].length;
        }

        byte[] ret = new byte[total_length];
        int index = 0;

        for (int i = 0; i < encoded_packets.length; i++)    {
            byte[] len = base.pack_value(encoded_packets[i].length, 4);
            ret[index++] = len[0];
            ret[index++] = len[1];
            ret[index++] = len[2];
            ret[index++] = len[3];
            for (int j = 0; j < encoded_packets[i].length; j++) {
                ret[index++] = encoded_packets[i][j];
            }
        }

        return ret;
    }

    public byte[] serialize() throws java.security.NoSuchAlgorithmException {
        byte[] non_len_string = this.non_len_string();

        // This is where compression should happen in the future

        byte[] ret = new byte[4 + non_len_string.length];
        byte[] len = base.pack_value(non_len_string.length, 4);

        ret[0] = len[0];
        ret[1] = len[1];
        ret[2] = len[2];
        ret[3] = len[3];

        for (int i = 0; i < non_len_string.length; i++) {
            ret[4 + i] = non_len_string[i];
        }

        return ret;
    }
}