/**
   * Returns the result of applying XOR on the specified attribute's address. The method may be used
   * for both encoding and decoding XorMappedAddresses.
   *
   * @param address the address on which XOR should be applied
   * @param transactionID the transaction id to use for the XOR
   * @return the XOR-ed address.
   */
  public static TransportAddress applyXor(TransportAddress address, byte[] transactionID) {
    byte[] addressBytes = address.getAddressBytes();
    char port = (char) address.getPort();

    char portModifier =
        (char) ((transactionID[0] << 8 & 0x0000FF00) | (transactionID[1] & 0x000000FF));

    port ^= portModifier;

    for (int i = 0; i < addressBytes.length; i++) addressBytes[i] ^= transactionID[i];

    TransportAddress xoredAdd;
    try {
      xoredAdd = new TransportAddress(addressBytes, port, Transport.UDP);
    } catch (UnknownHostException e) {
      // shouldn't happen so just throw an illegal arg
      throw new IllegalArgumentException(e);
    }

    return xoredAdd;
  }