% Usage chapter

\svnInfo $Id$

\chapter{Usage}
\label{ch:usage}

In this chapter, we are looking at the API and present how the \vampeer{} library
can and should be used. While we first list all the possibilities, we describe
also some examples which are all supplied with the library. The next chapter
then focuses on a bigger example, a simple Origo cluster.

\section{Platform starting}

For starting and stopping the platform, we always deal with a
\eclass{P2P\_PLATFORM} instance. To get the instance, we call \texttt{make}
passing the configuration directory path and a logger (\eclass{L4E\_LOGGER}).
The platform automatically reads the configuration file
\texttt{PlatformConfiguration.xml}, if available, and sets the
\texttt{is\_configured} variable appropriately. If it is false, we have to
provide a new \eclass{P2P\_CONFIGURATION} as shown in
listing~\ref{lst:usage_configureplatform}.

\begin{lstlisting}[caption={Configuring the platform instance},
label=lst:usage_configureplatform]
configure_platform is
		-- Configure VamPeer platform instance
	require
		Logger_valid: logger /= Void
	local
		conf: P2P_CONFIGURATION
	do
		create platform.make (".vampeer", logger)
		if not platform.is_configured then
			conf := platform.default_configuration -- New NPG Peer
			conf.set_name ("Peer name")
			conf.set_description ("Peer node description")
			platform.configure (conf)
		end
	ensure
		Platform_set: platform /= Void
	end
\end{lstlisting}

The default configuration returns the settings for a new NPG peer: A new peer ID
is created, the TCP settings are set to automatic interface/port detection and
the rendezvous is set to client mode with the standard NPG rendezvous servers.
Before the configuration is fed into the platform, we set an appropriate peer
name and a description.

The next step is to load the NPG. For the public NPG, this is easily done with
the \texttt{standard\_net\_peergroup} method which takes care of module
implementation advertisement creation and group loading.

\begin{lstlisting}[caption={Loading/starting the platform with the public NPG},
label=lst:usage_startnpg]
start_platform is
		-- Load and start net peer group
	require
		Platform_configured: platform /= Void and platform.is_configured
	do
		npg := platform.standard_net_peergroup  -- Load NPG
		if platform.module_status /= platform.init_failed then
			platform.start  -- Start Platform/NPG
		end
		if platform.module_status /= platform.start_ok then
			npg := Void
		end
	ensure
		Npg_set: npg /= Void implies npg.module_status = npg.start_ok
	end
\end{lstlisting}

Modules can make use of start parameters which are provided with the platform's
\texttt{start\_with\_arguments} command (expecting an \eclass{ARRAY [STRING]}).
All started modules will receive the same arguments. However, the JXTA services
do not actually use them.

When the platform is successfully started, we may access the services via the
NPG peer group instance. Note that at this point of time, the rendezvous client
may not yet be connected to a server and propagated messages will be lost. See
subsection~\ref{sec:usage_rendezvous} to see solutions to this problem.

We should not forget to maintain an event loop when we are done with
initializing, or the application will quit instantly. The platform does not
provide such a feature.

To stop the platform again, we just call \texttt{platform.stop}. If you just
like to pause the \ptp{} activity, you will like the \texttt{suspend} command
(see section~\ref{sec:design_modules}).

\subsection{Private peer groups}
\label{sec:usage_peergroup}

It is somewhat more complicated to load a private peer group since we have to
provide and create more specific settings. The entire process looks very
similar but we have to create another configuration and load the private NPG
differently.

\paragraph{Creating new IDs}

The very first step is to create all the IDs used for the new peer group.
Please read the introduction in section~\ref{sec:design_peergroup} at
page~\pageref{sec:design_peergroup} to get an overview about the definition of a
peer group.

Listing~\ref{lst:usage_createids} shows how to generate the three IDs used for a
new private NPG: a MCID and a MSID for the peer group module and finally the
peer group ID. A private NPG is always a child of the WPG, so we use the WPG
UUID as parent ID.

\begin{lstlisting}[caption={Creation of IDs for a new peer group},
label=lst:usage_createids]
create_peergroup_ids is
		-- Create all IDs used for a new peer group
	local
		mcid: P2P_MODULE_CLASS_ID
		msid: P2P_MODULE_SPECIFICATION_ID
		gid: P2P_PEERGROUP_ID
		wpgid: P2P_WORLDGROUP_ID
	do
		create mcid.make_new
		create msid.make_new_with_class (mcid.uuid)
		create wpgid.make
		create gid.make_new_with_parent (wpgid.uuid)
	end
