Addenda

The Message.java file for project 5 may not work for project 6
because the Message() constructors are not public. You should edit
your Message.java files to make all of the constructors
(Message(String) and Message(String, int)) public.

Like Measure.java, your Main.java should take a well-known
portal address as its first argument.

You should submit working Measure.java and Main.java files. We
should be able to run java -Djava.security.policy=... Main
rmi://cafe.cs.umd.edu:6666/TestSix to run your code on the test
oracle. (We will also supply -Dport, -DfilePort, and
-Djava.rmi.server.codebase properties.) Similarly, we should be able
to java -D... Measure ... in order to measure the network.

A Distributed Peer-to-Peer Network: Part 2

In project 5 you built a program that
let you broadcast messages on a distributed peer-to-peer network. In
this project you will refine your implementation, improving its
robustness in the face of errors and making it more functional.

One of the main lessons to learn from this project is that code you
write continues to haunt you long after you thought you were done with
it.

There are several small parts to this project. Parts 1-4 are all
independent of one another, so you can implement those right away, in
any order.

0. Multicasting somebodyPeerWithMe

In project 5 we relied heavily on joining the network by contacting a
well-known Portal. For this project that option will also be
available, but we will also supply you with some code to use multicast
to find peers.

1. Dealing with Slow Portals

Your project 6 code should be able to handle slow peers. If you peer
with a portal that responds to messages very slowly, your portal
should still handle other messages while waiting for receive() to
return from the slow portal. Our suggestion is to use a separate
thread (or a command given to a PooledExecutor) to send each message.

2. Making Connection Failures Symmetric

Suppose that Portals A and B are peered, and furthermore suppose that
Portal A tries to send a message to B just when someone in the machine
room trips over a network cord and disconnects B from the network.
Then Portal A will catch the RemoteException from receive() and remove
B from its set of peers. But B has no way of knowing that A un-peered
with it. So if the network cord is reconnected, then B can continue
sending messages to A, even though A can't send messages to B.

There are several other similar situations that can happen. To solve
this problem, your project 6 code should make network failures
symmetric. The receive() method should raise an exception if invoked
on a peer that is no longer in the local portal's myPeers set.

3. Reverse Path Forwarding

We have supplied a new LocalPortal
interface with one additional method for doing reverse path
forwarding:

public void forwardBackToSource(Long id, Message msg);

The forwardBackToSource() method sends msg to the Peer who original sent
this portal message #id. For example, suppose our peer-to-peer
network looks like this:

Suppose that A broadcasts message #101 to the network. Then at D, if
we invoke forwardBackToSource(#101, msg), D will send msg to B. And at B,
if we invoke forwardBackToSource(#101, msg), B will send msg only
to A, and not to C or D.

If forwardBackToSource is called and id hasn't been seen on this
portal, forwardBackToSource can simply ignore the request.

4. Allow Downloaded Code

You must install a SecurityManager in Main.java so that you can run
downloaded code. You should only allow downloaded code to connect to
port 80 of any host, and you should not grant downloaded code any
other permissions.

Once you've installed a security manager, you'll need to grant
permissions to your local code as well. Here is a policy file that
grants all code the permissions you need to read the port
property and to connect to anything on the network:

Instead, if you want, you can just grant your own code
java.security.AllPermission, which allows your own code to do any
privileged action.

You will need to modify this policy file to restrict permissions for
downloaded code. Remember, you specify a policy file by running you
program with java -Djava.security.policy=java.policy. You should
use java.policy for the name of your policy file.

5. Find Routes on the Network

Finally, you should extend your Portal class to also implement the
NetworkMeasurement interface, which is
as follows:

The NetworkMeasurement interface contains a method measureNetwork(callback)
that finds all the paths on the network from the Portal to all other
Portals. For each path it finds, it calls foundPath(path). The paths
do not contain the Portal itself.

For example, if measureNetwork(c) is invoked on Portal A in the
network from part 3, then A should call (in any order) c({B}), c({B,
D}), and c({B, C}).

You should implement measureNetwork() by writing two new subclasses of
Message whose code you will make available on the network (thus using
part 4). Let P be the portal on which measureNetwork() is called.
The first message should, like BroadcastTextMessage, forward itself to
all portals on the network. Whenever the message reaches a Portal, it
should make a new message (of the second message kind) and send that
back to P using forwardBackToSender() (thus using part 3). On the way
back, the second message should call getAddress() and keep a list of
the portals on the path back to P. When it reaches P it should stop,
and then the callback supplied to measureNetwork should be invoked
with the path.

Important: You must incorporate your class account name
into your new message class names in some way, so that your local
message classes don't collide with downloaded message class names.
You can either put your account name directly in the class name, or
you can make a package using your accout name.

To make your Message class code available for downloading, you'll need
to run a web server. Use the simple web server here.
To use this web server, in your own Main.java file you can make a new
ClassFileServer(port, classpath). Use . as the classpath, and get the
port via the "fileport" property (using
Integer.getInteger("fileport",8xxx), where xxx is the last three
digits of your class account).

Even More Important: Once a remote client has downloaded the
code for your message classes, it will not download the code
from the same code base again, even if you change it. Thus we
recommend that whenever you make a change to your message classes,
change the portal your web file server listens on.