| // Copyright 2015 The Vanadium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package io.v.impl.google.lib.discovery; |
| |
| |
| import com.google.common.primitives.Bytes; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.IOException; |
| import java.nio.charset.Charset; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import io.v.v23.vom.BinaryUtil; |
| import io.v.x.ref.lib.discovery.EncryptionKey; |
| |
| /** |
| * A utility to encode and decode fields in io.v.v23.Service fields for use in discovery. |
| */ |
| public class EncodingUtil { |
| static final Charset UTF8_CHARSET = Charset.forName("UTF-8"); |
| |
| /** |
| * Encodes the addresses passed in. |
| * @param addrs The list of addresses to encode. |
| * @return The byte representation of the encoded addresses. |
| * @throws IOException |
| */ |
| public static byte[] packAddresses(List<String> addrs) throws IOException { |
| ByteArrayOutputStream stream = new ByteArrayOutputStream(); |
| for (String addr : addrs) { |
| BinaryUtil.encodeUint(stream, addr.length()); |
| stream.write(addr.getBytes(UTF8_CHARSET)); |
| } |
| return stream.toByteArray(); |
| } |
| |
| /** |
| * Decodes addresses from a byte array that was encoded by packAddresses |
| * @param input The byte array toe decode |
| * @return The list of addresses. |
| * @throws IOException |
| */ |
| public static List<String> unpackAddresses(byte[] input) throws IOException { |
| ByteArrayInputStream stream = new ByteArrayInputStream(input); |
| List<String> output = new ArrayList<>(); |
| while (stream.available() > 0) { |
| int stringSize = (int)BinaryUtil.decodeUint(stream); |
| byte[] data = new byte[stringSize]; |
| int read = stream.read(data); |
| if (read != stringSize) { |
| throw new IOException("Unexpected end of stream while reading address"); |
| } |
| output.add(new String(data, UTF8_CHARSET)); |
| } |
| return output; |
| } |
| |
| /** |
| * Encode the encryption keys and algorithm passed in. |
| * @param encryptionAlgorithm The encryption algorithm to use. |
| * See io.v.x.ref.lib.discovery.Constants for valid values. |
| * @param keys The keys to encode |
| * @return The byte array that is the encoded form. |
| * @throws IOException |
| */ |
| public static byte[] packEncryptionKeys(int encryptionAlgorithm, List<EncryptionKey> keys) |
| throws IOException { |
| ByteArrayOutputStream stream = new ByteArrayOutputStream(); |
| BinaryUtil.encodeUint(stream, encryptionAlgorithm); |
| for (EncryptionKey key : keys) { |
| byte[] byteKey = Bytes.toArray(key); |
| BinaryUtil.encodeUint(stream, byteKey.length); |
| stream.write(byteKey); |
| } |
| return stream.toByteArray(); |
| } |
| |
| |
| /** |
| * Decodes the encryption algorithm and keys that was encoded by packEncryptionKeys. |
| * @param input The byte array containg the keys. |
| * @return The keys and the encryption algorithm in input. |
| * @throws IOException |
| */ |
| public static KeysAndAlgorithm unpackEncryptionKeys(byte[] input) throws IOException { |
| ByteArrayInputStream stream = new ByteArrayInputStream(input); |
| int algo = (int) BinaryUtil.decodeUint(stream); |
| List<EncryptionKey> keys = new ArrayList<>(); |
| while (stream.available() > 0) { |
| int size = (int) BinaryUtil.decodeUint(stream); |
| byte[] key = new byte[size]; |
| int read = stream.read(key); |
| if (read != size) { |
| throw new IOException("Unexpected end of file reading keys"); |
| } |
| keys.add(new EncryptionKey(Bytes.asList(key))); |
| } |
| return new KeysAndAlgorithm(algo, keys); |
| } |
| |
| /** |
| * An object with EncryptionKeys and the encryption algorithm. |
| */ |
| public static class KeysAndAlgorithm { |
| int encryptionAlgorithm; |
| List<EncryptionKey> keys; |
| |
| /** |
| * Gets the stored encryption algorithm. |
| */ |
| public int getEncryptionAlgorithm() { |
| return encryptionAlgorithm; |
| } |
| |
| /** |
| * Gets the stored keys. |
| */ |
| public List<EncryptionKey> getKeys() { |
| return keys; |
| } |
| |
| KeysAndAlgorithm(int encryptionAlgo, List<EncryptionKey> keys) { |
| encryptionAlgorithm = encryptionAlgo; |
| this.keys = keys; |
| } |
| } |
| |
| } |