\end{lstlisting}

You will not use that code in your peer application; the creation of the new IDs
is a one-time process. You will hard code the new IDs in your application
afterwards. Instead of using this example above, you would better use the
\emph{idcreator} example which generates all the different kinds of IDs.

\paragraph{Creating a configuration}

To create an appropriate configuration, we have to set the peer ID, name and
description in a \eclass{P2P\_CONFIGURATION} object as shown in
listing~\ref{lst:usage_newconf}. Additionally, we have to add service
configurations for the tcp and the rendezvous module. For the TCP configuration,
you may safely choose the default one with \texttt{default\_tcp\_configuration}.
The rendezvous configuration needs to be adapted to the groups rendezvous
servers, see subsection~\ref{sec:usage_rendezvous} for more details.

\begin{lstlisting}[caption={Creating a platform configuration for a private peer
group}, label=lst:usage_newconf]
new_configuration: P2P_CONFIGURATION is
		-- New configuration for a private peer group
	require
		Group_id_valid: gid /= Void and gid.is_valid
	local
		pid: P2P_PEER_ID
		rdvconf: P2P_RENDEZVOUS_CONFIGURATION
	do
		create pid.make_new_with_group (gid.uuid) -- New peer ID
		create rdvconf.make -- Rendezvous client configuration
		rdvconf.add_seed_uri ("http://stablehost.org/rdvs.cgi")
		create Result.make_with_id (pid)
		Result.add_service_parameter (transport_tcp_mcid, default_tcp_configuration)
		Result.add_service_parameter (rendezvous_mcid, rdvconf)
	ensure
		Result_set: Result /= Void and Result.is_valid
	end
\end{lstlisting}

The constants for the TCP and rendezvous MCIDs can be found in
\eclass{P2P\_CONSTANTS}.

\paragraph{Creating a module implementation advertisement}

A module implementation advertisement for the group should be created when it
is not available in the cache yet. Listing~\ref{lst:usage_impladv} shows how we
first can get a standard advertisement containing already all advertisements for
the JXTA services. We then add a user service and store the entire document to
disk using the cache manager.

\begin{lstlisting}[caption={Creating a peer group module implementation
advertisement}, label=lst:usage_impladv]
set_peergroup_implementation_advertisement is
		-- Make sure that peer group implementation advertisement exists
	require
		Platform_valid: platform /= Void
	local
		params_doc: P2P_XML_DOCUMENT
		pg_mia, smia: P2P_MODULE_IMPLEMENTATION_ADVERTISEMENT
	do
		if not platform.cache_manager.has_module_implementation_advertisement (pg_msid) then
			pg_mia := platform.peergroup_implementation_advertisement (pg_msid, "PG_CLASS", "group description")
			params_doc := Result.parameter.document
			-- Add user service impl adv
			smia := platform.default_implementation_advertisement (service_msid, "SERVICE_CLASS", "service description")
			params_doc.create_root_child_element ("Svc", namespace_empty)
			params_doc.add_child_element (params_doc.last_element, smia.document.document.root_element)
			-- Store group impl adv
			platform.cache_manager.store_module_implementation_advertisement (pg_mia)
		end
	end
\end{lstlisting}

\paragraph{Loading a private NPG} To load a private peer group, the platform
provides the method \texttt{load\_net\_peergroup} which expects the group ID,
the specification ID and an agent for instantiating the group.

We do not like to load the peer group module directly because we want to have a
unified access through the platform object. This also allows the platform to be
up to date with its module status.

\begin{lstlisting}[caption={Loading a private NPG}, label=lst:usage_loadnpg]
load_peergroup is
		-- Load a private net peer group
	do
		npg ?= platform.load_net_peergroup (gid, pg_msid, agent peergroup_loader)
		if npg /= Void and npg.module_status /= npg.init_failed then
			npg.group_advertisement.set_name ("Group name")
			npg.group_advertisement.set_description ("group description")
			platform.cache_manager.store_peergroup_advertisement (npg.group_advertisement)
		end
	end

peergroup_loader (a_pg: P2P_PEERGROUP; an_id: P2P_ID; a_mia: P2P_MODULE_IMPLEMENTATION_ADVERTISEMENT): P2P_MODULE is
		-- Private NPG loader
	do
		if a_pg = platform and an_id.is_equal (gid) and pg_msid.is_equal (a_mia.specification_id) then
			create {PG_CLASS} Result.init (a_pg, an_id, a_mia)
		end
	end
