summaryrefslogtreecommitdiff
path: root/src/org/noreply/fancydress/type3/routing/RoutingHOST.java
blob: 2203ac8b3b8dad271c5e6118cf4d61ab2d08c6d9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/* $Id$ */
package org.noreply.fancydress.type3.routing;

import org.noreply.fancydress.misc.Util;
import org.noreply.fancydress.crypto.*;

/**
 * The FWD/HOST and SWAP-FWD/HOST routing as specified in the type III spec.
 *
 * FWD/HOST packets are forwarded to another type III node given by
 * a hostname/port pair.  The delivering node (i.e. the node parsing
 * this routing type) is responsible for resolving the hostname to an
 * IP address.
 */
public class RoutingHOST extends RoutingForward {
	/**
	 * The hostname of the next hop
	 */
	private String hostname;
	/**
	 * Port at which the Type III server is listening
	 */
	private int port;
	/**
	 * Keyid of the Packet Key
	 */
	private byte[] keyid;

	/**
	 * Constructor that creates the routing as either FWD/HOST or SWAP-FWD/HOST
	 *
	 * @param hostname host name of the next hop
	 * @param port TCP port at which the next hop is listening
	 * @param keyid keyid of the packet key
	 * @param boolean if true, have a SWAP-FWD/HOST routing type, FWD/HOST otherwhise
	 */
	private RoutingHOST(String hostname, int port, byte[] keyid, boolean asSwap) {
		super (asSwap ? RoutingType.SWAP_FWD_HOST : RoutingType.FWD_HOST);

		if (keyid.length != CryptoPrimitives.HASH_LEN)
			throw new Error("keyid must be HASH_LEN bytes long.");

		this.hostname = hostname;
		this.port = port;
		this.keyid = keyid;
	}

	/**
	 * Create a FWD/HOST routing.
	 *
	 * @param hostname host name of the next hop
	 * @param port TCP port at which the next hop is listening
	 * @param keyid keyid of the packet key
	 */
	public RoutingHOST(String hostname, int port, byte[] keyid) {
		this(hostname, port, keyid, false);
	}

	/**
	 * Return a routing with the same information but with a SWAP_FWD_HOST routing type.
	 * 
	 * @return a SWAP_FWD_HOST routing.
	 */
	public RoutingForward asSwap() {
		RoutingHOST swap = new RoutingHOST(hostname, port, keyid, true);
		return swap;
	}

	/**
	 * Return the total length in octets of the routing information.
	 *
	 * @return total length in octets of the routing information
	 */
	public int getRoutingInformationLength() {
		return 2 + keyid.length + hostname.length();
	}

	/**
	 * Get the routing type of this instance.
	 *
	 * @return routing type
	 */
	public byte[] getRoutingInformation() {
		int length = getRoutingInformationLength();
		byte[] result = new byte[length];
		int pos = 0;

		result[pos] = (byte) ( (port >> 8) & 0xff);
		pos++;
		result[pos] = (byte) (  port       & 0xff);
		pos++;
		System.arraycopy(keyid, 0, result, pos, keyid.length);
		pos += keyid.length;
		System.arraycopy(Util.toOctets(hostname), 0, result, pos, hostname.length());
		pos += hostname.length();

		if (pos != length)
			throw new Error("Did not fill in expected amount of bytes!");

		return result;
	}
}