% Design chapter

\svnInfo $Id$

\chapter{Design}
\label{ch:design}

Keeping our goal in mind, we focus on the essential parts needed for Origo (see
the requirements in section~\ref{sec:design_requirements}) because we cannot
port \emph{all} JXTA protocols to Eiffel within the given six months of this
thesis. See chapter~\ref{ch:futurework} for future work and how \vampeer{} may
be extended to add missing features.

\section{Requirements}
\label{sec:design_requirements}

As we are implementing JXTA for Eiffel with regard to support Origo's network
layer, we state the following demands:

\begin{enumerate}

\item The Origo peers may communicate among each other without being disturbed
by messages from other peer applications.

\item An Origo peer is on the one hand able to advertise its existence to the
peer group and on the other hand to discover other peers, especially a ``core''
peer.

\item An Origo peer is able to send messages to other peers. A message may
contain data of any type and length.

\end{enumerate}

Mapping these ideas to the JXTA world, we specify the following requirements:

To fulfill the first demand, we should be able to support private peer groups.
This means also that we need to be able to run an own JXTA infrastructure
without using foreign resources on the net. This is exactly what JXTA teaches us
to do for peer applications.

To enable peer discovery in JXTA (second demand), we need a set of services:
Obviously, we need at least the \emph{discovery service} which allows us to
publish and query for (peer) advertisements. Then, we need the \emph{resolver
service} which the discovery depends on\footnote{See
subsection~\ref{sec:jxta_services} for a short introduction to the mentioned
services.}.

But to get into contact with unknown peers, we heavily rely on the
\emph{rendezvous service}. The rendezvous server is the first peer we contact
and the advantages of the discovery service only is possible with the
rendezvous' help.

Whereas a rendezvous server is needed for the entire peer group, not every peer
needs to implement the server part. An Origo peer may be a rendezvous client
only. Therefore, we concentrate on the client part and note the possibility to
run the rendezvous server as a JXTA JSE peer.

As all discovery messages (and also messages from the resolver and rendezvous)
are based on normal JXTA messages, we clearly need the \emph{endpoint service}
together with a transport module. Having these, we honor also the third demand
requesting a message transport.

There is still a missing service: the \emph{endpoint router}. Peers are
addressed with peer IDs (see subsection~\ref{sec:jxta_ids}) so we need the
endpoint router to resolve the IDs to addresses that specify the transport
protocol and the exact address. This is only a small task of the router. There
is no urgent need for the other functionality enabling us to have peers behind
firewalls and NAT gateways.

Summing up the set of required services, we get the list shown in
table~\ref{tab:design_requirements}. The requirements are fairly vague but we
will enlighten the details later in this section and show the resulting
challenge when presenting the implementation in chapter~\ref{ch:implementation}.

\begin{table}[h] \centering
\begin{tabular}{|p{.4\textwidth}|p{0.54\textwidth}|}
\hline
\emph{Service module} & \emph{Functionality} \\
\hline
Endpoint service & Message layer abstraction \\
A transport module (e.g.\ TCP) & Message sending and receiving over the wire \\
Endpoint router (parts) & Routing messages to available gateways selecting a
fast transport \\
Rendezvous service (client) & Connection to peer group \\
Resolver service & Query-response system \\
Discovery service & Advertisement querying and publishing \\
\hline
\end{tabular}
\caption{Required services}
\label{tab:design_requirements}
\end{table}

We now move on to the \vampeer's design. By first introducing the module
structure, we see how the entire platform works.

\section{Module structure}
\label{sec:design_modules}

The JXTA structure is very modular; every service and every peer group,
even the platform (the world peer group) itself, is a module.

A module is an entity which can be started, suspended and stopped. This enables
the \vampeer{} platform to perform the entire start up process without knowing
every modules' internal details.

\begin{figure}[h] \centering
\includegraphics[width=0.8\textwidth]{module_lifecycle}
\caption{Module life cycle}
\label{fig:module_lifecycle}
\end{figure}