\end{lstlisting}

\section{Services}

After starting the platform, we will only work with the peer group instance and
its services. All modules are registered in the peer group, so we may access
them through our NPG. While the JXTA services have an easy access method (for
example \texttt{npg.endpoint\_service}), we have to access user services through
their module name: \texttt{npg.lookup\_module("servicename")}.

\subsection{Endpoint service}

The endpoint service is very central because all other services rely on it,
directly or indirectly. This is true on the one hand for all services and on the
other hand also for the transport modules.

\paragraph{Receiving endpoint messages}

We shall first look how services may use the endpoint service. When they are
ready to receive endpoint messages, they register a service name, an optional
service parameter and a handler using \texttt{extend\_service}. The service name
is usually the assigned module ID of the registering service, therewith we get a
unique ID.

The actual, internal handler name is the combination of the service name and the
parameter. When we specify also a parameter, we get only those messages that
match exactly the service name \emph{and} the parameter. If no such handler
exists, the handler matching only the service name will be called. Note that we
can only have one handler per service; when a handler is registered, a possibly
old handler for the same service name/parameter is silently replaced.

Message handlers get an endpoint message together with the extracted source and
destination endpoint address. Handlers should not do long processing jobs and
should return as soon as possible\footnote{See
section~\ref{sec:impl_threads_tcp} about the thread handling in our TCP
transport.}.

See listing~\ref{lst:usage_endpointhandler} for an example message handler. It
prints out the content for the message element with name ``dummy'' from the user
namespace.

\begin{lstlisting}[float, caption={Example endpoint message handler},
label=lst:usage_endpointhandler]
process_message (a_msg: P2P_MESSAGE; a_source, a_destination: P2P_ENDPOINT_ADDRESS) is
		-- Process incoming endpoint message
	require
		Message_valid: a_msg /= Void
		Source_valid: a_source /= Void
		Destination_valid: a_destination /= Void and a_destination.service_name.is_equal (sname)
	local
		msgel: P2P_MESSAGE_ELEMENT
	do
		msgel := a_msg.element_by_namespace_and_name (a_msg.namespace_user, "dummy")
		if msgel /= Void then
			print (msgel.content)
		end
	end
\end{lstlisting}

\paragraph{Reaching remote peers}

For actively reaching other peers, there are three possibilities:

\begin{enumerate}
\item \texttt{send\_message} and \texttt{send\_message\_mangled},
\item \texttt{propagate} and \texttt{propagate\_mangled} and
\item \texttt{ping}.
\end{enumerate}

To send a message, we simply call one of the send message methods passing an
endpoint message together with an endpoint address. The endpoint address should
use the protocol \texttt{jxta} with a peer ID.
Listing~\ref{lst:usage_sendmessage} shows a simple example for this.

\begin{lstlisting}[float, caption={Creating and sending an endpoint message},
label=lst:usage_sendmessage]
send_endpoint_message (a_dest: P2P_PEER_ID) is
		-- Send endpoint message to `a_dest'
	require
		Dest_valid: a_dest /= Void and a_dest.is_valid
	local
		ea: P2P_ENDPOINT_ADDRESS
		msgel: P2P_MESSAGE_ELEMENT
		msg: P2P_MESSAGE
	do
		create ea.make_with_id (a_dest, "pingservice", Void)
		create msg.make
		create msgel.make_string (msg.namespace_user, "Data", Void, "Ping")
		msg.extend (msgel)
		peer_group.endpoint_service.send_message (ea, msg)
	end
\end{lstlisting}

To learn if you need the ``mangled'' version or not, you may revert to
section~\ref{sec:design_mangling} on page~\pageref{sec:design_mangling}.
However, using \texttt{send\_message\_mangled} is usually the safer way, but
requires us to pass the group ID of the calling service.

The propagate methods pass the message to all transports which should make use
of transport specific propagation techniques. Currently, only the TCP transport
can handle this request by sending a UDP multicast packet\footnote{The message
size is therefore limited to 16KB\@.}. However, our TCP module only implements
outgoing multicast and cannot read any incoming multicast messages. Thus,
multicast is virtually useless at the moment.

Using the endpoint's propagation method will at best reach peers in the local
network, never the entire peer group. To propagate a message, we do not pass a
full destination address because it is protocol and destination unspecific; we
just pass the destination's service name and parameter.

While the methods for sending or propagating messages are normally asynchronous,
the ping command is a time-consuming call as it waits for a remote answer. We do
not send messages with \texttt{ping}, we just like to check whether the given
endpoint address is valid and available to us or not. The TCP transport for
example tries to open a connection and to do a handshake with the remote peer.

\paragraph{Transport handling}

Transport modules also register with the endpoint service but using the method
\texttt{extend\_message\_transport}. Transports may either be responsible for
incoming (\eclass{P2P\_MESSAGE\_RECEIVER\_TRANSPORT}) or outgoing messages
(\eclass{P2P\_MESSAGE\_SENDER\_TRANSPORT}) or both; the endpoint service is able
to deal with these types.

Transports may induce messages by calling the \texttt{demux} command which
analyzes the message and passes it to the appropriate service. The endpoint
service will simply ignore messages for which no service handler exists.

\paragraph{Message filtering}

The endpoint service has the feature to filter messages out. It is possible to
extend filters for incoming or outgoing messages. Filters may not only decide
whether a message is discarded or not but may also change the messages.
Listing~\ref{lst:usage_endpointfilter} shows how such a filter handler could
look like.

\begin{lstlisting}[caption={Example endpoint message filter},
label=lst:usage_endpointfilter]
message_filter (a_msg: P2P_MESSAGE; a_src, a_dest: P2P_ENDPOINT_ADDRESS): P2P_MESSAGE is
		-- Discard incoming messages, if `ignore_all' is set
	require
		Message_valid: a_msg /= Void
		Source_valid: a_src /= Void
		Destination_valid: a_dest /= Void
	do
		if ignore_all then
			logger.info ("Discarding message from: " + a_src.out)
		else
			Result := a_msg -- feed message back to other filters and services
		end
	ensure
		Result_set: ignore_all = (Result = Void)
	end
