com.offbynull.voip.kademlia.internalmessages.Start.java Source code

Java tutorial

Introduction

Here is the source code for com.offbynull.voip.kademlia.internalmessages.Start.java

Source

/*
 * Copyright (c) 2015, Kasra Faghihi, All rights reserved.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3.0 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.
 */
package com.offbynull.voip.kademlia.internalmessages;

import com.offbynull.peernetic.core.shuttle.Address;
import com.offbynull.peernetic.core.actor.helpers.AddressTransformer;
import com.offbynull.peernetic.core.actor.helpers.IdGenerator;
import com.offbynull.voip.kademlia.model.Id;
import com.offbynull.voip.kademlia.model.RouteTreeBranchStrategy;
import com.offbynull.voip.kademlia.model.RouteTreeBucketStrategy;
import com.offbynull.voip.kademlia.model.SimpleRouteTreeStrategy;
import java.util.Arrays;
import java.util.function.Supplier;
import org.apache.commons.lang3.Validate;

/**
 * Starts a Kademlia actor (priming message).
 * <p>
 * This class is immutable.
 * @author Kasra Faghihi
 */
public final class Start {

    private final AddressTransformer addressTransformer;
    private final Id baseId;
    private final String bootstrapLink;
    private final byte[] seed1;
    private final byte[] seed2;
    private final Address timerAddress;
    private final Address graphAddress;
    private final Address logAddress;
    private final KademliaParameters kademliaParameters;

    /**
     * Constructs a {@link Start} object.
     * @param addressTransformer address transformer to use for converting node links to addresses (and vice-versa)
     * @param baseId ID to use for the node being started
     * @param bootstrapLink link to connect to the network (if {@code null} if means this node is the first node in the network)
     * @param kademliaParameters Kademlia parameters
     * @param seed1 random number generator seed value 1
     * @param seed2 random number generator seed value 2
     * @param timerAddress address of timer
     * @param graphAddress address of visualizer graph
     * @param logAddress address of logger
     * @throws NullPointerException if any argument other than {@code bootstrapLink} is {@code null}
     * @throws IllegalArgumentException if {@code seed1} or {@code seed2} is less than {@link IdGenerator#MIN_SEED_SIZE}
     */
    public Start(AddressTransformer addressTransformer, Id baseId, String bootstrapLink,
            KademliaParameters kademliaParameters, byte[] seed1, byte[] seed2, Address timerAddress,
            Address graphAddress, Address logAddress) {
        Validate.notNull(addressTransformer);
        Validate.notNull(baseId);
        // bootstrapNode can be null
        Validate.notNull(kademliaParameters);
        Validate.notNull(seed1);
        Validate.notNull(seed2);
        Validate.notNull(timerAddress);
        Validate.notNull(graphAddress);
        Validate.isTrue(seed1.length >= IdGenerator.MIN_SEED_SIZE);
        Validate.isTrue(seed2.length >= IdGenerator.MIN_SEED_SIZE);
        this.addressTransformer = addressTransformer;
        this.baseId = baseId;
        this.bootstrapLink = bootstrapLink;
        this.kademliaParameters = kademliaParameters;
        this.seed1 = Arrays.copyOf(seed1, seed1.length);
        this.seed2 = Arrays.copyOf(seed2, seed2.length);
        this.timerAddress = timerAddress;
        this.graphAddress = graphAddress;
        this.logAddress = logAddress;
    }

    /**
     * Get address transformer used for converting node links to addresses (and vice-versa).
     * @return address transformer
     */
    public AddressTransformer getAddressTransformer() {
        return addressTransformer;
    }

    /**
     * Get the ID to use for the node being started.
     * @return node ID
     */
    public Id getBaseId() {
        return baseId;
    }

    /**
     * Get the link to connect to the network.
     * @return link to connect to the network (if {@code null} if means this node is the first node in the network)
     */
    public String getBootstrapLink() {
        return bootstrapLink;
    }

    /**
     * Get the Kademlia parameters.
     * @return kademlia parameters
     */
    public KademliaParameters getKademliaParameters() {
        return kademliaParameters;
    }

    /**
     * Get the first random number generator seed value.
     * @return first seed value for RNG
     */
    public byte[] getSeed1() {
        return Arrays.copyOf(seed1, seed1.length);
    }

