summaryrefslogtreecommitdiff
path: root/src/org/noreply/fancydress/directory/Server.java
blob: 45ca720913b21873102cba6f56db6928cac21d78 (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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/* $Id$ */
package org.noreply.fancydress.directory;

import org.noreply.fancydress.misc.Util;
import org.noreply.fancydress.status.*;
import org.noreply.fancydress.crypto.*;
import java.util.*;

/**
 * This class represents a server, pooling one or more server descriptors into one class.
 *
 * @see ServerDescriptor
 */
public class Server {
	/**
	 * Nickname of the server.
	 *
	 * Note that all nickname comparisons need to be done in a case insensitive way.
	 */
	String nickname;

	/**
	 * The asn1 representation of the server's identity key.
	 */
	byte[] identity;

	/**
	 * The hash of <code>identity</code>, which is the node's keyid
	 */
	byte[] keyid;

	/**
	 * A list of one of more server descriptors.
	 */
	ArrayList descriptors;

	/**
	 * whether or not this node is recommended.
	 */
	boolean recommended;

	/**
	 * Construct a Server from a given ServerDescriptor.
	 *
	 * @param descriptor a ServerDescriptor.
	 */
	public Server(ServerDescriptor descriptor) {
		nickname = descriptor.getNickname();
		identity = descriptor.getIdentity();
		keyid = CryptoPrimitives.hash(identity);

		descriptors = new ArrayList();
		descriptors.add(descriptor);
		recommended = false;
	}

	/**
	 * Set this node recommended.
	 *
	 * This is done by the Directory according to the recommended-servers list.
	 *
	 * @see Directory
	 */
	public void setRecommended() {
		recommended = true;
	}

	/**
	 * Get whether or not this node recommended.
	 *
	 * @return whether or not this node is recommended
	 */
	public boolean isRecommended() {
		return recommended;
	}

	/**
	 * Get whether or not this node is useable.
	 *
	 * A server is useable if it understands PacketVersions that we speak,
	 * has a serverdescriptor that is useable right now, and this SD has
	 * an Incoming/MMTP section.
	 *
	 * @return whether or not this node is useable
	 */
	public boolean isUseable() {
		ServerDescriptor sd;
		try {
			 sd = getDescriptor();
		} catch (Mix3NoServerDescriptorException e) {
			return false;
		}
		String[] pv = sd.getPacketVersions(); /* getPacketVersions only returns packet versions that we understand */
		if (pv.length == 0)
			return false;
		if (sd.getIncomingMMTPSection() == null)
			return false;
		return true;
	}

	/**
	 * Add a ServerDescriptor to this Server.
	 *
	 * @param descriptor a ServerDescriptor to add.
	 * @throws Mix3BadServerFormatException if the nickname or the identity key do not match this server's nickname or identity key.
	 */
	public void addDescriptor(ServerDescriptor descriptor) throws Mix3BadServerFormatException {

		if (!nickname.equalsIgnoreCase(descriptor.getNickname()))
			/* This indicates an error in whoever called us */
			throw new Error("Nickname does not match.");

		if (!Util.equal(identity, descriptor.getIdentity()))
			/* While this might happen.  In this case this ServerDesc should be ignored */
			throw new Mix3BadServerFormatException("Identity does not match.");

		descriptors.add(descriptor);
	}

	/**
	 * Get the keyid (hash of the identity key) of this Server.
	 *
	 * @return keyid
	 */
	public byte[] getKeyID() {
		return keyid;
	}

	/**
	 * Get the nickname of this server.
	 *
	 * @return nickname
	 */
	public String getNickname() {
		return nickname;
	}

	/**
	 * get the the currently valid server descriptor.
	 *
	 * @return current server descriptor
	 * @throws Mix3NoServerDescriptorException if there is no valid server descriptor
	 */
	public ServerDescriptor getDescriptor() throws Mix3NoServerDescriptorException {
		ServerDescriptor result = null;
		Date now = new Date();

		for (int i=0; i<descriptors.size(); i++) {
			ServerDescriptor desc = (ServerDescriptor) descriptors.get(i);
			if (now.after( desc.getValidAfter() ) &&
			    now.before( desc.getValidUntil() ) &&
			    ((result == null) || desc.getPublished().after( result.getPublished())))
				result = desc;
		}
		if (result == null)
			throw new Mix3NoServerDescriptorException("No valid server descriptor found.");
		return result;
	}
}