\end{lstlisting}


\subsection{TCP Transport module}

For the TCP transport module, we will not show its interface because a user
never gets into direct contact with the module's features. But we like to show
how the user may configure the transport.

The TCP transport looks for its service parameter in the platform configuration.
The configuration must be existent or the module will not start. There are
currently three values to set: the \texttt{Port}, the \texttt{InterfaceAddress}
and the \texttt{MulticastOff} flag.

\begin{lstlisting}[language=XML, caption={Full TCP transport configuration},
label=lst:usage_tcpconf]
<Parm type="jxta:TCPTransportConfiguration">
	<MulticastOff></MulticastOff>
	<Port>9701</Port>
	<InterfaceAddress>129.132.105.170</InterfaceAddress>
</Parm>
\end{lstlisting}

When the \emph{MulticastOff} flag is set, the TCP module will disable
propagating via multicast. When the flag is not set, only sending of multicast
messages is supported. The module currently does not support listening for
multicast messages. We should therefore disable multicast.

The \emph{port} specifies the server port. If it is not set, the module will
automatically choose a port in the range 1024--65'535.

The \emph{interface address} also concerns the TCP server. When the address is
set, the module will only accept messages for the given address. We may use this
in combination with VPN (virtual private network) to lock out messages from
unauthorized sources.

When the interface address is not specified, the module tries to detect the
interface and only listens on this interface. It is important for the platform
to know its own IP, namely to create the peer advertisement which includes the
route information.

The platform can not always detect its IP correctly. It has to use a connection
to find out the local IP. This is done when the rendezvous seed URL is resolved
when the platform is started (see the next sub section). When the platform does
not need to get the rendezvous seed list, it will set the local IP to
\texttt{127.0.0.1}.

\subsection{Rendezvous service}
\label{sec:usage_rendezvous}

The essential rendezvous service interface is rather small as it only has to
provide methods to propagate messages\footnote{See
section~\ref{sec:jxta_rendezvous} for a detailed rendezvous service
description.}. The main part of the entire server connection handling is done
internally and is not really of interest for a user.

\paragraph{Message propagation}

When propagating a message, one has to provide the endpoint message, the
destination's service name/parameter and a TTL.

The TTL is an integer value meaning the maximal number of hops the message can
be forwarded. Usually, we just set the maximum \texttt{Ttl\_max}~(50).

There are several propagation methods: \texttt{propagate\_in\_group} sends the
message to all connected rendezvous servers whereas
\texttt{propagate\_to\_neighbours} uses the endpoint's propagation method
(propagating to the local network). \texttt{propagate} is usually the preferred
method as it calls both methods above. We provide also the possibility to
propagate messages to a given list of peers with \texttt{propagate\_to\_peers}.

The rendezvous service is only responsible for sending messages, the recipient's
endpoint service will pass the message directly to the specified service, the
rendezvous service is not touched at the recipient side.