    /**
     * Get the second random number generator seed value.
     * @return second seed value for RNG
     */
    public byte[] getSeed2() {
        return Arrays.copyOf(seed2, seed2.length);
    }

    /**
     * Get the timer address.
     * @return timer address
     */
    public Address getTimerAddress() {
        return timerAddress;
    }

    /**
     * Get the visualizer graph address.
     * @return visualizer graph address
     */
    public Address getGraphAddress() {
        return graphAddress;
    }

    /**
     * Get the logger address.
     * @return logger address
     */
    public Address getLogAddress() {
        return logAddress;
    }

    /**
     * Kademlia parameters.
     */
    public static final class KademliaParameters {
        private final Supplier<RouteTreeBranchStrategy> branchStrategySupplier;
        private final Supplier<RouteTreeBucketStrategy> bucketStrategySupplier;
        private final int maxConcurrentRequestsPerFind;

        /**
         * Constructs a {@link KademliaParameters} object.
         * @param baseId ID of the Kademlia node this parameter is for
         * @param branchesPerLevel number of branches in the routing tree at each depth (must be power of 2 and greater than 1)
         * @param nodesPerBucket maximum number of nodes allowed in each k-bucket
         * @param cacheNodesPerBucket maximum number of nodes allowed in each k-bucket's cache
         * @param maxConcurrentRequestsPerFind maximum number of requests to run concurrently for each search
         * @throws NullPointerException if any argument is {@code null}
         * @throws IllegalArgumentException if any numeric argument is {@code < 0}, or if {@code maxConcurrentRequestsPerFind <= 0}, or if
         * {@code branchesPerLevel <= 1 || !isPowerOfTwo(branchesPerLevel)}
         */
        public KademliaParameters(Id baseId, int branchesPerLevel, int nodesPerBucket, int cacheNodesPerBucket,
                int maxConcurrentRequestsPerFind) {
            this(() -> new SimpleRouteTreeStrategy(baseId, branchesPerLevel, nodesPerBucket, cacheNodesPerBucket),
                    () -> new SimpleRouteTreeStrategy(baseId, branchesPerLevel, nodesPerBucket,
                            cacheNodesPerBucket),
                    maxConcurrentRequestsPerFind);
        }

        /**
         * Constructs a {@link KademliaParameters} object.
         * @param branchStrategySupplier branching strategy to use when building routing tree (make sure the {@link Supplier} passed
         * in here generates a new {@link RouteTreeBranchStrategy} every time {@link Supplier#get() } is invoked)
         * @param bucketStrategySupplier bucket creation strategy to use when building k-bucket within routing tree (make sure the
         * {@link Supplier} passed in here generates a new {@link RouteTreeBucketStrategy} every time {@link Supplier#get() }
         * is invoked)
         * @param maxConcurrentRequestsPerFind maximum number of requests to run concurrently for each search
         * @throws NullPointerException if any argument is {@code null}
         * @throws IllegalArgumentException if {@code maxConcurrentRequestsPerFind <= 0}
         */
        public KademliaParameters(Supplier<RouteTreeBranchStrategy> branchStrategySupplier,
                Supplier<RouteTreeBucketStrategy> bucketStrategySupplier, int maxConcurrentRequestsPerFind) {
            Validate.notNull(branchStrategySupplier);
            Validate.notNull(bucketStrategySupplier);
            Validate.notNull(maxConcurrentRequestsPerFind > 0);
            this.branchStrategySupplier = branchStrategySupplier;
            this.bucketStrategySupplier = bucketStrategySupplier;
            this.maxConcurrentRequestsPerFind = maxConcurrentRequestsPerFind;
        }

        /**
         * Get the supplier that generates a new branching strategy.
         * @return supplier that generates a new branching strategy
         */
        public Supplier<RouteTreeBranchStrategy> getBranchStrategy() {
            return branchStrategySupplier;
        }

        /**
         * Get the supplier that generates a new bucket strategy.
         * @return supplier that generates a new bucket strategy
         */
        public Supplier<RouteTreeBucketStrategy> getBucketStrategy() {
            return bucketStrategySupplier;
        }

        /**
         * Get the maximum number of requests to run concurrently for each search.
         * @return max number of requests allowed at one time for each search
         */
        public int getMaxConcurrentRequestsPerFind() {
            return maxConcurrentRequestsPerFind;
        }

    }
}