This is a pre-release of RCDS (resource catalog and distribution system)

RCDS has several components:

+ resource catalog server (rc_server)
+ test clients
+ ftp-mirror that updates rc_server
+ personal web proxy
+ publication tool
+ SONAR daemon

RCDS was designed to replicate web pages and keep track of the locations
of replicas, so that a client (such as a web browser) could query RCDS
(the rc_server) to find out the locations of a resource (such as a web page)
and then use SONAR to choose from a nearby location.

SNIPE is a distributed system based on components of RCDS.  If you're
experimenting with SNIPE, you don't need all components of RCDS, only
the rc_server and perhaps some of the test clients.

Eventually we will get the various components separated out so that it's 
less confusing.

This is just a pre-release.  We're working on substantial improvements
to RCDS, including better authentication and multi-master replication
for the rc_server.

We've tried to make the code reasonably portable, but some bugs remain.

I. Compilation

To compile everything, do:

./configure
make

If you've already compiled RCDS on one platform and you need to
compile it on another, do

make distclean
./configure
make

("make distclean" gets rid of any config.* files already generated
by a previous run of configure.)

By default, "configure" will use the gcc compiler if you have it installed.
Sometimes gcc doesn't work correctly, or isn't installed correctly.
If you have problems using gcc, you might want to build rcds with your
system's native C compiler.  You can do this by saying

make distclean
CC=cc ./configure
make

(assuming your native c compiler is called "cc")


II. Installation

Once you have the components compiled, there are several things you 
need to do to install the rc_server on a host:

1. create an empty directory for the server data files

This directory can have any name, but it needs to be on a disk
with enough space.

Warning: the current rc_server uses the UNIX file system as a very 
crude indexed file system, that basically stores each record in
a separate file which is named for the MD5 hash of the key.  We
did this because we could not find a free indexed file package
which was sufficiently robust to distribute.  Berekely db 1.85
caused core dumps, and gdbm exhibited a lot of heap storage leakage.
The package we have is slow but reasonably bulletproof.
However, if you create lots of records your disk may run out of 
inodes.  So we recommend that you install it on a disk which 
isn't otherwise used for anything critical.

For the sake of example, we'll assume you're using /usr/local/rcds/ as
a top-level directory for rcds, and /usr/local/rcds/data/ as a place
to store the server data files.  Configuration files will be stored in
/usr/local/rcds/etc/.

2. copy the rc_server binary into an appropriate directory

For our example we'll assume you copy rc_server into
/usr/local/rcds/bin/rc_server

3. create authority and user files for the server

3.1 authority file

This file is used to tell the rc_server which URI domains it's
authoritative for.  Eventually this will be used by the server
to know which URIs to look up internally and which ones to
return redirects or error messages.  At present, the file is 
actually ignored, except that the rc_server complains if it is
not there.  So create one.  It's of the form:

uri_domain:server_domain

where uri_domain is a domain that might appear in a URI,
and server_domain is the domain of an RCDS server for URLs
with that uri_domain

Our example server_authority_file would go in
/usr/local/rcds/etc/server_authority_file
and have the contents

cs.utk.edu:nhse.cs.utk.edu

meaning that for URIs that contain cs.utk.edu as a domain, the
authoritative rc_server is nhse.cs.utk.edu 

3.2  user file

This is a file that the server looks at to obtain client
authentication credentials.  It is a text file which contains
lines (one for each user) of the form:

username:user-id:permissions:authtype:secret

where

+ "username" is the name of a user for the purposes of authenticating
  to rcds.  It doesn't have to be the same as a UNIX username.
  It can be any string of characters that is unique.

+ "user-id" is a unique integer identifier corresponding to that user.

+ "permissions" specifies the list of things that this user is allowed
  to do.  it is a comma-separated list of capability names, of which
  "urn" "url" "lifn" "debug" are currently defined.

  "urn" allows the user to make assertions about a URI
  "url" allows the user to add lifn->url bindings that point
    to a particular URL domain
  "lifn" allows the user to add lifn->url bindings from a 
    particular LIFN domain
  "debug" allows the user to set the debug level 

  Eventually it should be possible to specify these permissions
  on a per-domain basis, so that a user could only write entries
  to the rc_server database for a particular domain.  (a single
  rc_server can serve multiple domains).  For now, the permissions
  apply to the entire database.

  Note that in order for a user to create a lifn->url binding 
  he/she must have both "url" and "lifn" permission.

+ "authtype" is the kind of authenticaiton used.  for now,
  only "md5" is supported.  This uses md5, timestamps, and
  shared secrets to authenticate the user without transmitting
  the shared secret over the net.