When we repropagate a message (meaning to propagate a received propagated
message), the rendezvous service is able to detect this and automatically reuses
the meta data stored in a special rendezvous message element.

\paragraph{Rendezvous events}

As many services rely on message propagation, they would like to make sure that
the current peer is connected to a rendezvous so that message propagation
is guaranteed. However, just at the time when the platform has started, the
rendezvous connection is not available yet. So, it is rather useless at this
time to use the service.

We therefore need a way to know when the connection will be of use to the
services. That is what \emph{rendezvous events} are designed for. Interested
parties may register for such events. Current supported rendezvous types are
only the connection and disconnection events to a rendezvous server as we
currently just implement an edge peer.

To receive these events, we register an agent with
\texttt{extend\_rendezvous\_event\_handler}. The agent should expect a
\eclass{P2P\_RENDEZVOUS\_EVENT} which provides the event type and the involved
peer ID (e.g. the rendezvous server). An agent should not do time consuming
processes as it would stall incoming messages from the rendezvous.
Listing~\ref{lst:usage_rdvevent} shows how to publish the peer advertisement as
soon as we are connected to the group.

\begin{lstlisting}[caption={Example rendezvous event handler},
label=lst:usage_rdvevent]
process_rendezvous_event (an_event: P2P_RENDEZVOUS_EVENT) is
		-- Publish our peer advertisement to group when connected to rdv
	require
		Event_valid: an_event /= Void
	do
		if an_event.type = {P2P_RENDEZVOUS_EVENT}.type_connected_to_rendezvous then
			peer_group.discovery_service.publish_advertisement_remotely (peer_group.peer_advertisement, Void)
		end
	end
\end{lstlisting}

\paragraph{Rendezvous Seeds}

We somehow have to specify the rendezvous server address (or multiple addresses)
so that a new, isolated peer can contact the group. For a peer application, one
would elect some peers as permanent rendezvous servers and make their addresses
available.

