Registry for [comm] based applications
======================================

Intro
-----

Our goal is to implement interpreter discovery functionality for
[comm] based applications similar to the functionality in existence
for [tk send] based applications.


Properties of the [tk] based registry
-------------------------------------

*	Uses the X server as the database of known applications,
	through the upload of atoms and associating special
	properties with the master Tk toplevel window of an application.

From the above automatically follows that the [tk] registry is user
centric. I.e. each user has its own display, therefore its own X
server and thus a unique location for the placement of registry
information without interfering with other users.

This property of the [tk] registry should be preserved by the [comm]
registry as it automatically provides some amount of protection
against attacks.


Beyond the basics
-----------------

Each registry essentially constitutes a namespace for applications
with a want for communication, sort of a chatroom for
meeting. Depending on the context a per-user space can be to broad, or
not broad enough. How can we do this ?

*	An easy to implement restrictive scheme is to have one
	application launch a private registry (independent of the
	per-user registry) which is then available only to the child
	processes to this application. This allows a close knit group
	of processes a private room for communication without
	disturbing the greater scheme of things. Where are two
	alternate behaviours for this private registry: Independent
	and semi-private. In the first mode all child processes see
	only each other and nothing more. In the second mode the
	application holding the private registry also acts as a proxy
	to the per-user registry, making all per-user applications
	visible to the private group, but not the other way around.

*	A broader scheme is to have a per-host registry.

*	Another broader scheme is remote communication and remote
	registries.

Note that the above schemes are not entirely hierarchical. In the
implementation of the basic registry (see below) I mention that the
users home directory can be shared between multiple machines. This
already allows us to not only implement a per-user-and-host registry,
but also a per-user registry crossing the boundaries of the local
host.

I have currently no good idea how to implement a per-host registry
with good security. The point is that not only applications should be
able to choose whether to offer services to the full host or not, but
the registry should be able to have a say in this too, IOW allowed to
reject registration offers seen as dangerous.

As for accessing remote registries (beyond the distributed per-user
registry) I believe that a proxy-based solution provides better
security. IOW the applications and/or registries on a host talking to
a single local registry application which in turn talks to the
requested remote registries instead of all applications directly
talking to the remote registries they want.

The main problem I currently have is how to provide the information
about these more global registries to the applications and local
registries. Given that this is a system administration issue we can
accept here solutions requiring more manual intervention and setup
than for the simple case of a user just wanting his applications to
talk to each other. Best bet currently seems to be to have
world-readable global configuration files in the directory
"/etc/tcl/comm/" which provide this information to the user
registries.


Now that the namespacing issues of registries are discussed we can
move to another issue, advanced functionality. In contrast to the [tk]
registry which has to make do with the services provided by the X
server we can implement functionality which goes beyond the basic
(de)register of and searching for applications.

One exmaple of such functionality is the ability to ask for and get
notifications when applications (de)register.



Contents of the registry
------------------------

For the normal purposes of an application using the registry to find
other applications it is enough to store the name of a registered
application ( and a serial number if there are several instances of
the same application) together with the connection information (host
and port).

The host information (ip address) is also enough to allow a registry
to purge everything from a single host when the user-registry for that
host is going down.



Implementation of the basic [comm] registry
-------------------------------------------

*	The [comm] registry considers the home directory of a user as
	a resource unique to that user, possibly shared between
	several machines.

*	Inside of the home directory [comm] claims the directory
	".tcl/comm" for its own purposes, i.e. for the storage of
	configuration and state information.