+ "secret" is a shared secret.  It is a string of bits, encoded
  as short English words.  You cannot make up your own secret
  just by typing in English words.  Instead, you must generate 
  secrets using a program that knows how to output the right
  format.  

  In the "common/" subdirectory there is a program named "textbits".
  You can generate a secret of approximately NNN bits by typing 

  textbits -l NNN
  
  Because there are 2^11 different English words used in the text
  encodings of the bit-strings, each word encodes 11 bits.
  "textbits" will round NNN up to the next multiple of 11.

  textbits generates bit strings at the rate of one random bit per second.
  It will print out the bits one at a time, then it will print out the
  English language words corresponding to the bits.

  For good secrecy, we recommend using secrets of 80 bits or more.

an example line from the  server user file might look like

john:0:urn,lifn,url,debug:md5:MEN MYRA KING SAM LUGE DUE

where "MEN MYRA KING SAM LUGE DUE" was generated by the command
"textbits -l 64"

In our examples below, we'll assume that this file is called
/usr/local/rcds/etc/server_user_file

This file should only be readable by the user that runs rc_server.
It should NOT be world-readable.

4. create a user file for a client

The client also needs a file that contains credentials to talk to 
a server.  The client user file looks like:

uri_domain:server_host:server_port:username:authtype:secret

where 
+ "uri_domain" is the domain from a uri
+ "server_host" is the host name or ip address of a server host
+ "server_port" is the port # to use (0 = default port of 9272)
  (NOTE: this is NOT the user_id!)
+ "username" is the username that the server expects
+ "authtype" specifies what authentication type to use
+ "secret" specifies what secret to use

so if the server for uri_domain foo.bar.com were rcds.foo.bar.com,
and the user were "john" with the same secret as above, then the 
line for "john" in the user file would look like:

foo.bar.com:rcds.foo.bar.com:0:john:md5:MEN MYRA KING SAM LUGE DUE

In our example we'll call this "foo.credentials"

This file should only be readable by the user that runs the client.
It should NOT be world-readable.

5. start up rc_server and try it out

The way to start up rc_server is:

rc_server options &

where "options" include

-af authority_file 
	specify the name of the server authority file

-uf -user_file 
	specify the name of the server credentials file

-create 
	create databases.  if databases don't exist yet, and you
	don't specify this flag, rc_server will fail.

-debug ###
	set the debug level to ### (should be a number).

-logfile filename
	specify the name of a lot file

-syslog
	log events, debugging messages, etc. to syslog

-nosyslog
	do not use syslog

A typical startup script might look like

------------------------------------------------------------------------------
#!/bin/sh
RCDS_DIR=/usr/local/rcds
cd $RCDS_DIR/data
$RCDS_DIR/bin/rc_server \
	-af $RCDS_DIR/etc/authority \
	-uf $RCDS_DIR/etc/users \
	-debug 1 \
	-syslog &
------------------------------------------------------------------------------

To try out the rc_server, you can use the client programs in "client/"

First you must configure certain environment variables:

RC_SERVER	Is the host name of a server to use when writing
		to an RCDS server.  If this environment variable
		is not set, the RCDS client code will try to find
		a server using the domain name of the URI.

RC_PROXY	is the host name of a server that a client should
		use when doing queries.  If this variable is not
		set the RCDS client code will try to find a server
		using the domain name of the URI. 

RC_AUTH_INFO_FILE
		is the name of a file containing user credentials 
		

For example

------------------------------------------------------------------------------
#!/bin/sh
RC_SERVER=netlib2.cs.utk.edu
RC_AUTH_INFO_FILE=foo.credentials
export RC_SERVER RC_AUTH_INFO_FILE
update_name_test http://foo.bar.com/index.html md5=4FPUszVV5wiFxCK6uz2LRg
------------------------------------------------------------------------------

will add an assertion with name "md5" and value
"4FPUszVV5wiFxCK6uz2LRg" to the list of attributes for URI
http://foo.bar.com/index.html

------------------------------------------------------------------------------
#!/bin/sh
RC_PROXY=netlib2.cs.utk.edu
export RC_PROXY
query_name_test http://foo.bar.com/index.html 
------------------------------------------------------------------------------

will list the assertions for http://foo.bar.com/index.html

6. arrange for rc_server to be started every time the system reboots

On Berkeley-style systems, you need to run the startup script from
/etc/rc.local that starts up rc_server.

On SysV-style systems, you need to write up a script that will
start up rcds and/or shut it down, and put it in the appropriate
directory according to "init" run-levels.