As described in section~\ref{sec:jxta_rendezvous}, there are several ways to do
this. The preferred solution is to maintain a file, accessible through HTTP,
with a rendezvous server list. The peer's configuration then would be hard coded
to this URL. The NPG rendezvous list can be found at the following address,
listing~\ref{lst:npgrdvs} shows its content:\\
\texttt{\url{http://rdv.jxtahosts.net/cgi-bin/rendezvous.cgi?2}}

\begin{lstlisting}[language=, caption={Public NPG rendezvous seeds},
label=lst:npgrdvs]
http://209.128.126.120:9700
http://209.128.126.120:9710
tcp://192.18.37.36:9701
tcp://192.18.37.37:9701
tcp://192.18.37.38:9701
tcp://209.128.126.120:9701
tcp://209.128.126.120:9711
\end{lstlisting}

Edge peers then randomly try one of the seed addresses and continue trying until
they get a connection lease.

The rendezvous configuration contained in the platform configuration file is
simple and looks like the one in listing~\ref{lst:usage_rdvconf}.
\vampeer{} updates the configuration with known servers, once it has resolved a
seed URL.

\begin{lstlisting}[language=XML, caption={Example rendezvous configuration},
label=lst:usage_rdvconf]
<Parm type="jxta:RdvConfig" config="client">
	<seeds>
		<addr seeding="true">http://origo.ethz.ch/rdv.cgi</addr>
		<addr>tcp://129.132.105.170:9700</addr>
	</seeds>
</Parm>
\end{lstlisting}

\subsection{Resolver service}

\paragraph{Resolver handlers}

Clients using the resolver service choose a unique handler name and register a
handler agent for processing query and one for response messages. Queries and
responses are thus tightly coupled because when you send a query, you are
interested in replies and a typical peer will perform queries and replies. The
handler registration works with the \texttt{extend\_handler} command. The
handler name is usually the client service module ID.

A resolver query handler gets a \eclass{P2P\_RESOLVER\_QUERY} object containing
the query string with some meta information. The agent should set the
\texttt{repropagate} flag in the query object to specify whether the resolver
should repropagate the message or not. Repropagation is only done by the
resolver if the peer is configured as a rendezvous. The response handlers have
the equivalent signature, they expect a \eclass{P2P\_RESOLVER\_RESPONSE} object.

Besides queries and responses, the resolver handles also SRDI messages. It is
basically the same as with queries, so we overlook the exact details here.

\paragraph{Querying and responding}

To send a query, we build a \eclass{P2P\_RESOLVER\_QUERY} as shown in
listing~\ref{lst:usage_rsvquery}\footnote{The final query would then look like
in listing~\ref{lst:jxta_resolverquery} on
page~\pageref{lst:jxta_resolverquery}.}. Beside the query string, it needs the
source peer ID, the handler name and an integer ID. The ID's purpose is to help
identify responses. The resolver automatically adds the source peer route
advertisement so that every recipient is able to respond directly.

\begin{lstlisting}[caption={Sending a resolver query}, label=lst:usage_rsvquery]
send_resolver_query (a_dest: P2P_PEER_ID) is
		-- Send a resolver query
	require
		Dest_valid: a_dest /= Void and a_dest.is_valid
	local
		query: P2P_RESOLVER_QUERY
	do
		create query.make (peer_group.peer_id, handler_name, 1, "Got a beer?")
		peer_group.resolver_service.send_query (a_dest, query)
	end
\end{lstlisting}

The example sends the query to a specific peer but it is also possible to send
messages to the entire group. We just have to use the \texttt{propagate\_query}
method which only expects the query.

Responding is equivalent. It is somewhat easier to respond to a received query
because \eclass{P2P\_RESOLVER\_RESPONSE} provides a constructor to create a
response out of a query: \texttt{make\_from\_query}.

Note that a response does not need to be preceded by a query. This means that a
response can also be propagated in order to publish information to everyone.

\subsection{Discovery service}

As we already know is the discovery service used to deal with advertisements. It
provides methods for querying and publishing, locally and remotely. Most
functions differ between peer, group and other (general) types of
advertisements because also the discovery protocol does.

\paragraph{Querying}

A query always consists of the advertisement type and possibly a key/ value pair.
The value may be unspecified in local queries meaning to find all advertisements
that have an element named like the key. Wildchars are also allowed in values
as already described in section~\ref{sec:jxta_discovery}.

For local queries, we call one of the \texttt{local\_*\_advertisements} methods
(there is one for each type) passing the key and a value. The return value is a
list of all matching advertisements.

It is also possible to get an advertisement from the store using its unique ID.
This is done with a \texttt{local\_*\_advertisement} command. While you pass an
ID for the peer or group advertisements, you have to specify the exact unique ID
as \eclass{STRING} when looking for an other advertisement type.

Local queries can always be performed except when the discovery module is
stopped or has failed during the start.

Remote queries are done with the \texttt{query\_remote\_advertisements} method.
For this, we need to build a \eclass{P2P\_DISCOVERY\_QUERY} object and possibly
specify a single recipient peer and a response handler. When the recipient peer
is not specified, the query is propagated to the group.

A query object may contain an advertisement type, a key/value pair, a threshold
and a source peer advertisement. We have to pay attention to the different
semantics for some attribute combinations.

Normally, we specify all the attributes which means to search for all
matching advertisements of the given type. The threshold defines how many
results we like to receive in maximum. However, we could receive a lot more
since we may receive answers from various peers. A peer query example is
provided in listing~\ref{lst:usage_discoveryquery} on the next page.

Specifying only the type \texttt{Peer} and the threshold \texttt{0}, all
recipient peers should send a response with their own peer advertisement.

\begin{lstlisting}[caption={Sending a remote discovery query},
label=lst:usage_discoveryquery]
discover_buddy is
		-- Send discovery query for peers named "Buddy"
	require
		Network_connected: peer_group.rendezvous_service.is_connected
	local
		query: P2P_DISCOVERY_QUERY
	do
		create query.make (peer_group.discovery_service.type_peer)
		query.set_threshold (10)
		query.set_restriction ("Name", "Buddy")
		peer_group.discovery_service.query_remote_advertisements (query, Void, agent response_handler)
	end

response_handler (a_response: P2P_DISCOVERY_RESPONSE) is
		-- Prints buddy IDs of all results
	require
		Response_valid: a_response /= Void and a_response.is_valid
	local
		advs: DS_LIST_CURSOR [P2P_PEER_ADVERTISEMENT]
	do
		from
			advs := a_response.all_peer_advertisements.new_cursor
			advs.start
		until
			advs.after
		loop
			print (advs.item.peer_id.out + "%N")
			advs.forth
		end
	end
\end{lstlisting}

When the key/value pair is not specified, recipient peers should return a random
advertisement set matching the given type. The set's count should not exceed the
threshold value.

\paragraph{Response handlers}

In the discovery service, there are two possibilities to add a response handler.
If we are only interested in our query, we specify a \emph{query ID} handler
when querying. This handler will only be called when a response for our query is
received. Since multiple responses can be sent, the handler stays registered
until we call \texttt{remove\_queryid\_listener}.

The other response handler type serves for general responses which can be
registered through \texttt{extend\_response\_listener}. Whenever a response is
received, the discovery calls all response agents (actually, after a possible,
specific query ID handler).

When no response handler is called, the discovery will itself locally publish
all received results. So, whenever we register a handler, we have to handle the
results and publish them, if needed.

It is only possible to register handlers for responses. Queries are always
handled by the discovery service itself. We can not tune the discovery to
respond differently to certain queries.

\paragraph{Publishing}

Publishing an advertisement locally, using
\texttt{publish\_advertisement\_locally}, means to save it in the local
advertisements store under its unique ID. An older advertisement with the same
ID is replaced.

On remote publishing, we may either choose to build the discovery response
ourselves or to just pass a single advertisement to
\texttt{publish\_advertisement\_remotely}. We also may specify a recipient peer,
when we do not want the response to be published to the group.

A \eclass{P2P\_DISCOVERY\_RESPONSE} contains besides a list of results, the type
and the key/ value pair (if it is really a response). A respondent may also
provide its peer advertisement.

An advertisement is always published together with its remote expiration time.
When the lifetime is not set, the default expiration time for remote peers is by
default two hours.

Note that remotely published advertisements cannot be revoked. They may be
passed among group peers until they expire. Though, it is possible to delete an
advertisement locally using one of the flush methods which expect the
advertisement's unique ID.

See listing~\ref{lst:usage_publishadv} to see a publishing example and how to
set the lifetime.

\begin{lstlisting}[caption={Publishing an advertisement remotely},
label=lst:usage_publishadv]
publish_advertisement (an_adv: P2P_ADVERTISEMENT) is
		-- Publish an advertisement setting its lifetime to a day from now
	require
		Advertisement_valid: an_adv /= Void and an_adv.is_valid
	do
		an_adv.set_lifetime_relative (86400000)
		peer_group.discovery_service.publish_advertisement_remotely (an_adv, Void)
	end
\end{lstlisting}


\section{Writing a P2P application}

While the \vampeer{} library offers very basic \ptp{} features, the overlying
applications will have to specialize them and to design their own application
messaging protocol above JXTA.

For its design, we recommend to rely on the JXTA services, especially on the
discovery. The use of advertisements is a core idea in JXTA and it would be
great to create advertisements for user related entities too.

Unfortunately, there is a problem associated with this endeavour since the
rendezvous server has to know all advertisement types it deals with. This means
that we currently either have to bypass the rendezvous or to implement user
defined types in the JSE rendezvous peer too.

\subsection{Writing a user service}

Applications will usually create at least one service which closes the gap
between the application's logic and JXTA.

To create a module, we just inherit from the deferred class \eclass{P2P\_MODULE}
and effect the methods \texttt{start}, \texttt{suspend} and
\texttt{stop}\footnote{Please read section~\ref{sec:design_modules} for further
details.}. We usually also redefine the \texttt{init} method to create needed
data structures.

We also have to implement the feature \texttt{check\_dependencies} which has the
purpose to identify the required module dependencies used for loading. It is
therefore called in the precondition of \texttt{init}. We are allowed to use
also other services but we then have to check them for existence first.

While it is simple to build a user service, the integration into the peer group
involves several steps.

As the user service is a module, we have to build a MCID, a MSID and a module
implementation advertisement. Listing~\ref{lst:usage_impladv} already pointed
out how to do this.

Because we change the set of user services in the group, we will certainly have
to build a private peer group as described in section~\ref{sec:usage_peergroup}.
We now also have to specialize the peer group implementation by creating a new
peer group class which should inherit from \eclass{P2P\_GENERIC\_PEERGROUP}.
\texttt{define\_modules} and \texttt{load\_extern\_module} should be redefined
as shown in listing~\ref{lst:usage_userservice}.

\begin{lstlisting}[caption={Redefining peer group modules},
label=lst:usage_userservice]
define_modules is
		-- Define Group services in `modules_list'
	do
		-- add standard modules from parent peer group to `modules_list'
		Precursor
		-- add user service to the end of `modules_list'
		modules_list.put_last (["user_service", service_mcid, service_msid, parent_is_owner_if_available])
	end

load_extern_module (an_id: P2P_ID; a_mia: P2P_MODULE_IMPLEMENTATION_ADVERTISEMENT; a_name: STRING): P2P_MODULE is
		-- Load user module
	do
		if service_msid.is_equal (a_mia.specification_id) then
			create {SERVICE_CLASS} Result.init (Current, an_id, a_mia)
		else
			Result := Precursor (an_id, a_mia, a_name)
		end
	end
\end{lstlisting}

The \texttt{parent\_is\_owner\_if\_available} flag means that the module loader
will only create a new module loader if the parent peer group did not define
this module. If each peer group would need its own instance, we would specify
\texttt{current\_is\_owner}.

Using the new private peer group implementation, our user service will be loaded
and managed by the \vampeer's platform.

\section{Examples}

The current \vampeer{} release also contains some examples so that new users
are able to get into the code and can test the library. We will describe them
here and show how to run them. There is also a bigger example which we will
separately enlighten in the next chapter.

\subsection{Endpoint message sender/handler}

The first example shows how to use the \emph{endpoint service}. It was
originally created when the other services were not available yet. Therefore, it
does not make use of the discovery to find other peers.

It consists of two parts, namely two peer roles: the
\texttt{endpoint\_message\_sender} and the \texttt{endpoint\_message\_handler},
which both run in the public NPG. The sender will send a simple endpoint message
to the handler peer which sends a reply message back. Both peers log the events
to the standard output, so we can see what is currently happening. While the
handler only quits when we shut it down (with \texttt{Ctrl-C}), the sender
terminates as soon as it receives the reply.

The handler's platform is configured to listen on port \texttt{9710} while the
sender chooses its port automatically. To start the sender, we have to specify
the handler peer's IP and port. This is of course not the way we would like to
deal with other peers in our application. We just like to limit our example to
the endpoint service's possibilities.

To run the example locally, we first start the endpoint message handler and
afterwards the sender application with the arguments: \texttt{localhost 9710}.
The logging level is set to \texttt{INFO}, so we can see when the platform has
been started and the message has been sent and received.

Looking at the code, we see how the sender creates and sends an endpoint message
and how it registers the service listener to receive the reply. The handler
looks similar but also uses the endpoint's filter method to display all
incoming messages.

The example is very simple but shows how the minimal configuration for a
\vampeer{} platform may look like.

\subsection{Rendezvous propagation}

The next example demonstrates the rendezvous propagation mechanism. It resides
in the \texttt{rendezvous\_propagate} example directory. The application
connects to a NPG rendezvous and propagates a message every five seconds.

When running multiple instances, we could see the propagated messages from the
others. But it does not work; messages get not propagated to the entire group.
The reason for this is that we would have to adapt the rendezvous server to
repropagate messages for our specific service\footnote{See
section~\ref{sec:design_propagation} for more details to this problem.}.

Thus, this example shows how we can not use the rendezvous service for
propagating any message and it shows how important it is that the rendezvous
server is part of the \ptp{} system and not just a standard JXTA infrastructure
peer.

\subsection{Discovery}

The \texttt{discovery} example shows how we can find other peers in the public
NPG. We just run multiple instances and they should be able to discover each
other. The application only expects a configuration directory path as argument.

The details of the discovery procedure are as follows: As soon as we are
connected to a rendezvous, we publish our peer advertisement in the group. We
then send one peer query request and wait one minute for responses. Incoming
peer advertisements are printed out immediately.

When no other peers are known to the rendezvous, we should at least receive the
rendezvous peer and our own advertisement. Note that we may get responses from
multiple peers, not only from the rendezvous because the rendezvous propagates
the query request also to the others.

\subsection{JXTA JSE rendezvous server}
\label{sec:usage_rdvserver}

The last two examples make use of the NPG rendezvous servers. But we mentioned
already that the public infrastructure is not accessible at the moment. Hence,
we will have to run our own NPG rendezvous server. The \texttt{RdvServer}
example shows how we can set it up using the JXTA's reference implementation JSE
in version 2.4.1.

The Java application provides a rendezvous and a relay server and is configured
to listen on port \texttt{9700} on all interfaces. When we start the script
\texttt{startNPGPeer.sh}, the rendezvous will be started in the NPG. Because we
use also a rendezvous peer for the next example, namely Origo, there exists
another script \texttt{startOrigoPeer.sh} which starts the rendezvous in the
private Origo peer group.

To point the discovery example to our new rendezvous server, we have to change
its platform configuration. We normally start the discovery application first to
generate the configuration directory. Then, we are able to change the
configuration XML file by replacing the old seeds and the NPG seed URL with the
new destination address.