*	When [comm] is loaded it looks for a file called
	"$HOME/.tcl/comm/registry/<hostname>". This file is called the
	"host-specific port file".

	(a)	[comm] will reads its contents and interprets them as
		the port the registry for the current user and host is
		listening on. [comm] when tries to connect to that
		port. If this is succesful [comm] will establish that
		it truly talks to the registry. If this is sucessful
		the application will register itself.

		If [comm] was unable to connect to a server on that
		port, or the server is not a registry [comm] will
		assume that there was a registry which lived on that
		port, but that this registry is now gone. It will
		erase the file and then proceed to become the registry
		itself. See (b) and (c).

	(b)	If the file exists, but is empty [comm] knows that
		another application is currently becoming the registry
		and will wait until the file is not empty. To prevent
		an early read of incomplete information the data in
		the file is considered valid if and only if it ends in
		a EOL marker.

	(c)
		If the file is missing [comm] will create it as empty,
		thus locking out other contenders (see last paragraph)
		and then proceed in becoming the registry itself. To
		this end it will start a server on a free listening
		port (as chosen by the OS) and then write the number
		of the port to the port file, enabling any waiting
		contender to proceed and talk to the newly created
		registry.

*	If the process currently holding the registry dies all
	registered applications are notified and will then try to turn
	themselves into the new registry. One of them will succeed and
	the others will then re-register themselves at the new
	registry application.

	Here the process of becoming the registry is easier as the
	identity of the port to use by the registry is already known
	to all applications. The applications will take that
	information and just try to start server on that port. The
	application which succeeds becomes the registry, thereas the
	others will find a server on that port and just reconnect.

*	The items above deal with a per-user registry local to a
	single host. They are not sufficient when trying to deal with
	per-user registry crossing the boundaries of a host to all
	machines sharing the users home directory.

	We could try to create a truly unique registry which is
	accessed by all hosts sharing the users home directory. There
	is however the diffcult problem of file locking. The rules
	above work good enough for one host accessing its port file,
	even if the file resides on a different host, as caching is
	the same for all the applications on the host. But when it
	comes to accessing the file from different hosts different
	cache policies, network latencies etc. make this quite
	fragile.

	Instead we go for a distributed solution. On each host the
	user executes his applications on one of the processes becomes
	the per-user registry for that host. As all these registries
	share the home directory their host-specific port files are
	visisible to each other. This means that the host-specific
	registries can watch the port files of the other registries
	for changes and are able to communicate with each other. This
	we use to distribute the information about (de)registrations
	across all registries for the user, creating one (virtual)
	host-independent registry for that user.

	This solution also works in the case if one of the registries
	dies. The other applications on that host will elect a new
	registry per the rules above and this registry will then
	proceed to open talks to the other registries. If the last
	application on a host dies this host simply drops out of the
	network until a new application starts and becomes the
	registry.

	Whenever a part of the distributed registry goes down all
	applications registered through that part are removed from the
	caches of the other parts. After the reelection of new
	registry the cache is filled again through the
	reregistrations.

	Future: We should make it possible for the parts of the
	distributed registry to talk to each other using encrypted
	communication lines to enhance the security.



Implementation of the restricted [comm] registry
------------------------------------------------

*	The application launching the private registry considers the
	environment as a unique resource it is sharing with its child
	processes. It relies on the fact that if an application makes
	modifications to the environment these changes are visible
	only to child processes, but not the parent.

*	Inside of the environment the restricted registry claims the
	variable "TCL_COMM_REGPORT" for its own purposes, i.e. the
	transmission of contact information to its childs.

*	A [comm] registry which finds the aforementioned variable in
	its environment will try to contact the registry at the port
	given as the value of the variable. If this succeeds the
	application will register itself. However if this fails the
	normal startup process is entered instead.

*	If the process holding the registry dies the child processes
	will be notified of this. Instead of selecting one of their
	kind as the new registry they will do nothing. They can keep
	up their current communication, and if they cached the
	name/port mapping for their peers even establish new
	communication in their group, but they are unable to talk
	outside of this group.


Packaging
---------

The configuration functionality of the registry and the management of
all data structures is placed into a separate package,
"comm::registry". This separation allows an application to configure
the behaviour of the registry according to its wishes (like: start a
private registry, no talking to a per-user registry, per-user-and-host
only instead of full per-user, etc.) before the loading of the "comm"
package actually launches the service and then provides access to it.