Figure~\ref{fig:module_lifecycle} shows a module's life cycle. After successful
loading where usually the basic initialization like creating data structures is
done, a module can be started. The \texttt{suspended} mode is available to
temporarily stop a service in order to make it rest for a while in standby. The
\texttt{start} method has to take care of the two possible calling states. To
permanently shutdown a module, one can call \texttt{stop} in suspended mode. A
stopped module should not and cannot be started again. If you really need to do
this, you have to create a new module instance.

There are also some states indicating fatal errors. When one of them has
occurred, a module should not be touched again. Only the constructive operations
\texttt{init} and \texttt{start} are allowed to produce errors. \texttt{suspend}
and \texttt{stop} are always expected to function properly.

A module is represented in \vampeer{} with the deferred class
\eclass{P2P\_MODULE}. Figure~\ref{fig:modules} gives an idea about the classes
which effect it\footnote{A deferred class in Eiffel is like an abstract class in
Java; to effect such a class means to implement deferred features (abstract
methods).}. Also, we already see how the peer groups are related with modules;
that is what we will look at in the next subsection.

\begin{figure}[h] \centering
\includegraphics[width=.8\textwidth]{modules}
\caption{Module class hierarchy}
\label{fig:modules}
\end{figure}


\subsection{Peer group modules}
\label{sec:design_peergroup_modules}

As a peer group specifies the available services for its group, it makes sense
to make a peer group responsible for managing its services. So we just have to
start the peer group when we would like to start the application's \ptp{}
support with all services. Therefore, the peer group is also a module which can
be started and stopped (\eclass{P2P\_PEERGROUP}).

Unfortunately, it is not that easy to start the entire \ptp{} platform. To load
a module we need a parent peer group, an ID and a module implementation
advertisement\footnote{See sections~\ref{sec:jxta_ids} and
\ref{sec:jxta_advertisements}.} used for configuration. Thus, we need a
bootstrapping process that handles the loading of our main peer group---usually
the net peer group.

This is exactly the purpose of our world peer group (\eclass{P2P\_PLATFORM}). In
\vampeer, it is not used for anything else but loading the NPG. As the WPG is
itself a peer group, it is also a module but with a different creation
procedure.  This allows us to retrieve the needed data like the configuration
directory path and the logger object.

It is not yet clear enough why we do not just adapt the net peer group to
manage the platform creation. At the moment, only one real peer group can be run
in \vampeer{} but this could more or less easily be changed. By then, generic
peer groups (represented through \eclass{P2P\_GENERIC\_PEERGROUP}) should not be
involved in the bootstrapping process. See section~\ref{sec:design_peergroup}
for more details about how peer groups are defined in \vampeer\@.

In JXTA JSE, the entire \ptp{} application is also a module controlled by the
JXTA's module loader. We do not go so far in \vampeer: The \ptp{} environment
should only be a part of the user's application and should not dominate
everything.

\section{Defining a peer group}
\label{sec:design_peergroup}

Defining a peer group implies to prepare several requirements:

As a peer group is in the first place a normal module, we first have to
establish the module configuration. This requires to have a module class ID
(MCID) and a module specification ID (MSID) which identify the local and remote
behavior as already pointed out in section~\ref{sec:jxta_services}.

Another part of the group definition is built by the group ID, a name and a
description. Together with the MSID, we are now able to build the peer group
advertisement.

Modules are loaded by the MSID. This means that the module loader gets a MSID
(besides an arbitrary ID and a name) in order to load the correct module code.
Hence when loading a peer group, we have to provide its MSID.

As peer groups define which services (modules) they provide, the peer group
module code is responsible to load these modules. The group module therefore
somehow contains a list of needed module MSIDs. In our standard group
implementation \eclass{P2P\_GENERIC\_PEERGROUP}, this list is called
\texttt{modules} and \texttt{define\_modules} is the method that initializes it.
As we use a parent-child relationship between groups, the group services are
usually inherited by a child group but one may easily redefine them.

