summaryrefslogtreecommitdiff
path: root/src/org/noreply/fancydress/directory/Directory.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/org/noreply/fancydress/directory/Directory.java')
-rw-r--r--src/org/noreply/fancydress/directory/Directory.java230
1 files changed, 199 insertions, 31 deletions
diff --git a/src/org/noreply/fancydress/directory/Directory.java b/src/org/noreply/fancydress/directory/Directory.java
index f2eda8c..ff0cfdf 100644
--- a/src/org/noreply/fancydress/directory/Directory.java
+++ b/src/org/noreply/fancydress/directory/Directory.java
@@ -25,6 +25,12 @@ import java.util.*;
*/
public class Directory {
/**
+ * directory version we understand.
+ */
+
+ private static final String DIRECTORY_VERSION = "0.2";
+
+ /**
* Hash holding all Servers.
*
* This hash holds all Servers. Since nickname are to be treaded case
@@ -37,35 +43,27 @@ public class Directory {
private Hashtable byName;
/**
- * Possibly add a new server descriptor to the directory.
+ * Useable servers.
*
- * This method adds a server desccriptor to the directory if it
- * - conforms to the syntax specified.
- * - the server is not yet known or it's identity key matches the key of the already known ServerDescriptor.
+ * A server is useable if it understands PacketVersions that we understand
+ * and has a serverdescriptor that is useable right now.
+ */
+ private Server[] useableServers;
+
+ /**
+ * Recommended servers.
+ */
+ private Server[] recommendedServers;
+
+ /*
+ * matrix of friends.
*
- * @param server a DirectoryMessage consisting of one of more sections. At 'Server' section needs to be present.
- * @throws Mix3BadServerFormatException if a section is syntactially invalid and the error cannot be ignored.
- * @throws Mix3BadServerSignatureException if the server descriptor's signature is invalid.
+ * (a, b) are friends, if a can send messages to b.
*/
- private void addServerDescriptor(DirectoryMessage server) throws Mix3BadServerFormatException, Mix3BadServerSignatureException {
- try {
- ServerDescriptor sd = new ServerDescriptor(server);
- String key = sd.getNickname().toLowerCase();
- if (byName.containsKey(key)) {
- Server s = (Server) byName.get(key);
- try {
- s.addDescriptor(sd);
- } catch (Mix3BadServerFormatException e) {
- System.err.println("Ignoring Descriptor with different identity for "+key);
- }
- } else {
- Server s = new Server(sd);
- byName.put(key, s);
- }
- } catch (Mix3BadServerUnrecognizedVersionException e) {
- System.err.println("Ignoring unregonized version");
- }
- }
+ /*
+ private boolean[][] friends;
+ */
+
/**
* Create a directory from an entire DirectoryMessage.
@@ -82,11 +80,87 @@ public class Directory {
*/
public Directory(DirectoryMessage m, boolean checkDirectorySignature) throws
Mix3BadDirectorySignatureException,
+ Mix3BadDirectoryFormatException,
Mix3BadServerFormatException,
Mix3BadServerSignatureException
{
byName = new Hashtable();
+
+ parseDirectory(m, checkDirectorySignature);
+
+
+ Collection all = byName.values();
+ ArrayList useable = new ArrayList();
+ for (Iterator i = all.iterator(); i.hasNext(); ) {
+ Server s = (Server) i.next();
+ if (s.isUseable())
+ useable.add(s);
+ }
+ useableServers = (Server[]) useable.toArray( new Server[useable.size()] );
+
+
+ ArrayList recommended = new ArrayList();
+ for (int i=0; i<useableServers.length; i++)
+ if (useableServers[i].isRecommended())
+ recommended.add(useableServers[i]);
+ recommendedServers = (Server[]) recommended.toArray( new Server[recommended.size()] );
+ }
+
+
+
+ /**
+ * Possibly add a new server descriptor to the directory.
+ *
+ * This method adds a server desccriptor to the directory if it
+ * - conforms to the syntax specified.
+ * - the server is not yet known or it's identity key matches the key of the already known ServerDescriptor.
+ *
+ * @param server a DirectoryMessage consisting of one of more sections. At 'Server' section needs to be present.
+ * @throws Mix3BadServerFormatException if a section is syntactially invalid and the error cannot be ignored.
+ * @throws Mix3BadServerSignatureException if the server descriptor's signature is invalid.
+ */
+ private void addServerDescriptor(DirectoryMessage server) throws Mix3BadServerFormatException, Mix3BadServerSignatureException {
+ ServerDescriptor sd;
+ try {
+ sd = new ServerDescriptor(server);
+ } catch (Mix3BadServerUnrecognizedVersionException e) {
+ System.err.println("Ignoring unregonized version");
+ return;
+ }
+ String key = sd.getNickname().toLowerCase();
+ if (byName.containsKey(key)) {
+ Server s = (Server) byName.get(key);
+ try {
+ s.addDescriptor(sd);
+ } catch (Mix3BadServerFormatException e) {
+ System.err.println("Ignoring Descriptor with different identity for "+key);
+ }
+ } else {
+ Server s = new Server(sd);
+ byName.put(key, s);
+ }
+ }
+
+
+ private void parseDirectory(DirectoryMessage m, boolean checkDirectorySignature) throws
+ Mix3BadDirectorySignatureException,
+ Mix3BadDirectoryFormatException,
+ Mix3BadServerFormatException,
+ Mix3BadServerSignatureException
+ {
+ DirectorySection directorySection = m.getSection("Directory");
+ if (directorySection == null)
+ throw new Mix3BadDirectoryFormatException("No Directory section found.");
+
+ DirectoryEntry versionEntry = directorySection.getEntry("Version");
+ if (versionEntry == null)
+ throw new Mix3BadDirectoryFormatException("No Version in Directory section found.");
+ if (! versionEntry.getValue().equals(DIRECTORY_VERSION))
+ throw new Mix3BadDirectoryFormatException("Directory Version "+versionEntry+" not recognized.");
+
+ /* FIXME: check validity (date range) */
+
if (checkDirectorySignature)
checkSignature(m);
DirectoryMessage server = null;
@@ -102,27 +176,38 @@ public class Directory {
}
if (server != null)
addServerDescriptor(server);
+
+ DirectoryEntry recommendedServersEntry = directorySection.getEntry("Recommended-Servers");
+ if (recommendedServersEntry == null)
+ throw new Mix3BadDirectorySignatureException("No Recommended-Servers in Directory section found.");
+ String[] recommendedServers = Util.tokenize( recommendedServersEntry.getValue(), ',');
+ for (int i=0; i<recommendedServers.length; i++) {
+ Server s = getServer(recommendedServers[i]);
+ if (s == null)
+ throw new Mix3BadDirectoryFormatException("Unkown nickname '"+recommendedServers[i]+"'in Recommended-Servers");
+ s.setRecommended();
+ }
}
/* FIXME: known directory servers should be passed as arguments */
/**
* Check the signature of a type III directory.
*/
- private void checkSignature(DirectoryMessage m) throws Mix3BadDirectorySignatureException {
+ private void checkSignature(DirectoryMessage m) throws Mix3BadDirectorySignatureException, Mix3BadDirectoryFormatException {
/* FIXME: handle more than one signature block,
*/
DirectorySection signatureSection = m.getSection("Signature");
if (signatureSection == null)
- throw new Mix3BadDirectorySignatureException("No Signature section found.");
+ throw new Mix3BadDirectoryFormatException("No Signature section found.");
DirectoryEntry signatureEntry = signatureSection.getEntry("DirectorySignature");
if (signatureEntry == null)
- throw new Mix3BadDirectorySignatureException("No DirectorySignature in Signature section found.");
+ throw new Mix3BadDirectoryFormatException("No DirectorySignature in Signature section found.");
DirectoryEntry identityEntry = signatureSection.getEntry("DirectoryIdentity");
if (identityEntry == null)
- throw new Mix3BadDirectorySignatureException("No DirectoryIdentity in Signature section found.");
+ throw new Mix3BadDirectoryFormatException("No DirectoryIdentity in Signature section found.");
byte[] signature = Base64.decode(signatureEntry.getValue());
byte[] identity = Base64.decode(identityEntry.getValue());
@@ -131,7 +216,6 @@ public class Directory {
cleanedDirectory.blindValue("Signature","DirectoryDigest");
cleanedDirectory.blindValue("Signature","DirectorySignature");
- /* FIXME: what if identity is no valid key? */
RSAPublicKey identityKey = new RSAPublicKey(identity);
boolean verifies;
try {
@@ -145,6 +229,9 @@ public class Directory {
/**
* Get a server by nickname.
+ *
+ * @param name nickname of the requested server
+ * @return server specified by the nickname or null if no such server exists
*/
public Server getServer(String name) {
String key = name.toLowerCase();
@@ -152,4 +239,85 @@ public class Directory {
return (Server) byName.get(key);
return null;
}
+
+ /*
+ * Get current server descriptor of useable servers.
+ *
+ * A server is useable if it understands PacketVersions that we understand
+ * and has a serverdescriptor that is useable right now.
+ *
+ * @return server descriptor of useable servers
+ */
+ /*
+ private Server[] getUseableServers() {
+ return useableServers;
+ }
+ */
+
+ /**
+ * Get server descriptor of all recommended servers that are useable.
+ *
+ * @return server descriptor recommended servers
+ * @see #getUseableServers
+ */
+ public Server[] getRecommendedServers() {
+ return recommendedServers;
+ }
+
+ /**
+ * Check if server a can talk to server b.
+ *
+ * A server can talk to another one if they have MMTP/Outgoing and
+ * MMTP/Incoming sections respectively and speak a common MMTP version.
+ *
+ * FIXME: check Allow/Deny ACLs
+ *
+ * @param a server a
+ * @param b server b
+ * @return whether a can send messages to b
+ */
+ public boolean areFriends(Server a, Server b) {
+ ServerDescriptor aa,bb;
+
+ try {
+ aa = a.getDescriptor();
+ } catch (Mix3NoServerDescriptorException e) {
+ throw new Error(a.getNickname()+" should have a valid ServerDescriptor.", e);
+ }
+ try {
+ bb = b.getDescriptor();
+ } catch (Mix3NoServerDescriptorException e) {
+ throw new Error(b.getNickname()+" should have a valid ServerDescriptor.", e);
+ }
+
+ OutgoingMMTPSection out = aa.getOutgoingMMTPSection();
+ IncomingMMTPSection in = bb.getIncomingMMTPSection();
+
+ if (out == null || in == null)
+ return false;
+ String[] inP = in.getProtocols();
+ String[] outP = out.getProtocols();
+ for (int i=0; i<inP.length; i++)
+ for (int o=0; o<outP.length; o++)
+ if (inP[i].equals(outP[o]))
+ return true;
+ return false;
+ }
+
+ /*
+ * Build a matrix of friends.
+ *
+ * (a, b) are friends, if a can send messages to b.
+ */
+ /*
+ private void buildFriendsMatrix() {
+ friends = new boolean[useableServers.length][useableServers.length];
+ for (int i=0; i<useableServers.length; i++)
+ for (int j=0; j<useableServers.length; j++)
+ if (i==j)
+ friends[i][j] = true;
+ else
+ friends[i][j] = areFriends(useableServers[i], useableServers[j]);
+ }
+ */
}