When we inherit group services, we share the module instance. This clearly makes
sense for certain services which are not group context sensitive. The top group
which defines such a service is responsible for it (it is the only authorized
group to load, start and stop this module). To respect this rule, the group's
module list also has to keep track of whether a module is inherited or newly
defined.

When a module is loaded, the loader and later also the module itself should be
able to access the module implementation advertisement. The loader may need the
advertisement to know what module code to load for the given MSID. The module
itself may use the advertisement to lookup some configuration parameters. Thus,
the module implementation advertisement has to be available for each used
module.

Conventionally, the group module implementation advertisement contains all
advertisement of its modules. The peer group module will then extract these and
make them singly available.

There is one open issue with module loading: a running module has itself an ID.
We speak thereof of the \emph{assigned ID} because the module loader assigns an
arbitrary ID to the module. Usually, we assign the MCID but it is not necessary
to do so. The module uses its ID to create a unique handler name when
registering with other services.

Summarizing, we need for each module an implementation advertisement where the
one for the group contains all advertisements for its services. Additionally, we
should provide a peer group advertisement to declare the group module as a JXTA
peer group.

The entire module loading procedure is quite generic because of the dynamic
module loading. Although Eiffel does not provide this, we choose to stick to the
convention and provide also these implementation advertisements even if we only
may use it to parametrize modules.

Unhappily, we need code in Eiffel where we specify which classes have to be
loaded for a given MSID. To create a peer group with user services, we therefore
have to heir from \eclass{P2P\_GENERIC\_PEERGROUP}, adapt the modules list and
redefine \texttt{load\_extern\_module} to be able to specify the Eiffel class
which should be used. To load a private net peer group, the platform
\eclass{P2P\_PLATFORM} provides the possibility to specify a net group loader in
terms of an agent.

\section{Services}
\label{sec:design_services}

With the strict module structure, we are basically done with presenting the
\vampeer's design because everything is bundled into a module and therefore
every service looks quite similar. Nevertheless, we have to describe some
particularities, especially how services interact among each other.

\subsection{Module choice}

Each module resides in its own Eiffel cluster together with its related classes,
namely the XML document types. Module unspecific classes are located in the main
\texttt{vampeer} cluster. See figure~\ref{lst:design_clusters} for a clusters
overview.

\begin{lstlisting}[language=, caption={Clusters overview},
label=lst:design_clusters]
vampeer/           (38 classes)
|-- discovery/     ( 3 classes)
|-- endpoint/      ( 4 classes)
|-- pipe/          ( 2 classes)
|-- rendezvous/    ( 5 classes)
|-- resolver/      ( 5 classes)
`-- transports/    ( 7 classes)
    |-- router/    ( 4 classes)
    `-- tcp/       ( 5 classes)
\end{lstlisting}

The pipe service\footnote{The \emph{pipe service} implements the pipe binding
protocol and provides virtual communication channels among several peers.} is
not actually implemented but the module specification advertisement depends on
the pipe advertisement.

Until now, we have mostly spoken of generic transport modules but finally we
implement only one, the TCP transport.

TCP is actually a dumb name as most of the other transports indirectly are TCP
based too. But with the TCP transport, we directly lie on top of TCP using the
JXTA's wire representation for messages. It is the most simple but also the
fastest transport, which explains our choice.

\subsection{Service layers}

We would like to clarify how all the JXTA services are related to each other.
Particularly, how messages are passed through. We do so by looking at two
examples which cover all services implemented in \vampeer\@. We first treat an
outgoing and later an incoming message.

\paragraph{Outgoing message}

Lets look at a discovery query which is sent out to be propagated in the group.
It could be a general query to find new peers.
Figure~\ref{fig:discoveryquerysequence} shows the UML sequence diagram hiding
the exact operation signatures. We will comment each method call:

\begin{figure}[h] \centering
\includegraphics[width=\textwidth]{discoveryquerysequence}
\caption{Information flow for an outgoing discovery query}
\label{fig:discoveryquerysequence}
\end{figure}

\begin{itemize}

\item[1] When the discovery service is called with
\texttt{remote\_query\_advertisements}, it creates a
\eclass{P2P\_RESOLVER\_QUERY} containing the discovery query string and a
handler name (see the incoming message example for its use). It then passes it
to the resolver which is requested to propagate the query (instead of just
sending the message to a single peer).

\item[2] The resolver service then creates a \eclass{P2P\_ENDPOINT\_MESSAGE}
with a message element containing the resolver query string. It passes the
message together with the resolver's service name to the rendezvous service.

\item[3a] The rendezvous adds another message element with some meta data to the
message. This informs the recipients that the message was propagated (important
when they do repropagation). The rendezvous then first propagates the message in
the local network by simply calling the endpoint's propagation service.

\item[3a1] The endpoint service now passes the message and the service name to
each transport's propagation method. Actually, it makes only sense for the TCP
transport, as it supports IP multicast (other transports just ignore the call).
However, multicast is discouraged\footnote{Multicasting should not be used
because it causes much network traffic and may stress some smaller edge peers.
It poses also a risk for developers that test in local networks only because
things may work locally with multicast but maybe will not with remote peers.}
and mostly turned off in the platform configuration.

\item[3b] When the peer is connected to a rendezvous server, it is able to do
propagation via this server. So the rendezvous service sends the message to the
server's peer ID by calling the endpoint service's \texttt{send\_message}. For
this, it has to create a \eclass{P2P\_ENDPOINT\_ADDRESS} with the \texttt{jxta}
protocol and the server's peer ID\footnote{E.g.
\texttt{jxta://rdv-peer-id/rsv-service-name} (while rsv-service-name is the
resolver service module class ID).}.

\item[3b1] To resolve the endpoint address, the endpoint service passes the
message to the endpoint router which is the registered transport module for the
\texttt{jxta} protocol.

\item[3b2] The endpoint router does a (local) lookup for the given destination
peer ID (querying for peer and route advertisements). As soon as a gateway and a
transport protocol is chosen, it calls the endpoint service again to deliver the
message with a rewritten, specific destination address\footnote{E.g.
\texttt{tcp://129.132.105.170:9700/rsv-service-name}}.

\item[3b3] The endpoint service now passes the message to the specified
transport protocol which tries to connect to the specified peer and writes the
message to the wire. Note that there is neither a feedback to the caller whether
the message dispatching has been successful or not, nor an acknowledgment
message from the other peer. The TCP transport is therefore seen as an
unreliable transport.

\end{itemize}

\paragraph{Incoming message}

The path for incoming messages is somewhat shorter. We will continue our example
and let the peer receive a discovery response. To explain the three method
calls, we first look at figure~\ref{fig:discoveryresponsesequence} which
presents the calling sequence.

\begin{figure}[h] \centering
\includegraphics[width=\textwidth]{discoveryresponsesequence}
\caption{Information flow for an incoming discovery response}
\label{fig:discoveryresponsesequence}
\end{figure}

\begin{itemize}

\item[1] As soon as the message transport has received a message and the message
parsing from the wire has been successful, it calls the endpoint service's
\texttt{demux} method with a \eclass{P2P\_ENDPOINT\_MESSAGE} object.

\item[2] From the delivered message, the endpoint service extracts the
destination address and therefrom the service name. Then it calls the registered
agent for this server name which is owned in our case by the resolver service.

\item[3] The resolver interprets the resolver message element and is able to
extract the response string and a handler name. It then calls the registered
agent for this handler name and passes a \eclass{P2P\_RESOLVER\_RESPONSE}
object.

The discovery service will finally parse the resolver response string and create
a \eclass{P2P\_DISCOVERY\_RESPONSE}. From there, the delivered advertisements
(responses) are either published locally or they may be passed to a further
agent registered by a user service.

\end{itemize}

\section{Address rewriting}
\label{sec:design_mangling}

To stay compatible with other JXTA implementations, we have to pay attention to
a special and a little cumbersome topic: \emph{address rewriting} (address
mangling). The problem is that messages may not be directed to the correct
service in other implementations since they may have a slightly other peer group
hierarchy.

In a JXTA platform, only one module can actually handle network traffic (one
module per transport protocol). But generally, it is possible to run multiple
peer groups at a peer such that each group has its own endpoint service. Hence,
the question is where we register the transport module(s).

As the JXTA protocol does not specify this, each implementation can do as it
likes. While in JXTA JSE the WPG owns the transport modules, JXTA-C and
\vampeer{} settle them in the NPG. The reason for that is that in Java, the WPG
is a real peer group whereas JXTA-C does not have a WPG and we \vampeer{} guys
only use it for platform configuration purposes.

With multiple endpoint services and in order to receive messages, services have
also to be registered in the top peer group that owns the transport modules.
Such an indirect registration, which is automatically done behind the scenes, is
done with a \emph{mangled} address which includes the original peer group ID
where the service is registered in the first point.
Figure~\ref{fig:design_mangledaddress} shows how such a mangled address is
assembled.

\begin{figure}[h] \small \centering
$\underbrace{
	\underbrace{\mbox{\texttt{EndpointService:}}}_{\mbox{Mangling prefix}}
	\underbrace{\mbox{\texttt{jxta-NetGroup}}}_{\mbox{Service's group id}}
}_{\mbox{New service name}}
\mbox{\texttt{/}}
\underbrace{
	\underbrace{\mbox{\texttt{service\_name/service\_parameter}}}_{\mbox{Original service name/parameter}}
}_{\mbox{New service parameter}}$
\caption{A mangled service handler name}
\label{fig:design_mangledaddress}
\end{figure}

With such a mangling scheme, it is clear that also the message destination
address has to obey this rule. To send a NPG discovery message to a Java peer,
we have to mangle the address before because the discovery is in the NPG but
the Java's transports are in the WPG. Sending the same message to a
\vampeer{} peer, we would not have to mangle the address because its transport
modules are also in the NPG.

That is really bad, but it gets worse when we look at the reverse direction: A
Java peer will send discovery messages always mangled and we would discard the
message because we have no mangled address registered for it as our discovery
service already runs in the top group NPG.

To overcome these troubles, we always register our services also with the
mangled address in order to not loose any messages from Java peers. And to send
messages, we may always need to mangle the destination addresses but we do not
force it; hence, it is still possible to speak with other \vampeer{} peers
without group mangling.

\section{Rendezvous propagation}
\label{sec:design_propagation}

In \ptp{} networks, propagation is a central service because for many messages
we do not know which peer exactly may use the information. So, we just propagate
the message to everyone and hope that some peers may use or process it. As we
have already seen, propagation with group scope (instead of local network only)
is done by the rendezvous service.

When we hear about message propagation, we might be tempted to classify it as
flooding the network. While this may be a solution (actually, previous versions
of JXTA JSE did this), it is rather traffic consuming and extremely inefficient.

We already mentioned in section~\ref{sec:jxta_rendezvous} that the rendezvous
today just passes the messages to the appropriate services which decide based on
some gathered knowledge if the message should be repropagated or not.

But this means that we have to get away from the idea that we may only place a
JSE rendezvous somewhere and propagation just works. Either, we design our peer
application to use only standard services or we implement the user services also
in Java on the rendezvous peer. The third and best solution would be of course
to have an Eiffel rendezvous implementation but this is not possible due to
lack of time.
