Documentation changes needed to support RTD

Changes which are necessary to support a docs directory that
is scraped for "read the docs."  Changes include:

Tweaks to manual pages to allow them to be combined into a
large "user's guide" (removed the final quit command).

Addition of an rtd subidrectory under source and the needed
.xfm source to generate the various .rst files in the top
level docs (plural).

Moved the top level readme to the main source directory as
it was out of place at the top; created a new top level README.

Signed-off-by: E. Scott Daniels <daniels@research.att.com>
Change-Id: I708a750e3c58df4d0446eb3a5706c10bf65bed1d
diff --git a/README b/README
index 757b115..f3772d4 100644
--- a/README
+++ b/README
@@ -17,88 +17,44 @@
 #==================================================================================
 #
 
+RIC Message Router -- RMR
 
-Source for the RIC Messaging Library -- RMR.
+RMR is a message router library which an application can use to send messages
+to other RMR based applications. The destination of each message is governed
+by the message type and subscription ID, or just the message type.  RMR is
+responsible for establishing and managing each connection freeing the application
+from any network connectivity management.
 
-C does not provide the concept of package names,  yet we have
-a desire not to maintain all of the static code in a single large
-file, we use the following convention:
+This repo contains the source and documentation for both the core RMR library
+and for the Python bindings which allow a Python (v3) application to use RMR
+to send and receive messages.
 
-	<name>.c --		C code which builds separately and generates an object
-					that is ultimately added to the archive.
-
-	<name>_static.c - File containing nothing but static functions (a.k.a package
-					only functions). These files should be included by other *.c
-					files and should not generate object.
-
-	<name>.h		Header file that user applications are expected to include
-					in order to make use of the library
-
-	<name>_inline.h Header files containing inline static functions that the
-					user application is expected to include.
-
-	<name>_private.h Header file meant only to be included by the package.
-
-Further, as this code is used to generate libraries which make use of different
-transport mechanisms, there are some modules which are specific to the
-underlying transport being used.  The original code supported both Nanomsg and
-NNG, however Nanomsg has been phased out (starting with 1.0.45).  File naming
-convention for modules which are transport specific originally included a
-suffix (e.g. _nng), however as the directory structure was reorganised, and
-transport specific directories, plus a common directory, have been created,
-the need for the suffix has been eliminated (existing files were not changed).
+The directories at the root level are as follows, each contains its own readme
+file where additional details are necessary.
 
 
-External Names
-All externally facing function names and constants will start with rmr_ or
-RMR_ respectively (RIC Message Router).    For the time being, there is a
-set of mappings from the old uta_* names to rmr_* names. The user code must
-define UTA_COMPAT to have these enabled.
+ci		This directory contains the continuous integration scripts needed
+		to build and verify RMR when changes are made and committed to the repo.
 
-Internal Names
-Internal (static) functions have no mandated convention. There are some
-names which are prefixed with uta_.  These are left over from the original
-prototype library which had the name Uta.  The uta_ prefixes were mostly on
-functions which were initially external, but were pulled back for this release.
+doc		RMR documentation is written in a document language and thus is
+		source code.  This directory contains the source for all generated
+		documentation.
 
+docs	This is a 'canned' directory which is intended to be scraped. Direct
+		editing of documentation files in this directory is dangerous as
+		most of the files, even though checked into the repo per mandate,
+		are artifacts and will be overlaid if hand edited.
 
+examples This directory contains example programmes which illustrate the use
+		of RMR.
 
-Requirements
-To build the RMR libraries, NNG must be installed, or the external references
-in the source tree must be used to pull and build the NNG library. It might
-be necessary to alter the values of C_INCLUDE_PATH,  LD_LIBRARY_PATH, or
-LIBRARY_PATH to reflect the installation location when the installed version
-of NNG is being used.
+ext		RMR makes use of NNG (next generation Nanomsg). The ext directory is
+		the git reference allowing the NNG code to be pulled and built as
+		a reference.
 
-To install see the instructions on their html sites:
-	https://github.com/nanomsg/nng
+src		This directory is the top level source directory containing both the
+		core RMR code, and any bindings which have been written.
 
-The default CMake build will not require NNG to be installed, and this is the
-easiest way to build.
-
-Unit Testing
-The script ../test/unit_test.ksh should be used for running unit tests. With no
-parameters it will attempt to build any file in this directory which has the
-name *_test.c.  Build is attempted with either mk or make and enables the
-necessary compiler flags to support coverage output (gcov).  Once built, the
-test program is executed and if the return code is success (0), the
-coverage data is interpreted.
-
-The test programs may make use of ../test/tools.c which provide simple
-validation check functions.  These programs should also directly include
-the module(s) under test.  This ensures that they are not linked, and are
-compiled with the proper coverage flags. In addition, it allows modules that
-are not under test to be linked from the archive and (most importantly) not
-reported on from a coverage perspective. In cases where two modules depend on
-each other, and are static functions, they will need to be tested from a single
-unit test program (see the rt_tool test program).
-
-It might be necessary to write a higher level test driver as some of the modules
-(e.g. route table) have threaded daemons which might not be easy to drive
-completely or at all, and thus the code coverage for a passing test might need
-to be lower for this type of module.
-
-Containerized Build
-The Dockerfile defines an environment to build and test this library.  It uses
-a base image with the C toolchain.  The Dockerfile is NOT intended to create a
-distributable image.
+test	All unit and application level tests for the core library are kept
+		within this directory.  Tests for bindings are managed within the
+		binding's directory under the source directory.
diff --git a/doc/README b/doc/README
index ea47501..d8f0a8b 100644
--- a/doc/README
+++ b/doc/README
@@ -1,8 +1,8 @@
 
-Documentation for RMr.
+Documentation for RMR.
 
-Most (all?) documentation for RMr is built from source ({X)fm, or other text
-formatter source, not the RMr code) rather than hand editing the output 
+Most (all?) documentation for RMR is built from source ({X)fm, or other text
+formatter source, not the RMR code) rather than hand editing the output 
 (markdown/rst) files.  This allows for more control over the output, a wider 
 variety of output types, and (most importantly) the generation of multiple 
 output from the same source (e.g. man pages can be rendered in troff which 
@@ -10,8 +10,9 @@
 wikis prefer, and as PDF which can be easily distributed).
 
 Thus, there is a source file below this directory which has the document
-source.  There may also be an output directory at this level. If necessary, 
-the output directory will contain generated documents (.rst files?) which for
-some odd reason need to also be committed to the repo (I don't commit binaries
-so I'm having a difficult time sorting out the reason why these generated files
-might be committed).
+source.  Directories are as follows:
+
+	man		Manual pages included with the development package
+
+	rtd		Source to generate the .rst files for the "read the docs"
+			repo scraper.
diff --git a/doc/src/man/rmr.7.xfm b/doc/src/man/rmr.7.xfm
index 26738e1..2f2e47d 100644
--- a/doc/src/man/rmr.7.xfm
+++ b/doc/src/man/rmr.7.xfm
@@ -73,34 +73,8 @@
 The following is a list of the various environment variables, what they control
 and the defaults which RMr uses if undefined.
 
-&beg_dlist(.75i : ^&bold_font )
-&di(RMR_ASYNC_CONN) Allows the asynch connection mode to be turned off (by setting the
-	value to 0. When set to 1, or missing from the environment, RMR will invoke the
-	connection interface in the transport mechanism using the non-blocking (asynch)
-	mode.  This will likely result in many "soft failures" (retry) until the connection
-	is established, but allows the application to continue unimpeeded should the
-	connection be slow to set up.
-
-&di(RMR_BIND_IF) This provides the interface that RMr will bind listen ports to allowing
-	for a single interface to be used rather than listening across all interfaces.
-	This should be the IP address assigned to the interface that RMr should listen
-	on, and if not defined RMr will listen on all interfaces.
-
-&di(RMR_RTG_SVC) RMr opens a TCP listen socket using the port defined by this
-	environment variable and expects that the route table generator process
-	will connect to this port.
-	If not supplied the port 4561 is used.
-
-&di(RMR_RTG_ISRAW) Is set to 1 if the route table generator is sending "plain" messages
-	(not using RMr to send messages, 0 if the rtg is using RMr to send. The default
-	is 1 as we don't expect the rtg to use RMr.
-
-&di(RMR_SEED_RT) This is used to supply a static route table which can be used for
-	debugging, testing, or if no route table generator process is being used to
-	supply the route table.
-	If not defined, no static table is used and RMr will not report &ital(ready)
-	until a table is received.
-&end_dlist
+.** the list of environment vars supported
+.im &{lib}/man/env_var_list.im
 
 
 &h2(SEE ALSO )
@@ -135,4 +109,3 @@
 .ju on
 
 
-.qu
diff --git a/doc/src/man/rmr_alloc_msg.3.xfm b/doc/src/man/rmr_alloc_msg.3.xfm
index 5377871..ed814b8 100644
--- a/doc/src/man/rmr_alloc_msg.3.xfm
+++ b/doc/src/man/rmr_alloc_msg.3.xfm
@@ -70,7 +70,7 @@
 
 &space
 &beg_dlist(.75i : ^&bold_font )
-&ditem(state)  Is the current buffer state.  Following a call to &cw(rmr_send_msg)
+&diitem(state)  Is the current buffer state.  Following a call to &cw(rmr_send_msg)
 the state indicates whether the buffer was successfully sent which determines
 exactly what the payload points to.  If the send failed, the payload referenced
 by the buffer is the message that failed to send (allowing the application to
@@ -79,14 +79,14 @@
 may fill in in preparation to send.
 
 &half_space
-&ditem(mtype)  When sending a message, the application is expected to set this field
+&diitem(mtype)  When sending a message, the application is expected to set this field
 to the appropriate message type value (as determined by the user programme). Upon send
 this value determines how the RMR library will route the message.
 For a buffer which has been received, this field will contain the message type that was
 set by the sending application.
 
 &half_space
-&ditem(len) The application using a buffer to send a message is expected to set the
+&diitem(len) The application using a buffer to send a message is expected to set the
 length value to the actual number of bytes that it placed into the message. This
 is likely less than the total number of bytes that the message can carry.
 For a message buffer that is passed to the application as the result of a receive
@@ -94,7 +94,7 @@
 indicate the number of bytes in the payload which are valid.
 
 &half_space
-&ditem(payload) The payload is a pointer to the actual received data.  The
+&diitem(payload) The payload is a pointer to the actual received data.  The
 user programme may read and write from/to the memory referenced by the payload
 up until the point in time that the buffer is used on a &cw(rmr_send, rmr_call)
 or &cw(rmr_reply) function call.
@@ -103,7 +103,7 @@
 
 
 &half_space
-&ditem(xaction) The &ital(xaction) field is a pointer to a fixed sized area in
+&diitem(xaction) The &ital(xaction) field is a pointer to a fixed sized area in
 the message into which the user may write a transaction ID.
 The ID is optional with the exception of when the user application uses the &cw(rmr_call)
 function to send a message and wait for the reply; the underlying RMR processing
@@ -112,7 +112,7 @@
 &end_dlist
 
 &half_space
-&ditem(sub_id)
+&diitem(sub_id)
 This value is the subscription ID. It, in combination with the message type is used
 by rmr to determine the target endpoint when sending a message.
 If the application to application protocol does not warrant the use of a subscription
@@ -121,7 +121,7 @@
 application's responsibility to set/reset this value.
 
 &half_space
-&ditem(tp_state)
+&diitem(tp_state)
 For C applications making use of RMR, the state of a transport based failure will
 often be available via &cw(errno.)
 However, some wrapper environments may not have direct access to the C-lib &cw(errno)
@@ -131,6 +131,7 @@
 User applications are strongly cautioned against relying on the value of errno as
 some transport mechanisms may not set this value on all calls.
 This value should also be ignored any time the message status is &cw(RMR_OK.)
+&end_dlist
 
 &h2(RETURN VALUE)
 The function returns a pointer to a &cw(rmr_mbuf) structure, or NULL on error.
@@ -163,5 +164,3 @@
 rmr_ring_free(3),
 rmr_set_trace(3)
 
-.qu
-
diff --git a/doc/src/man/rmr_bytes2meid.3.xfm b/doc/src/man/rmr_bytes2meid.3.xfm
index 0699cdf..86cee72 100644
--- a/doc/src/man/rmr_bytes2meid.3.xfm
+++ b/doc/src/man/rmr_bytes2meid.3.xfm
@@ -94,7 +94,3 @@
 rmr_wh_open(3),
 rmr_wh_send_msg(3)
 
-
-
-.qu
-
diff --git a/doc/src/man/rmr_bytes2payload.3.xfm b/doc/src/man/rmr_bytes2payload.3.xfm
index b9412a8..74bc4fc 100644
--- a/doc/src/man/rmr_bytes2payload.3.xfm
+++ b/doc/src/man/rmr_bytes2payload.3.xfm
@@ -84,7 +84,3 @@
 rmr_wh_open(3),
 rmr_wh_send_msg(3)
 
-
-
-.qu
-
diff --git a/doc/src/man/rmr_bytes2xact.3.xfm b/doc/src/man/rmr_bytes2xact.3.xfm
index 2f62a5f..b7b79e5 100644
--- a/doc/src/man/rmr_bytes2xact.3.xfm
+++ b/doc/src/man/rmr_bytes2xact.3.xfm
@@ -92,8 +92,3 @@
 rmr_str2meid(3),
 rmr_wh_open(3),
 rmr_wh_send_msg(3)
-
-
-
-.qu
-
diff --git a/doc/src/man/rmr_call.3.xfm b/doc/src/man/rmr_call.3.xfm
index edd8a5b..592544f 100644
--- a/doc/src/man/rmr_call.3.xfm
+++ b/doc/src/man/rmr_call.3.xfm
@@ -173,6 +173,3 @@
 rmr_ring_free(3)
 .ju on
 
-
-.qu
-
diff --git a/doc/src/man/rmr_close.3.xfm b/doc/src/man/rmr_close.3.xfm
index 3fe439c..469c993 100644
--- a/doc/src/man/rmr_close.3.xfm
+++ b/doc/src/man/rmr_close.3.xfm
@@ -54,6 +54,7 @@
 
 
 &h2(SEE ALSO )
+.ju off
 rmr_alloc_msg(3),
 rmr_call(3),
 rmr_free_msg(3),
@@ -71,7 +72,4 @@
 rmr_ring_free(3),
 rmr_wh_open(3),
 rmr_wh_send_msg(3)
-
-
-.qu
-
+.ju on
diff --git a/doc/src/man/rmr_free_msg.3.xfm b/doc/src/man/rmr_free_msg.3.xfm
index 5c0fd91..2f18b73 100644
--- a/doc/src/man/rmr_free_msg.3.xfm
+++ b/doc/src/man/rmr_free_msg.3.xfm
@@ -56,6 +56,7 @@
 
 
 &h2(SEE ALSO )
+.ju off
 rmr_alloc_msg(3),
 rmr_call(3),
 rmr_init(3),
@@ -70,7 +71,5 @@
 rmr_tokenise(3),
 rmr_mk_ring(3),
 rmr_ring_free(3)
-
-
-.qu
+.ju on
 
diff --git a/doc/src/man/rmr_get_meid.3.xfm b/doc/src/man/rmr_get_meid.3.xfm
index bcf7ce0..3980542 100644
--- a/doc/src/man/rmr_get_meid.3.xfm
+++ b/doc/src/man/rmr_get_meid.3.xfm
@@ -97,6 +97,3 @@
 rmr_wh_send_msg(3)
 .ju on
 
-
-.qu
-
diff --git a/doc/src/man/rmr_get_rcvfd.3.xfm b/doc/src/man/rmr_get_rcvfd.3.xfm
index 54cc515..9ed86b8 100644
--- a/doc/src/man/rmr_get_rcvfd.3.xfm
+++ b/doc/src/man/rmr_get_rcvfd.3.xfm
@@ -119,6 +119,7 @@
 &ex_end
 
 &h2(SEE ALSO )
+.ju off
 rmr_alloc_msg(3),
 rmr_call(3),
 rmr_free_msg(3),
@@ -133,7 +134,5 @@
 rmr_tokenise(3),
 rmr_mk_ring(3),
 rmr_ring_free(3)
-
-
-.qu
+.ju on
 
diff --git a/doc/src/man/rmr_get_src.3.xfm b/doc/src/man/rmr_get_src.3.xfm
index 98ec5a5..c46a2a5 100644
--- a/doc/src/man/rmr_get_src.3.xfm
+++ b/doc/src/man/rmr_get_src.3.xfm
@@ -97,6 +97,3 @@
 rmr_wh_send_msg(3)
 .ju on
 
-
-.qu
-
diff --git a/doc/src/man/rmr_get_srcip.3.xfm b/doc/src/man/rmr_get_srcip.3.xfm
index 7db7efe..489d1e5 100644
--- a/doc/src/man/rmr_get_srcip.3.xfm
+++ b/doc/src/man/rmr_get_srcip.3.xfm
@@ -98,6 +98,3 @@
 rmr_wh_send_msg(3)
 .ju on
 
-
-.qu
-
diff --git a/doc/src/man/rmr_get_trace.3.xfm b/doc/src/man/rmr_get_trace.3.xfm
index 21c0285..69f48cf 100644
--- a/doc/src/man/rmr_get_trace.3.xfm
+++ b/doc/src/man/rmr_get_trace.3.xfm
@@ -86,6 +86,3 @@
 rmr_trace_ref(3)
 .ju on
 
-
-.qu
-
diff --git a/doc/src/man/rmr_get_trlen.3.xfm b/doc/src/man/rmr_get_trlen.3.xfm
index 770935c..507c8c6 100644
--- a/doc/src/man/rmr_get_trlen.3.xfm
+++ b/doc/src/man/rmr_get_trlen.3.xfm
@@ -57,6 +57,7 @@
 
 
 &h2(SEE ALSO )
+.ju off
 rmr_alloc_msg(3),
 rmr_call(3),
 rmr_free_msg(3),
@@ -75,7 +76,5 @@
 rmr_ring_free(3),
 rmr_set_trace(3),
 rmr_tralloc_msg(3)
-
-
-.qu
+.ju on
 
diff --git a/doc/src/man/rmr_get_xact.3.xfm b/doc/src/man/rmr_get_xact.3.xfm
index cb924a5..8674702 100644
--- a/doc/src/man/rmr_get_xact.3.xfm
+++ b/doc/src/man/rmr_get_xact.3.xfm
@@ -97,6 +97,3 @@
 rmr_wh_send_msg(3)
 .ju on
 
-
-.qu
-
diff --git a/doc/src/man/rmr_init.3.xfm b/doc/src/man/rmr_init.3.xfm
index 3871d03..488e6d2 100644
--- a/doc/src/man/rmr_init.3.xfm
+++ b/doc/src/man/rmr_init.3.xfm
@@ -62,16 +62,16 @@
 
 &half_space
 &beg_dlist(1i : &bold_font )
-&ditem(RMRFL_NONE) 
+&diitem(RMRFL_NONE) 
 	No flags are set.
 
 &half_space
-&ditem(RMRFL_NOTHREAD)
+&diitem(RMRFL_NOTHREAD)
 	The route table collector thread is not to be started. This should only be used
 	by the route table generator application if it is based on RMr.
 
 &half_space
-&ditem(RMRFL_MTCALL)
+&diitem(RMRFL_MTCALL)
 	Enable multi-threaded call support. 
 &end_dlist
 
@@ -103,7 +103,7 @@
 &half_space 
 
 &beg_dlist(1i : &bold_font )
-&ditem(RMR_SEED_RT) 
+&diitem(RMR_SEED_RT) 
 Assumes this is the filename of the seed route table file to use. In normal situations,
 the library will wait for an update from the route table generator (expected within a few seconds
 of initialisation) before being able to send messages.
@@ -111,7 +111,7 @@
 supply it to the library.
 &half_space
 
-&ditem(RMR_RTG_SVC) 
+&diitem(RMR_RTG_SVC) 
 The route table generator assumes that RMr is listening on a well known port (4561) by 
 default, but this environment variable can be used to change the listening port if 
 needed. 
@@ -142,6 +142,7 @@
 &ex_end
 
 &h2(SEE ALSO )
+.ju off
 rmr_alloc_msg(3),
 rmr_call(3),
 rmr_free_msg(3),
@@ -159,7 +160,5 @@
 rmr_tokenise(3),
 rmr_mk_ring(3),
 rmr_ring_free(3)
-
-
-.qu
+.ju on
 
diff --git a/doc/src/man/rmr_init_trace.3.xfm b/doc/src/man/rmr_init_trace.3.xfm
index b6e534b..f31baf0 100644
--- a/doc/src/man/rmr_init_trace.3.xfm
+++ b/doc/src/man/rmr_init_trace.3.xfm
@@ -69,6 +69,7 @@
 RMr context (void *) passed to this function was not valid.
 
 &h2(SEE ALSO )
+.ju off
 rmr_alloc_msg(3),
 rmr_tr_alloc_msg(3),
 rmr_call(3),
@@ -88,7 +89,5 @@
 rmr_mk_ring(3),
 rmr_ring_free(3),
 rmr_set_trace(3)
-
-
-.qu
+.ju on
 
diff --git a/doc/src/man/rmr_mt_call.3.xfm b/doc/src/man/rmr_mt_call.3.xfm
index ecb65ca..76d209f 100644
--- a/doc/src/man/rmr_mt_call.3.xfm
+++ b/doc/src/man/rmr_mt_call.3.xfm
@@ -208,6 +208,3 @@
 rmr_ring_free(3)
 .ju on
 
-
-.qu
-
diff --git a/doc/src/man/rmr_mt_rcv.3.xfm b/doc/src/man/rmr_mt_rcv.3.xfm
index 8be015a..d5c31b2 100644
--- a/doc/src/man/rmr_mt_rcv.3.xfm
+++ b/doc/src/man/rmr_mt_rcv.3.xfm
@@ -194,6 +194,3 @@
 rmr_torcv_msg(3)
 .ju on
 
-
-.qu
-
diff --git a/doc/src/man/rmr_payload_size.3.xfm b/doc/src/man/rmr_payload_size.3.xfm
index 9e8bf1c..e4c0d97 100644
--- a/doc/src/man/rmr_payload_size.3.xfm
+++ b/doc/src/man/rmr_payload_size.3.xfm
@@ -58,6 +58,7 @@
 
 
 &h2(SEE ALSO )
+.ju off
 rmr_alloc_msg(3),
 rmr_call(3),
 rmr_free_msg(3),
@@ -72,7 +73,4 @@
 rmr_tokenise(3),
 rmr_mk_ring(3),
 rmr_ring_free(3)
-
-
-.qu
-
+.ju on
diff --git a/doc/src/man/rmr_rcv_msg.3.xfm b/doc/src/man/rmr_rcv_msg.3.xfm
index 6b0c40c..b67b4bb 100644
--- a/doc/src/man/rmr_rcv_msg.3.xfm
+++ b/doc/src/man/rmr_rcv_msg.3.xfm
@@ -112,6 +112,3 @@
 rmr_torcv_msg(3)
 .ju on
 
-
-.qu
-
diff --git a/doc/src/man/rmr_ready.3.xfm b/doc/src/man/rmr_ready.3.xfm
index 61ea2f8..9f0a2cd 100644
--- a/doc/src/man/rmr_ready.3.xfm
+++ b/doc/src/man/rmr_ready.3.xfm
@@ -70,6 +70,3 @@
 rmr_ring_free(3)
 .ju on
 
-
-.qu
-
diff --git a/doc/src/man/rmr_realloc_payload.3.xfm b/doc/src/man/rmr_realloc_payload.3.xfm
index 193d549..f745be3 100644
--- a/doc/src/man/rmr_realloc_payload.3.xfm
+++ b/doc/src/man/rmr_realloc_payload.3.xfm
@@ -134,6 +134,3 @@
 rmr_ring_free(3)
 .ju on
 
-
-.qu
-
diff --git a/doc/src/man/rmr_rts_msg.3.xfm b/doc/src/man/rmr_rts_msg.3.xfm
index 015c03c..dfdbab1 100644
--- a/doc/src/man/rmr_rts_msg.3.xfm
+++ b/doc/src/man/rmr_rts_msg.3.xfm
@@ -152,6 +152,3 @@
 rmr_ring_free(3)
 .ju on
 
-
-.qu
-
diff --git a/doc/src/man/rmr_send_msg.3.xfm b/doc/src/man/rmr_send_msg.3.xfm
index 9d9b625..d9cc620 100644
--- a/doc/src/man/rmr_send_msg.3.xfm
+++ b/doc/src/man/rmr_send_msg.3.xfm
@@ -182,6 +182,3 @@
 rmr_wh_send_msg(3)
 .ju on
 
-
-.qu
-
diff --git a/doc/src/man/rmr_set_stimeout.3.xfm b/doc/src/man/rmr_set_stimeout.3.xfm
index b8747d2..ca091ac 100644
--- a/doc/src/man/rmr_set_stimeout.3.xfm
+++ b/doc/src/man/rmr_set_stimeout.3.xfm
@@ -110,7 +110,3 @@
 rmr_torcv_rcv(3),
 rmr_wh_send_msg(3)
 .ju on
-
-
-.qu
-
diff --git a/doc/src/man/rmr_set_trace.3.xfm b/doc/src/man/rmr_set_trace.3.xfm
index bb9a1f4..0fb4955 100644
--- a/doc/src/man/rmr_set_trace.3.xfm
+++ b/doc/src/man/rmr_set_trace.3.xfm
@@ -57,6 +57,7 @@
 
 
 &h2(SEE ALSO )
+.ju off
 rmr_alloc_msg(3),
 rmr_tralloc_msg(3),
 rmr_bytes2xact(3),
@@ -84,8 +85,4 @@
 rmr_str2xact(3),
 rmr_wh_open(3),
 rmr_wh_send_msg(3)
-
-
-
-.qu
-
+.ju on
diff --git a/doc/src/man/rmr_str2meid.3.xfm b/doc/src/man/rmr_str2meid.3.xfm
index 1b741a4..5d336b6 100644
--- a/doc/src/man/rmr_str2meid.3.xfm
+++ b/doc/src/man/rmr_str2meid.3.xfm
@@ -93,5 +93,4 @@
 rmr_wh_open(3),
 rmr_wh_send_msg(3)
 .ju on
-.qu
 
diff --git a/doc/src/man/rmr_str2xact.3.xfm b/doc/src/man/rmr_str2xact.3.xfm
index 06ec74d..6f6046f 100644
--- a/doc/src/man/rmr_str2xact.3.xfm
+++ b/doc/src/man/rmr_str2xact.3.xfm
@@ -1,4 +1,3 @@
-
 .if false
 ==================================================================================
 	Copyright (c) 2019 Nokia 
@@ -72,6 +71,7 @@
 
 
 &h2(SEE ALSO )
+.ju off
 rmr_alloc_msg(3),
 rmr_bytes2meid(3),
 rmr_bytes2xact(3),
@@ -94,5 +94,5 @@
 rmr_str2meid(3),
 rmr_wh_open(3),
 rmr_wh_send_msg(3)
-.qu
+.ju on
 
diff --git a/doc/src/man/rmr_support.3.xfm b/doc/src/man/rmr_support.3.xfm
index 29a228a..ca73298 100644
--- a/doc/src/man/rmr_support.3.xfm
+++ b/doc/src/man/rmr_support.3.xfm
@@ -141,7 +141,3 @@
 rmr_rts_msg(3),
 rmr_ready(3),
 .ju on
-
-
-.qu
-
diff --git a/doc/src/man/rmr_torcv_msg.3.xfm b/doc/src/man/rmr_torcv_msg.3.xfm
index ffe26dc..d160f53 100644
--- a/doc/src/man/rmr_torcv_msg.3.xfm
+++ b/doc/src/man/rmr_torcv_msg.3.xfm
@@ -135,6 +135,3 @@
 rmr_ring_free(3)
 .ju on
 
-
-.qu
-
diff --git a/doc/src/man/rmr_trace_ref.3.xfm b/doc/src/man/rmr_trace_ref.3.xfm
index fc3e213..8b0fb9b 100644
--- a/doc/src/man/rmr_trace_ref.3.xfm
+++ b/doc/src/man/rmr_trace_ref.3.xfm
@@ -83,7 +83,3 @@
 rmr_wh_send_msg(3),
 rmr_set_trace(3)
 .ju on
-
-
-.qu
-
diff --git a/doc/src/man/rmr_tralloc_msg.3.xfm b/doc/src/man/rmr_tralloc_msg.3.xfm
index 0f26cf1..da7ac6b 100644
--- a/doc/src/man/rmr_tralloc_msg.3.xfm
+++ b/doc/src/man/rmr_tralloc_msg.3.xfm
@@ -77,7 +77,7 @@
 
 &space
 &beg_dlist(.75i : ^&bold_font )
-&ditem(state )  Is the current buffer state.  Following a call to &cw(rmr_send_msg) 
+&diitem(state )  Is the current buffer state.  Following a call to &cw(rmr_send_msg) 
 the state indicates whether the buffer was successfully sent which determines
 exactly what the payload points to.  If the send failed, the payload referenced
 by the buffer is the message that failed to send (allowing the application to 
@@ -86,14 +86,14 @@
 may fill in in preparation to send.
 
 &half_space
-&ditem(mtype )  When sending a message, the application is expected to set this field
+&diitem(mtype )  When sending a message, the application is expected to set this field
 to the appropriate message type value (as determined by the user programme). Upon send
 this value determines how the a library will route the message.
 For a buffer which has been received, this field will contain the message type that was
 set by the sending application. 
 
 &half_space
-&ditem(len ) The application using a buffer to send a message is expected to set the
+&diitem(len ) The application using a buffer to send a message is expected to set the
 length value to the actual number of bytes that it placed into the message. This
 is likely less than the total number of bytes that the message can carry.
 For a message buffer that is passed to the application as the result of a receive
@@ -101,7 +101,7 @@
 indicate the number of bytes in the payload which are valid.
 
 &half_space
-&ditem(payload ) The payload is a pointer to the actual received data.  The
+&diitem(payload ) The payload is a pointer to the actual received data.  The
 user programme may read and write from/to the memory referenced by the payload
 up until the point in time that the buffer is used on a &cw(rmr_send, rmr_call)
 or &cw(rmr_reply) function call.  
@@ -110,7 +110,7 @@
 
 
 &half_space
-&ditem(xaction) The &ital(xaction) field is a pointer to a fixed sized area in 
+&diitem(xaction) The &ital(xaction) field is a pointer to a fixed sized area in 
 the message into which the user may write a transaction ID.  
 The ID is optional with the exception of when the user application uses the &cw(rmr_call)
 function to send a message and wait for the reply; the underlying a processing
@@ -129,6 +129,7 @@
 .** &h2(EXAMPLE)
 
 &h2(SEE ALSO )
+.ju off
 rmr_alloc_msg(3),
 rmr_mbuf(3)
 rmr_call(3),
@@ -149,7 +150,5 @@
 rmr_mk_ring(3),
 rmr_ring_free(3),
 rmr_set_trace(3)
-
-
-.qu
+.ju on
 
diff --git a/doc/src/man/rmr_wh_close.3.xfm b/doc/src/man/rmr_wh_close.3.xfm
index e122a28..fbd94cf 100644
--- a/doc/src/man/rmr_wh_close.3.xfm
+++ b/doc/src/man/rmr_wh_close.3.xfm
@@ -56,6 +56,7 @@
 
 
 &h2(SEE ALSO )
+.ju off
 rmr_alloc_msg(3),
 rmr_call(3),
 rmr_free_msg(3),
@@ -74,6 +75,4 @@
 rmr_wh_open(3),
 rmr_wh_send_msg(3)
 
-
-.qu
-
+.ju on
diff --git a/doc/src/man/rmr_wh_open.3.xfm b/doc/src/man/rmr_wh_open.3.xfm
index 417a7de..5b26cf3 100644
--- a/doc/src/man/rmr_wh_open.3.xfm
+++ b/doc/src/man/rmr_wh_open.3.xfm
@@ -97,6 +97,7 @@
 &ex_end
 
 &h2(SEE ALSO )
+.ju off
 rmr_alloc_msg(3),
 rmr_call(3),
 rmr_free_msg(3),
@@ -114,7 +115,4 @@
 rmr_ring_free(3),
 rmr_wh_send_msg(3),
 rmr_wh_close(3)
-
-
-.qu
-
+.ju on
diff --git a/doc/src/man/rmr_wh_send_msg.3.xfm b/doc/src/man/rmr_wh_send_msg.3.xfm
index 460d9cb..bebc110 100644
--- a/doc/src/man/rmr_wh_send_msg.3.xfm
+++ b/doc/src/man/rmr_wh_send_msg.3.xfm
@@ -191,6 +191,3 @@
 rmr_wh_close(3)
 .ju on
 
-
-.qu
-
diff --git a/doc/src/man/setup.im b/doc/src/man/setup.im
index 546dfa1..fbd95fe 100644
--- a/doc/src/man/setup.im
+++ b/doc/src/man/setup.im
@@ -27,6 +27,8 @@
 .fi
 
 
+.if  ! _setup_im 
+
 .gv e LIB lib
 .if ! lib
 	.dv lib ..
@@ -50,4 +52,6 @@
 		.im &{lib}/roff.im
 	.fi
 .fi
-.xx 0
+
+.dv _setup_im 1
+.fi
diff --git a/doc/src/rst.im b/doc/src/rst.im
index b35a68f..ebbbefe 100644
--- a/doc/src/rst.im
+++ b/doc/src/rst.im
@@ -41,7 +41,7 @@
 	.** and of course they don't generate <hx> tags in the resulting HTML, but <section> tags. WTF?
 	.dv h1 .sp 1 $1 .br ============================================================================================ .sp 1
 	.dv h2 .sp 1 $1 .br -------------------------------------------------------------------------------------------- .sp 1
-	.dv h3 .sp 1 $1 .br ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .sp 1
+	.dv h3 .sp 1 $1 .br ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .sp 1
 	.dv h4 **$1**
 	.** .dv h1 === $1 .br ===  .sp 1
 	.** .dv h2 === $1 .br === .sp 1
@@ -69,12 +69,13 @@
 	.dv beg_list .sp 1 .dv lic $1 ^:
 	.dv end_list .sp 1
 
-	.dv beg_dlist .sp 1 
-	.dv end_dlist .br .in 0i
+	.dv beg_dlist .sp 1  .ll -3
+	.dv end_dlist .br .in 0i .ll +3
 
 	.** for now we allow only a single layer of defitems
-	.dv di .in 0i .br  $1 .br .in +.25i
-	.dv diitem .in 0i .br  $1 .br .in +.25i
+	.dv di     .in 0i .br  $1 .br .in +3
+	.** .dv diitem .in 0i .br  $1 .br .in +.25i
+	.dv diitem .in 0i .br  $1 .br .in +3
 	.dv item .br &lic
 	.dv li .br &lic
 	
diff --git a/doc/src/rtd/Makefile b/doc/src/rtd/Makefile
new file mode 100644
index 0000000..7e49946
--- /dev/null
+++ b/doc/src/rtd/Makefile
@@ -0,0 +1,62 @@
+# vim: ts=4 noet sw=4:
+#==================================================================================
+#	Copyright (c) 2019 Nokia
+#	Copyright (c) 2018-2019 AT&T Intellectual Property.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#==================================================================================
+
+# This is a stand-alone make file as the RTD documentation is NOT built and packaged
+# with the normal CMake process and thus isn't covered in the CMake files.
+
+# {X}fm is required to compile the source. 
+
+
+%.rst:: %.xfm
+	OUTPUT_TYPE=rst tfm $< | sed 's/^ //' >$@
+
+%.ps:: %.xfm
+	OUTPUT_TYPE=ps pfm $< $@
+
+%.txt:: %.xfm
+	OUTPUT_TYPE=txt tfm $< $@
+
+%.md:: %.xfm
+	OUTPUT_TYPE=markdown tfm $<  | sed 's/^ //' >$@
+
+docs = config-deploy developer-guide user-guide rel-notes overview
+
+all:: $(docs:%=%.rst) $(docs:%=%.txt) $(docs:%=%.md) 
+	echo ">>> rm rel-notes.xfm"
+
+rel-notes.xfm:
+	ksh fmt_changes.ksh >rel-notes.xfm
+
+# copy the .rst files which have changed into the docs (plural) directory at the root of the repo
+publish : $(docs:%=%.rst)
+	for f in *.rst;\
+	do\
+		if ! diff -N -q $$f ../../../docs/$$f >/dev/null 2>&1;\
+		then\
+			cp -p $$f ../../../docs/;\
+		fi;\
+	done
+
+# ditch any intermediate files
+clean:
+	rm -f rel-notes.xfm *.sp *.ca
+
+# ditch anything that can be rebuilt
+nuke: clean
+	rm -f *.ps *.pdf *.rst *.md
+
diff --git a/doc/src/rtd/README b/doc/src/rtd/README
new file mode 100644
index 0000000..b6f4acd
--- /dev/null
+++ b/doc/src/rtd/README
@@ -0,0 +1,17 @@
+
+This directory contains source for the project mandated "read the docs"
+.rst documentation.  The Makefile will both build the doc from the source
+here and "install" it into the docs directory at the repo root.  While 
+it is not good practice, the generated .rst files must be checked into
+the repo and committed with changes to the source.  
+
+The command 'make all' should be all that is needed to build the 
+rtd documentation.
+
+Rationale
+Documentation is just code, and by maintaining the documentation as
+source is is possible to generate various forms of output with a 
+single make.  While it is possible to convert X to Y, a true document
+composition language is far better at geneating readable Postscript
+output with embedded figures as well as text and tables. 
+
diff --git a/doc/src/rtd/config-deploy.xfm b/doc/src/rtd/config-deploy.xfm
new file mode 100644
index 0000000..654225f
--- /dev/null
+++ b/doc/src/rtd/config-deploy.xfm
@@ -0,0 +1,51 @@
+.** vim: ts=4 noet sw=4:
+.if false
+==================================================================================
+	Copyright (c) 2019 Nokia
+	Copyright (c) 2018-2019 AT&T Intellectual Property.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================================
+.fi
+
+
+.if false
+	Mnemonic:	config-deploy.xfm
+	Abstract:	Source to generate a configuration delployment guide.
+	Date:		6 November 2019
+	Author:		E. Scott Daniels
+.fi
+
+.im setup.im
+
+&h1(RMR Configuration and Delpoyment)
+
+The RIC Message Router (RMR) is a library which applications use to send and receive
+messages where the message routing, endpoint selection, is based on the message type 
+rather than on traditional DNS names or IP addresses. 
+This document contains information regarding the configuration of RMR when it is
+embedded by a &ital(user application).  
+RMR itself is not a deployable entity.
+
+&h2(Configuration)
+Several aspects of RMR behaviour is controlled via environment variables which are 
+set at the time that a user application invokes the RMR initialisation function.
+This allows these variables to be set before the application is started as a 
+function of the true environment, or set by the application as a means for the 
+application to influence RMR's behaviour. 
+The following is a list of RMR variables which RMR recognises (see the main
+RMR manual page in the development package for more details).
+
+
+.** use the same list which is used in the manual pages
+.im &{lib}/man/env_var_list.im
diff --git a/doc/src/rtd/developer-guide.xfm b/doc/src/rtd/developer-guide.xfm
new file mode 100644
index 0000000..3cf3bb8
--- /dev/null
+++ b/doc/src/rtd/developer-guide.xfm
@@ -0,0 +1,97 @@
+.** vim: ts=4 noet sw=4:
+.if false
+==================================================================================
+	Copyright (c) 2019 Nokia
+	Copyright (c) 2018-2019 AT&T Intellectual Property.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================================
+.fi
+
+
+.if false
+	Mnemonic:	config-deploy.xfm
+	Abstract:	Source to generate a configuration deployment guide.
+	Date:		6 November 2019
+	Author:		E. Scott Daniels
+.fi
+
+.im setup.im
+
+&h1(RMR Developer Guide)
+
+The RIC Message Router (RMR) is a library which applications use to send and receive
+messages where the message routing, endpoint selection, is based on the message type 
+rather than on traditional DNS names or IP addresses. 
+This document contains information that potential developers might need to know 
+in order to contribute to the project
+
+&h2(Language)
+RMR is written in C, and thus a contributing developer to the core library should 
+have an excellent working knowledge of C.
+There currently is one set of cross languages bindings supporting Python, and a
+developer wishing to contribute to the bindings source should be familiar with 
+Python (version 3.7+) and with the Python &ital(ctypes) library.
+
+&h2(Code Structure)
+RMR is designed to provide an insulation layer between user applications and 
+the actual transport mechanism.  
+Initially RMR was built on top of Nanosmg, and shortly after was ported to NNG
+(Nanomsg Next Generation).  
+Because RMR presents the same API to the user application regardless of the underlying
+transport library, the resulting output when compiling RMR is a transport specific
+library. 
+As an example, &cw(librmr_nng.a) is the library generated for use with the NNG
+transport.
+&space
+
+As such the library source is organised into multiple components:
+
+&beg_dlist(.75i : ^&bold_font )
+
+&di(common) Source in the common directory is agnostic to the underlying transport
+	mechanism (Nanomsg or NNG), and thus can be used when generating either library.
+
+&di(nano) Source which is tightly coupled with the underlying Nanomsg library.
+	(Nanomsg has been deprecated, but the RMR source remains as an example.)
+
+&di(nng) Source which is tightly coupled with the underlying NNG library.
+
+&end_dlist
+
+&space
+&h3(Internal Function Exposure)
+The decision to limit as much as practical the exposure of truely internal RMR functions
+was made, and as a result most of the RMR functions carry a &cw(static) label.
+In order to modularise the code as much as possible, this means that the primary
+module (e.g. rmr_nng.c) will directly include other RMR modules, rather than 
+depending on referencing the internal functions during linking.
+While this is an infrequently used approach, it does mean that there are very 
+few functions visible for the user application to reference, all of them having 
+the prefix &cw(rmr_,) while allowing internal functions to have shorter names
+while still being meaningful.
+
+&h2(Coding Style)
+There is a list of coding style guidelines in the top level directory, and as such
+they are not expanded upon here. 
+The general practice is to follow the style when editing an existing module, respect
+the author's choice where style alternatives are not frowned upon.
+When creating new modules, select a style that fits the guidelines and is easy
+for you to work with.
+There are a few things that are insisted on by the maintainers of RMR, but for the
+most part style is up to the creator of a module.
+
+&h2(Building)
+RMR is constructed using CMake.
+While CMake's project description can be more cumbersome than most typical Makefiles, 
+the tool provides convenience especially when it comes to creating packages.
diff --git a/doc/src/rtd/fmt_changes.ksh b/doc/src/rtd/fmt_changes.ksh
new file mode 100644
index 0000000..3a1498c
--- /dev/null
+++ b/doc/src/rtd/fmt_changes.ksh
@@ -0,0 +1,47 @@
+# vim: ts=4 noet sw=4:
+#==================================================================================
+#	Copyright (c) 2019 Nokia
+#	Copyright (c) 2018-2019 AT&T Intellectual Property.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#==================================================================================
+
+# format the changes file at the top level into xfm input
+cat <<endKat
+.im setup.im
+&h1(RMR Release Notes)
+The following is a list of release highlights for the core RMR library.
+These are extracted directly from the CHANGES file at the repo root; 
+please refer to that file for a completely up to date listing of
+API changes.  
+&space
+
+endKat
+
+sed 's/^/!/' ../../../CH*|awk ' 
+
+	print_raw && /^!$/ { 
+		printf( "&space\n\n" ); 
+		next 
+	} 
+
+	{ gsub ( "!", "", $1 ) }
+
+	$1 + 0 >= 2019 {
+		print_raw = 1
+		printf( "&h2(%s)\n", $0 )
+		next 
+	}
+
+	print_raw { print } 
+	'
diff --git a/doc/src/rtd/license.im b/doc/src/rtd/license.im
new file mode 100644
index 0000000..46a413b
--- /dev/null
+++ b/doc/src/rtd/license.im
@@ -0,0 +1,58 @@
+.** vim: ts=4 noet sw=4:
+.if false
+==================================================================================
+	Copyright (c) 2019 Nokia
+	Copyright (c) 2018-2019 AT&T Intellectual Property.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================================
+.fi
+
+
+
+.if false
+	These things are forced into some output to cary the license forward since 
+	someone believes the documentation generated is 'source'. We know better.
+	Also, we want to prevent anybody from acutally changing stuff in docs/ 
+	only to be overlaid by a regen.  Committing output is stupid.
+.fi
+
+.dv lic_comment_1 This work is licensed under a Creative Commons Attribution 4.0 International License.
+.dv lic_comment_2 SPDX-License-Identifier: CC-BY-4.0
+.dv caution_1 CAUTION: this document is generated from source in doc/src/rtd. 
+.dv caution_2 To make changes edit the source and recompile the document.
+.dv caution_3 Do NOT make changes directly to .rst or ^.md files.
+
+.if &ot "postscript" =
+	.** this is native postscript, so as is
+	.ai
+	% &lic_comment_1
+	% &lic_comment_2
+	.fo
+	.** no caution because nobody will change the postscript
+.ei
+	.if "&ot" "rst" = 
+		^.. &lic_comment_1
+		.br
+		^.. &lic_comment_2
+		.br
+		^.. &caution_1
+		.br
+		^.. &caution_2
+		.br
+		^.. &caution_3
+	.fi
+.fi
+
+.sp 1
+
diff --git a/doc/src/rtd/overview.xfm b/doc/src/rtd/overview.xfm
new file mode 100644
index 0000000..c9cc807
--- /dev/null
+++ b/doc/src/rtd/overview.xfm
@@ -0,0 +1,34 @@
+.** vim: ts=4 noet sw=4:
+.if false
+==================================================================================
+	Copyright (c) 2019 Nokia
+	Copyright (c) 2018-2019 AT&T Intellectual Property.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================================
+.fi
+
+
+.if false
+	Mnemonic:	overview.xfm
+	Abstract:	Source for the overview which is just a reformatting of the main
+				rmr.7 manual page.
+	Date:		6 November 2019
+	Author:		E. Scott Daniels
+.fi
+
+.im setup.im
+
+&h1(RMR Overview)
+
+.im &{lib}/man/rmr.7.xfm
diff --git a/doc/src/rtd/setup.im b/doc/src/rtd/setup.im
new file mode 100644
index 0000000..92f7539
--- /dev/null
+++ b/doc/src/rtd/setup.im
@@ -0,0 +1,66 @@
+.** vim: ts=4 sw=4 noet:
+.if false
+==================================================================================
+	Copyright (c) 2019 Nokia
+	Copyright (c) 2018-2019 AT&T Intellectual Property.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================================
+.fi
+
+.if false
+	Mnemonic:	setup.im
+	Abstract:	Look at environment variables and pull in the correct setup prep
+				imbed file based on the desired output type (when running tfm).
+				Obviously, when running pfm we are always generating postscirpt
+				so this isn't really doing much.
+	Date:		6 November 2019
+.fi
+
+.if  ! _setup_im
+
+.** if LIB is in the environment we expect it to point at our parent
+.gv e LIB lib
+.if ! lib
+	.dv lib ..
+.fi
+
+.** CAUTION:  xfm comparisons are reverse polish so  "a b ="  is true if a == b.
+.if pfm
+	.dv ot postscript
+	.im &{lib}/generic_ps.im
+.ei
+	.gv e OUTPUT_TYPE ot
+	.if "&ot" "txt" =
+		.im &{lib}/txt.im
+	.fi
+	.if "&ot" "rst" =
+		.im &{lib}/rst.im
+	.fi
+	.if "&ot" "markdown" =
+		.im &{lib}/markdown.im
+	.fi
+	.if "&ot" "troff" =
+		.im &{lib}/roff.im
+	.fi
+.fi
+
+.** if we can set a license into the output, do it early
+.cd 1 11i
+&line_len(10i)
+.im license.im
+.cd 1 6.5i m=0 i=0
+&line_len( 6i)
+
+.dv _setup_im 1
+.fi
diff --git a/doc/src/rtd/user-guide.xfm b/doc/src/rtd/user-guide.xfm
new file mode 100644
index 0000000..5329484
--- /dev/null
+++ b/doc/src/rtd/user-guide.xfm
@@ -0,0 +1,121 @@
+.** vim: ts=4 noet sw=4:
+.if false
+==================================================================================
+	Copyright (c) 2019 Nokia
+	Copyright (c) 2018-2019 AT&T Intellectual Property.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================================
+.fi
+
+
+.if false
+	Mnemonic:	user-guide.xfm
+	Abstract:	Source for the user's guide (mostly just an import of all
+				of the manual pages).
+	Date:		6 November 2019
+	Author:		E. Scott Daniels
+.fi
+
+.im setup.im
+
+&h1(RMR User's Guide)
+
+The RIC Message Router (RMR) is a library which applications use to send and receive
+messages where the message routing, endpoint selection, is based on the message type 
+rather than on traditional DNS names or IP addresses. 
+Because the user documentation for RMR is a collection of UNIX manpages (included
+in the development package, and available via the &cw(man) command when installed), 
+there is no separate "User's Guide." 
+To provide something for the document scrapers to find, this is a collection of
+the RMR manual pages formatted directly from their source which might be a bit
+ragged when combined into a single markup document.  
+Read the manual pages :) 
+&space
+
+
+.** turn of header 1 so that the rmr library header isn't generated for each page
+.dv h1
+.** .im &{lib}/man/rmr.7.xfm
+.ju off &space
+.im &{lib}/man/rmr_alloc_msg.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_bytes2meid.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_bytes2payload.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_bytes2xact.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_call.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_close.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_free_msg.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_get_meid.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_get_rcvfd.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_get_src.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_get_srcip.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_get_trace.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_get_trlen.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_get_xact.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_init.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_init_trace.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_mt_call.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_mt_rcv.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_payload_size.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_rcv_msg.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_ready.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_realloc_payload.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_rts_msg.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_send_msg.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_set_stimeout.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_set_trace.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_str2meid.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_str2xact.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_support.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_torcv_msg.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_trace_ref.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_tralloc_msg.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_wh_close.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_wh_open.3.xfm
+.ju off &space
+.im &{lib}/man/rmr_wh_send_msg.3.xfm
+.ju off &space
+
diff --git a/docs/.gitignore b/docs/.gitignore
new file mode 100644
index 0000000..89d0765
--- /dev/null
+++ b/docs/.gitignore
@@ -0,0 +1,2 @@
+/_build
+/out
diff --git a/docs/README b/docs/README
new file mode 100644
index 0000000..ed5bf27
--- /dev/null
+++ b/docs/README
@@ -0,0 +1,31 @@
+This directory contains project documentation, most of which is
+generated from document source in the doc directory (proj_doc 
+would be a better name for this directory).
+
+Because this directory is "scraped" by some other process(es)
+which seem to be python based, and are completely unrelated to
+this repo, there are some files in this directory which are
+necessary, misterious, and somewhat fragile:
+
+	_static
+	conf.py
+	conf.yaml
+	requirements-docs.txt
+	index.rst
+	favicon.ico		// checking in jpg/png is just as bad as checking a jar
+
+It is also very possible that introducing a change in the files
+listed above will cause the vetting jobs which run on checkin,
+and/or merge, to fail.
+
+The documentation that we place here which is generated (read
+don't modify it in place here as it won't be merged):
+	config-deploy.rst  
+	developer-guide.rst  
+	rel-notes.rst  
+	user-guide.rst
+
+Look for the source, along with instructions on how to compile
+the doc in rmr/doc/src/rtd.  Some of the source for these docs
+is pulled directly from the manual pages in rmr/doc/src/man.
+
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644
index 0000000..922e22f
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1,6 @@
+from docs_conf.conf import *
+linkcheck_ignore = [
+    'http://localhost.*',
+    'http://127.0.0.1.*',
+    'https://gerrit.o-ran-sc.org.*'
+]
diff --git a/docs/conf.yaml b/docs/conf.yaml
new file mode 100644
index 0000000..c2c417d
--- /dev/null
+++ b/docs/conf.yaml
@@ -0,0 +1,3 @@
+---
+project_cfg: oran
+project: portal-ric-librmr
diff --git a/docs/config-deploy.rst b/docs/config-deploy.rst
new file mode 100644
index 0000000..1b56489
--- /dev/null
+++ b/docs/config-deploy.rst
@@ -0,0 +1,104 @@
+ 
+.. This work is licensed under a Creative Commons Attribution 4.0 International License. 
+.. SPDX-License-Identifier: CC-BY-4.0 
+.. CAUTION: this document is generated from source in doc/src/rtd. 
+.. To make changes edit the source and recompile the document. 
+.. Do NOT make changes directly to .rst or .md files. 
+ 
+ 
+RMR Configuration and Delpoyment 
+============================================================================================ 
+ 
+The RIC Message Router (RMR) is a library which applications 
+use to send and receive messages where the message routing, 
+endpoint selection, is based on the message type rather than 
+on traditional DNS names or IP addresses. This document 
+contains information regarding the configuration of RMR when 
+it is embedded by a *user application* . RMR itself is not a 
+deployable entity. 
+ 
+Configuration 
+-------------------------------------------------------------------------------------------- 
+ 
+Several aspects of RMR behaviour is controlled via 
+environment variables which are set at the time that a user 
+application invokes the RMR initialisation function. This 
+allows these variables to be set before the application is 
+started as a function of the true environment, or set by the 
+application as a means for the application to influence RMR's 
+behaviour. The following is a list of RMR variables which RMR 
+recognises (see the main RMR manual page in the development 
+package for more details). 
+ 
+ 
+RMR_ASYNC_CONN 
+   
+  Allows the asynch connection mode to be turned off (by 
+  setting the value to 0. When set to 1, or missing from the 
+  environment, RMR will invoke the connection interface in 
+  the transport mechanism using the non-blocking (asynch) 
+  mode. This will likely result in many "soft failures" 
+  (retry) until the connection is established, but allows 
+  the application to continue unimpeeded should the 
+  connection be slow to set up. 
+ 
+RMR_BIND_IF 
+   
+  This provides the interface that RMr will bind listen 
+  ports to allowing for a single interface to be used rather 
+  than listening across all interfaces. This should be the 
+  IP address assigned to the interface that RMr should 
+  listen on, and if not defined RMr will listen on all 
+  interfaces. 
+ 
+RMR_RTG_SVC 
+   
+  RMr opens a TCP listen socket using the port defined by 
+  this environment variable and expects that the route table 
+  generator process will connect to this port. If not 
+  supplied the port 4561 is used. 
+ 
+RMR_RTG_ISRAW 
+   
+  Is set to 1 if the route table generator is sending 
+  "plain" messages (not using RMr to send messages, 0 if the 
+  rtg is using RMr to send. The default is 1 as we don't 
+  expect the rtg to use RMr. 
+ 
+RMR_SEED_RT 
+   
+  This is used to supply a static route table which can be 
+  used for debugging, testing, or if no route table 
+  generator process is being used to supply the route table. 
+  If not defined, no static table is used and RMr will not 
+  report *ready* until a table is received. 
+ 
+RMR_SRC_ID 
+   
+  This is either the name or IP address which is placed into 
+  outbound messages as the message source. This will used 
+  when an RMR based application uses the rmr_rts_msg() 
+  function to return a response to the sender. If not 
+  supplied RMR will use the hostname which in some container 
+  environments might not be routable. 
+ 
+RMR_VCTL_FILE 
+   
+  This supplies the name of a verbosity control file. The 
+  core RMR functions do not produce messages unless there is 
+  a critical failure. However, the route table collection 
+  thread, not a part of the main message processing 
+  component, can write additional messages to standard 
+  error. If this variable is set, RMR will extract the 
+  verbosity level for these messages (0 is silent) from the 
+  first line of the file. Changes to the file are detected 
+  and thus the level can be changed dynamically, however RMR 
+  will only suss out this variable during initialisation, so 
+  it is impossible to enable verbosity after startup. 
+ 
+RMR_WARNINGS 
+   
+  If set to 1, RMR will write some warnings which are 
+  non-performance impacting. If the variable is not defined, 
+  or set to 0, RMR will not write these additional warnings. 
+ 
diff --git a/docs/developer-guide.rst b/docs/developer-guide.rst
new file mode 100644
index 0000000..151a6f4
--- /dev/null
+++ b/docs/developer-guide.rst
@@ -0,0 +1,98 @@
+ 
+.. This work is licensed under a Creative Commons Attribution 4.0 International License. 
+.. SPDX-License-Identifier: CC-BY-4.0 
+.. CAUTION: this document is generated from source in doc/src/rtd. 
+.. To make changes edit the source and recompile the document. 
+.. Do NOT make changes directly to .rst or .md files. 
+ 
+ 
+RMR Developer Guide 
+============================================================================================ 
+ 
+The RIC Message Router (RMR) is a library which applications 
+use to send and receive messages where the message routing, 
+endpoint selection, is based on the message type rather than 
+on traditional DNS names or IP addresses. This document 
+contains information that potential developers might need to 
+know in order to contribute to the project 
+ 
+Language 
+-------------------------------------------------------------------------------------------- 
+ 
+RMR is written in C, and thus a contributing developer to the 
+core library should have an excellent working knowledge of C. 
+There currently is one set of cross languages bindings 
+supporting Python, and a developer wishing to contribute to 
+the bindings source should be familiar with Python (version 
+3.7+) and with the Ptyhhon *ctypes* library. 
+ 
+Code Structure 
+-------------------------------------------------------------------------------------------- 
+ 
+RMR is designed to provide an insulation layer between user 
+applications and the actual transport mechanism. Initially 
+RMR was built on top of Nanosmg, and shortly after was ported 
+to NNG (Nanomsg Next Generation). Becuase RMR presents the 
+same API to the user application regardless of the underlying 
+transport library, the resulting output when compiling RMR is 
+a transport specific library. As an example, librmr_nng.a is 
+the library generated for use with the NNG transport. 
+ 
+As such the library source is organised into multiple 
+components: 
+ 
+ 
+common 
+   
+  Source in the common directory is agnostic to the 
+  underlying transport mechanism (Nanomsg or NNG), and thus 
+  can be used when generating either library. 
+ 
+nano 
+   
+  Source which is tightly coupled with the underlying 
+  Nanomsg library. (Nanomsg has been dreprecated, but the 
+  RMR source remains as an example.) 
+ 
+nng 
+   
+  Source which is tightly coupled with the underlying NNG 
+  library. 
+ 
+ 
+ 
+Internal Function Exposure 
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
+ 
+The decision to limit as much as practical the exposure of 
+truely interal RMR functions was made, and as a result most 
+of the RMR functions carry a static label. In order to 
+modularlise the code as much as possible, this means that the 
+primary module (e.g. rmr_nng.c) will driectly include other 
+RMR modules, rather than depending on referencing the interal 
+functions during linking. While this is an infrequenly used 
+approach, it does mean that there are very few functions 
+visible for the user application to reference, all of them 
+having the prefix rmr_, while allowing internal functions to 
+have shorter names while still being meaningful. 
+ 
+Coding Style 
+-------------------------------------------------------------------------------------------- 
+ 
+There is a list of coding style guidelines in the top level 
+directory, and as such they are not expanded upon here. The 
+general practice is to follow the style when editing an 
+existing module, respect the author's choice where style 
+alternatves are not frowned upon. When creating new modules, 
+select a style that fits the guidelines and is easy for you 
+to work with. There are a few things that are insisted on by 
+the maintainers of RMR, but for the most part style is up to 
+the creator of a module. 
+ 
+Building 
+-------------------------------------------------------------------------------------------- 
+ 
+RMR is constructed using CMake. While CMake's project 
+description can be more cumbersome than most typical 
+Makefiles, the tool provides convenience especially when it 
+comes to creating packages. 
diff --git a/docs/favicon.ico b/docs/favicon.ico
new file mode 100644
index 0000000..dc983e0
--- /dev/null
+++ b/docs/favicon.ico
Binary files differ
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644
index 0000000..c9289fb
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,21 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. SPDX-License-Identifier: CC-BY-4.0
+
+
+.. who in bloody hell knows what format this should be; guessing!
+
+
+RIC Message Router -- RMR
+==========================
+
+
+.. toctree::
+   :maxdepth: 2
+   :caption: Contents:
+
+   overview.rst
+   config-deploy.rst
+   developer-guide.rst
+   rel-notes.rst
+
+* :ref:`search`
diff --git a/docs/overview.rst b/docs/overview.rst
new file mode 100644
index 0000000..65360bf
--- /dev/null
+++ b/docs/overview.rst
@@ -0,0 +1,154 @@
+ 
+.. This work is licensed under a Creative Commons Attribution 4.0 International License. 
+.. SPDX-License-Identifier: CC-BY-4.0 
+.. CAUTION: this document is generated from source in doc/src/rtd. 
+.. To make changes edit the source and recompile the document. 
+.. Do NOT make changes directly to .rst or .md files. 
+ 
+ 
+RMR Overview 
+============================================================================================ 
+ 
+ 
+RMr Library 
+============================================================================================ 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+RMr -- Ric Message Router Library 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+RMr is a library which provides a user application with the 
+ability to send and receive messages to/from other RMr based 
+applications without having to understand the underlying 
+messaging transport environment (e.g. Nanomsg) and without 
+needing to know which other endpoint applications are 
+currently available and accepting messages. To do this, RMr 
+depends on a routing table generated by an external source. 
+This table is used to determine the destination endpoint of 
+each message sent by mapping the message type T (supplied by 
+the user application) to an endpoint entry. Once determined, 
+the message is sent directly to the endpoint. The user 
+application is unaware of which endpoint actually receives 
+the message, and in some cases whether that message was sent 
+to multiple applications. 
+ 
+RMr functions do provide for the ability to respond to the 
+specific source instance of a message allowing for either a 
+request response, or call response relationship when needed. 
+ 
+The Route Table 
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
+ 
+The library is supplied with a route table which maps message 
+numbers to endpoint groups such that each time a message of 
+type T is sent, the message is delivered to one member of 
+each group associated with T. For example, message type 2 
+might route to two different groups where group A consists of 
+worker1 and worker2, while group B consists only of logger1. 
+ 
+It is the responsibility of the route table generator to know 
+which endpoints belong to which groups, and which groups 
+accept which message types. Once understood, the route table 
+generator publishes a table that is ingested by RMr and used 
+for mapping messages to end points. 
+ 
+Environment 
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
+ 
+To enable configuration of the library behaviour outside of 
+direct user application control, RMr supports a number of 
+environment variables which provide information to the 
+library. The following is a list of the various environment 
+variables, what they control and the defaults which RMr uses 
+if undefined. 
+ 
+ 
+RMR_ASYNC_CONN 
+   
+  Allows the asynch connection mode to be turned off (by 
+  setting the value to 0. When set to 1, or missing from the 
+  environment, RMR will invoke the connection interface in 
+  the transport mechanism using the non-blocking (asynch) 
+  mode. This will likely result in many "soft failures" 
+  (retry) until the connection is established, but allows 
+  the application to continue unimpeeded should the 
+  connection be slow to set up. 
+ 
+RMR_BIND_IF 
+   
+  This provides the interface that RMr will bind listen 
+  ports to allowing for a single interface to be used rather 
+  than listening across all interfaces. This should be the 
+  IP address assigned to the interface that RMr should 
+  listen on, and if not defined RMr will listen on all 
+  interfaces. 
+ 
+RMR_RTG_SVC 
+   
+  RMr opens a TCP listen socket using the port defined by 
+  this environment variable and expects that the route table 
+  generator process will connect to this port. If not 
+  supplied the port 4561 is used. 
+ 
+RMR_RTG_ISRAW 
+   
+  Is set to 1 if the route table generator is sending 
+  "plain" messages (not using RMr to send messages, 0 if the 
+  rtg is using RMr to send. The default is 1 as we don't 
+  expect the rtg to use RMr. 
+ 
+RMR_SEED_RT 
+   
+  This is used to supply a static route table which can be 
+  used for debugging, testing, or if no route table 
+  generator process is being used to supply the route table. 
+  If not defined, no static table is used and RMr will not 
+  report *ready* until a table is received. 
+ 
+RMR_SRC_ID 
+   
+  This is either the name or IP address which is placed into 
+  outbound messages as the message source. This will used 
+  when an RMR based application uses the rmr_rts_msg() 
+  function to return a response to the sender. If not 
+  supplied RMR will use the hostname which in some container 
+  environments might not be routable. 
+ 
+RMR_VCTL_FILE 
+   
+  This supplies the name of a verbosity control file. The 
+  core RMR functions do not produce messages unless there is 
+  a critical failure. However, the route table collection 
+  thread, not a part of the main message processing 
+  component, can write additional messages to standard 
+  error. If this variable is set, RMR will extract the 
+  verbosity level for these messages (0 is silent) from the 
+  first line of the file. Changes to the file are detected 
+  and thus the level can be changed dynamically, however RMR 
+  will only suss out this variable during initialisation, so 
+  it is impossible to enable verbosity after startup. 
+ 
+RMR_WARNINGS 
+   
+  If set to 1, RMR will write some warnings which are 
+  non-performance impacting. If the variable is not defined, 
+  or set to 0, RMR will not write these additional warnings. 
+ 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_tralloc_msg(3), rmr_call(3), 
+rmr_free_msg(3), rmr_init(3), rmr_init_trace(3), 
+rmr_get_meid(3), rmr_get_src(3), rmr_get_srcip(3), 
+rmr_get_trace(3), rmr_get_trlen(3), rmr_get_xact(3), 
+rmr_payload_size(3), rmr_rcv_msg(3), rmr_rcv_specific(3), 
+rmr_rts_msg(3), rmr_ready(3), rmr_fib(3), rmr_has_str(3), 
+rmr_tokenise(3), rmr_mk_ring(3), rmr_realloc_payload(3), 
+rmr_ring_free(3), rmr_set_trace(3), rmr_torcv_msg(3), 
+rmr_wh_open(3), rmr_wh_send_msg(3) 
diff --git a/docs/rel-notes.rst b/docs/rel-notes.rst
new file mode 100644
index 0000000..898787b
--- /dev/null
+++ b/docs/rel-notes.rst
@@ -0,0 +1,172 @@
+ 
+.. This work is licensed under a Creative Commons Attribution 4.0 International License. 
+.. SPDX-License-Identifier: CC-BY-4.0 
+.. CAUTION: this document is generated from source in doc/src/rtd. 
+.. To make changes edit the source and recompile the document. 
+.. Do NOT make changes directly to .rst or .md files. 
+ 
+ 
+RMR Release Notes 
+============================================================================================ 
+ 
+The following is a list of release highlights for the core 
+RMR library. These are extracted directly from the CHANGES 
+file at the repo root; please refer to that file for a 
+completely up to date listing of API changes. 
+ 
+ 
+2019 October 31; version 1.10.2 
+-------------------------------------------------------------------------------------------- 
+ 
+Provide the means to increase the payload size of a received 
+message without losing the data needed to use the 
+rmr_rts_msg() funciton. 
+ 
+ 
+2019 October 21; version 1.10.1 
+-------------------------------------------------------------------------------------------- 
+ 
+Fix to prevent null message buffer from being returned by the 
+timeout receive function if the function is passed one to 
+reuse. 
+ 
+ 
+2019 October 21; version 1.10.1 
+-------------------------------------------------------------------------------------------- 
+ 
+Add periodic dump of send count info to stderr. 
+ 
+ 
+2019 September 27; version 1.9.0 
+-------------------------------------------------------------------------------------------- 
+ 
+Python bindings added receive all queued function and 
+corrected a unit test 
+ 
+ 
+2019 September 25; version 1.8.3 
+-------------------------------------------------------------------------------------------- 
+ 
+Correct application level test issue causing timing problems 
+during jenkins verification testing at command and merge 
+ 
+Handle the NNG connection shutdown status which may now be 
+generated when a connection throug a proxy is reset. 
+ 
+ 
+2019 September 25; version 1.8.2 
+-------------------------------------------------------------------------------------------- 
+ 
+Correct bug in rmr_torcv_msg() when timeout set to zero (0). 
+ 
+ 
+2019 September 19; version 1.8.1 
+-------------------------------------------------------------------------------------------- 
+ 
+Correct missing constant for wrappers. 
+ 
+2019 September 19; version 1.8.0 
+-------------------------------------------------------------------------------------------- 
+ 
+New message types added: RAN_CONNECTED, RAN_RESTARTED, 
+RAN_RECONFIGURED 
+ 
+ 
+2019 September 17; version 1.7.0 
+-------------------------------------------------------------------------------------------- 
+ 
+Initial connection mode now defaults to asynchronous. Set 
+RMR_ASYNC_CONN=0 in the environment before rmr_init() is 
+invoked to revert to synchronous first TCP connections. 
+(Recovery connection attempts have always been asynchronous). 
+ 
+ 
+2019 September 3; version 1.6.0 
+-------------------------------------------------------------------------------------------- 
+ 
+Fix bug in the rmr_rts_msg() function. If a return to sender 
+message failed, the source IP address was not correctly 
+adjusted and could cause the message to be "reflected" back 
+to the sender on a retry. 
+ 
+Added the ability to set the source "ID" via an environment 
+var (RMR_SRC_ID). When present in the environment, the string 
+will be placed in to the message header as the source and 
+thus be used by an application calling rmr_rts_smg() to 
+return a response to the sender. If this environment variable 
+is not present, the host name (original behaviour) is used. 
+ 
+ 
+2019 August 26; version 1.4.0 
+-------------------------------------------------------------------------------------------- 
+ 
+New message types were added. 
+ 
+ 
+2019 August 16; version 1.3.0 
+-------------------------------------------------------------------------------------------- 
+ 
+New mesage types added. 
+ 
+ 
+2019 August 13; version 1.2.0 (API change, non-breaking) 
+-------------------------------------------------------------------------------------------- 
+ 
+The function rmr_get_xact() was added to proide a convenient 
+way to extract the transaction field from a message. 
+ 
+ 
+2019 August 8; version 1.1.0 (API change) 
+-------------------------------------------------------------------------------------------- 
+ 
+This change should be backward compatable/non-breaking A new 
+field has been added to the message buffer (rmr_mbuf_t). This 
+field (tp_state) is used to communicate the errno value that 
+the transport mechanism might set during send and/or receive 
+operations. C programmes should continue to use errno 
+directly, but in some environments wrappers may not be able 
+to access errno and this provides the value to them. See the 
+rmr_alloc_msg manual page for more details. 
+ 
+2019 August 6; version 1.0.45 (build changes) 
+-------------------------------------------------------------------------------------------- 
+ 
+Support for the Nanomsg transport library has been dropped. 
+The library librmr.* will no longer be included in packages. 
+ 
+Packages will install RMR libraries into the system preferred 
+target directory. On some systems this is /usr/local/lib and 
+on others it is /usr/local/lib64. The diretory is determined 
+by the sytem on which the package is built and NOT by the 
+system installing the package, so it's possible that the RMR 
+libraries end up in a strange location if the .deb or .rpm 
+file was generated on a Linux flavour that has a different 
+preference than the one where the package is installed. 
+ 
+ 
+2019 August 6; version 1.0.44 (API change) 
+-------------------------------------------------------------------------------------------- 
+ 
+Added a new message type constant. 
+ 
+ 
+2019 July 15; Version 1.0.39 (bug fix) 
+-------------------------------------------------------------------------------------------- 
+ 
+Prevent unnecessary usleep in retry loop. 
+ 
+ 
+2019 July 12; Version 1.0.38 (API change) 
+-------------------------------------------------------------------------------------------- 
+ 
+Added new message types to RIC_message_types.h. 
+ 
+ 
+2019 July 11; Version 1.0.37 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+librmr and librmr_nng - Add message buffer API function 
+rmr_trace_ref() (see rmr_trace_ref.3 manual page in dev 
+package). 
+ 
diff --git a/docs/release-notes.rst b/docs/release-notes.rst
new file mode 100644
index 0000000..67c3e88
--- /dev/null
+++ b/docs/release-notes.rst
@@ -0,0 +1,155 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. SPDX-License-Identifier: CC-BY-4.0
+
+RIC Dashboard Release Notes
+===========================
+
+Version 1.3.0, 4 Nov 2019
+-------------------------
+* Revise e2-mgr-client to use API spec in new submodule ric-plt/e2mgr;
+  removed cached copy
+* Silence many Sonar complaints
+* Revise license statements in documentation files
+* Revise stats screen to drop mock load, pendulum, reporting items
+
+Version 1.2.4, 24 Oct 2019
+--------------------------
+* This version is used for the AT&T/Nokia co-create PIZ trials Nov 2019.
+* Revise a1-med-client to use API spec in new submodule ric-plt/a1;
+  removed cached copy
+* Revise app manager client to use API spec in new submodule ric-plt/appmgr;
+  removed cached copy
+* Add Platform page showing Kubernetes pods in aux and platform obtained from CAAS-Ingress
+* Update Angular libraries to recent stable versions
+* Revise user controller to answer data sent by portal, drop the mock implementation
+* Set global style for page titles
+* Align page titles to top left,decrease font size
+* Update EPSDK-FW to version 2.6
+* Make constructor robust to missing caasingress.insecure property
+* Repair bug that omitted slashes in CAAS-Ingress URL builder
+* Improve the dark mode
+* Show container ready count with total count
+
+Version 1.2.3, 4 Oct 2019
+-------------------------
+* Serve unauthenticated user a login-at-portal page without using redirect
+* Upgrade to Spring-Boot 2.1.9.RELEASE
+
+Version 1.2.2, 27 Sep 2019
+--------------------------
+* Support Portal security using EPSDK-FW cookie and user management
+
+Version 1.2.1, 20 Sep 2019
+--------------------------
+* Repair E2 URLs in front end like endc-setup/endcSetup
+* Extend ANR mock feature to persist edits for demos
+* Block whitespace in E2 IP input field validation
+* Relax validation in E2 RAN name field validation
+* Make RAN connection table robust to missing fields
+* Install curl when building Docker image
+
+Version 1.2.0, 11 Sep 2019
+--------------------------
+* Split URL properties into prefix/suffix parts
+* Add jacoco plugin to back-end for code coverage
+* Compile with Java version 11, use base openjdk:11-jre-slim
+* Clean code of issues reported by Sonar
+* Drop mock RAN names feature that supported R1 testing
+* Extend mock endpoints to simulate delay seen in tests
+* Move mock configuration classes into test area
+* Update App manager client to spec version 0.1.7
+* Add controller for page refresh of Angular routes
+* Extend E2 mock configuration for demo purposes
+* Add pattern for matching AC/admin application name
+* Add custom (plain but not white-label) error page
+* Synch A1 method paths in front-end and back-end
+* Add xapp dynamic configuration feature
+* Disable x-frame-options response header
+* Repair app manager undeploy-app back/front methods
+* Display AC xAPP metrics data via Kibana source (metrics.url.ac) on dashboard
+* Pass AC policy parameter without parsing as JSON
+* Use snake_case (not camelCase) names in AC policy front end
+* Update A1 mediator client to spec version 0.10.3
+* Extend AC control screen to read policy from A1
+* Create loading-dialog component and service
+* Showing the loading-dialog while making API call
+* Add notification and error handling for xapp configuration
+* Update E2 manager client to spec version 2.0.5 of 2019-09-11
+* Display MC xAPP metrics data via Kibana source (metrics.url.mc) on dashboard
+
+Version 1.0.5, 5 July 2019
+--------------------------
+* Upgrade to Angular version 8
+* Upgrade to Spring-Boot 2.1.6.RELEASE
+* Align AC xApp policy page title
+* Update E2 manager client to spec version 20190703
+* Add configuration-driven mock of E2 getNodebIdList
+* Revise front-end components to use prefix 'rd'
+* Improve error handling in BE and FE code
+* Revise the notification service to display multiple notifications
+* Add JUnit test cases for controller methods
+
+Version 1.0.4, 27 June 2019
+---------------------------
+* Add AC xApp neighbor control screen
+* Add ANR xApp neighbor cell relation table
+* Drop the pendulum xApp control screen
+* Add column sorting on xApp catalog, xApp control, ANR
+* Add disconnect-all button to RAN connection screen
+* Extend E2 service with disconnect-all method
+* Update ANR xApp client to spec version 0.0.8
+* Update E2 manager client to spec version 20190620
+* Adjust CSS and HTML for main container positioning
+* Revise config property keys to use URL (not basepath)
+* Left menu overlap main content fix
+* Extend back-end controllers to return error details
+* Add feature resilient to malformed instance data
+* Extend Xapp Controller with config endpoints
+* Add build number to dashboard version string
+* Move mock admin screen user data to backend
+* Update App manager client to spec version 0.1.5
+* Move RAN connection feature to control screen
+* Rework admin table
+* Update the notification service
+* Move RAN connection feature to control screen
+* Repair deploy-app feature and use icon instead of text button
+
+Version 1.0.3, 28 May 2019
+--------------------------
+* Add AC xApp controller to backend
+* Add AC xApp interface to frontend
+* Add RAN type radio selector to connection setup
+* Update ANR xApp client to spec version 0.0.7
+* Update E2 manager client to spec version 20190515
+* Update xApp manager client to spec version 0.1.4
+* Add get-version methods to all controllers
+* Add simple page footer with copyright and version
+* Add AC and ANR xApp services
+* Rename signal service to E2 Manager service
+* Use XappMgrService to replace ControlService and CatalogService
+* Apply mat-table to control and catalog
+* RAN Connection screen upgrade to mat-table
+
+Version 1.0.2, 13 May 2019
+--------------------------
+* Update A1 mediator client to version 0.4.0
+* Add E2 response message with timestamp and status code
+* Fetch xAPP instance status information from xAPP Manager and display in dashboard
+* Allow the user to initiate an E2 (X2) connection between RIC and gNB/eNB
+* User input validations on connections between RIC and eNB/gNB in the dashboard
+* Add ANR xApp backend with mock implementation
+* Add undeploy xApp function
+* Add shared confirm dialog
+* Add shared notification
+
+Version 1.0.1, 6 May 2019
+-------------------------
+* Add draft A1 Mediator API definition
+* Use E2 Manager API definition dated 2 May 2019, with tag modifications
+* Adjust group IDs and packages for name O-RAN-SC; drop ORAN-OSC
+* Add ANR API spec and client code generator
+* Update xApp Manager API spec to version 0.1.2
+
+Version 1.0.0, 30 Apr 2019
+--------------------------
+* Initial version
diff --git a/docs/requirements-docs.txt b/docs/requirements-docs.txt
new file mode 100644
index 0000000..09a0c1c
--- /dev/null
+++ b/docs/requirements-docs.txt
@@ -0,0 +1,5 @@
+sphinx
+sphinx-rtd-theme
+sphinxcontrib-httpdomain
+recommonmark
+lfdocs-conf
diff --git a/docs/user-guide.rst b/docs/user-guide.rst
new file mode 100644
index 0000000..b13234a
--- /dev/null
+++ b/docs/user-guide.rst
@@ -0,0 +1,3752 @@
+ 
+.. This work is licensed under a Creative Commons Attribution 4.0 International License. 
+.. SPDX-License-Identifier: CC-BY-4.0 
+.. CAUTION: this document is generated from source in doc/src/rtd. 
+.. To make changes edit the source and recompile the document. 
+.. Do NOT make changes directly to .rst or .md files. 
+ 
+ 
+RMR User's Guide 
+============================================================================================ 
+ 
+The RIC Message Router (RMR) is a library which applications 
+use to send and receive messages where the message routing, 
+endpoint selection, is based on the message type rather than 
+on traditional DNS names or IP addresses. Because the user 
+documentation for RMR is a collection of UNIX manpages 
+(included in the development package, and avalable via the 
+man command when installed), there is no separate "User's 
+Guide." To prvide something for the document scrapers to 
+find, this is a collection of the RMR manual pages formatted 
+directly from their source which might be a bit ragged when 
+combined into a single markup document. Read the manual pages 
+:) 
+ 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ rmr_mbuf_t* rmr_alloc_msg( void* ctx, int size );
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_alloc_msg function is used to allocate a buffer which 
+the user programme can write into and then send through the 
+RMR library. The buffer is allocated such that sending it 
+requires no additional copying out of the buffer. If the 
+value passed in size is 0, then the default size supplied on 
+the *rmr_init* call will be used. The *ctx* parameter is the 
+void context pointer that was returned by the *rmr_init* 
+function. 
+ 
+The pointer to the message buffer returned is a structure 
+which has some user application visible fields; the structure 
+is described in rmr.h, and is illustrated below. 
+ 
+ 
+:: 
+  
+ typedef struct {
+     int state;
+     int mtype;
+     int len;
+     unsigned char* payload;
+     unsigned char* xaction;
+     uint sub_id;
+     uint tp_state;
+ } rmr_mbuf_t;
+ 
+ 
+ 
+ 
+ 
+state 
+   
+  Is the current buffer state. Following a call to 
+  rmr_send_msg the state indicates whether the buffer was 
+  successfully sent which determines exactly what the 
+  payload points to. If the send failed, the payload 
+  referenced by the buffer is the message that failed to 
+  send (allowing the application to attempt a 
+  retransmission). When the state is RMR_OK the buffer 
+  represents an empty buffer that the application may fill 
+  in in preparation to send. 
+   
+ 
+mtype 
+   
+  When sending a message, the application is expected to set 
+  this field to the appropriate message type value (as 
+  determined by the user programme). Upon send this value 
+  determines how the RMR library will route the message. For 
+  a buffer which has been received, this field will contain 
+  the message type that was set by the sending application. 
+   
+ 
+len 
+   
+  The application using a buffer to send a message is 
+  expected to set the length value to the actual number of 
+  bytes that it placed into the message. This is likely less 
+  than the total number of bytes that the message can carry. 
+  For a message buffer that is passed to the application as 
+  the result of a receive call, this will be the value that 
+  the sending application supplied and should indicate the 
+  number of bytes in the payload which are valid. 
+   
+ 
+payload 
+   
+  The payload is a pointer to the actual received data. The 
+  user programme may read and write from/to the memory 
+  referenced by the payload up until the point in time that 
+  the buffer is used on a rmr_send, rmr_call or rmr_reply 
+  function call. Once the buffer has been passed back to a 
+  RMR library function the user programme should **NOT** 
+  make use of the payload pointer. 
+   
+ 
+xaction 
+   
+  The *xaction* field is a pointer to a fixed sized area in 
+  the message into which the user may write a transaction 
+  ID. The ID is optional with the exception of when the user 
+  application uses the rmr_call function to send a message 
+  and wait for the reply; the underlying RMR processing 
+  expects that the matching reply message will also contain 
+  the same data in the *xaction* field. 
+ 
+ 
+ 
+sub_id 
+   
+  This value is the subscription ID. It, in combination with 
+  the message type is used by rmr to determine the target 
+  endpoint when sending a message. If the application to 
+  application protocol does not warrant the use of a 
+  subscription ID, the RMR constant RMR_VOID_SUBID should be 
+  placed in this field. When an application is forwarding or 
+  returning a buffer to the sender, it is the application's 
+  responsibility to set/reset this value. 
+   
+ 
+tp_state 
+   
+  For C applications making use of RMR, the state of a 
+  transport based failure will often be available via errno. 
+  However, some wrapper environments may not have direct access 
+  to the C-lib errno value. RMR send and receive operations 
+  will place the current value of errno into this field which 
+  should make it available to wrapper functions. User 
+  applications are strongly cautioned against relying on the 
+  value of errno as some transport mechanisms may not set this 
+  value on all calls. This value should also be ignored any 
+  time the message status is RMR_OK. 
+ 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+The function returns a pointer to a rmr_mbuf structure, or NULL 
+on error. 
+ 
+ERRORS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+ 
+ENOMEM 
+   
+  Unable to allocate memory. 
+ 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_tralloc_msg(3), rmr_call(3), rmr_free_msg(3), rmr_init(3), 
+rmr_init_trace(3), rmr_get_trace(3), rmr_get_trlen(3), 
+rmr_payload_size(3), rmr_send_msg(3), rmr_rcv_msg(3), 
+rmr_rcv_specific(3), rmr_rts_msg(3), rmr_ready(3), rmr_fib(3), 
+rmr_has_str(3), rmr_tokenise(3), rmr_mk_ring(3), 
+rmr_ring_free(3), rmr_set_trace(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_bytes2meid 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ int rmr_bytes2meid( rmr_mbuf_t* mbuf, unsigned char* src, int len )
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_bytes2meid function will copy up to *len* butes from 
+*src* to the managed equipment ID (meid) field in the 
+message. The field is a fixed length, gated by the constant 
+RMR_MAX_MEID and if len is larger than this value, only 
+RMR_MAX_MEID bytes will actually be copied. 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+On success, the actual number of bytes copied is returned, or 
+-1 to indicate a hard error. If the length is less than 0, or 
+not the same as length passed in, errno is set to one of the 
+errors described in the *Errors* section. 
+ 
+ERRORS 
+-------------------------------------------------------------------------------------------- 
+ 
+If the returned length does not match the length passed in, 
+errno will be set to one of the following constants with the 
+meaning listed below. 
+ 
+ 
+ 
+EINVAL 
+   
+  The message, or an internal portion of the message, was 
+  corrupted or the pointer was invalid. 
+   
+ 
+EOVERFLOW 
+   
+  The length passed in was larger than the maximum length of 
+  the field; only a portion of the source bytes were copied. 
+ 
+ 
+EXAMPLE 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_bytes2xact(3), rmr_call(3), 
+rmr_free_msg(3), rmr_get_rcvfd(3), rmr_get_meid(3), 
+rmr_payload_size(3), rmr_send_msg(3), rmr_rcv_msg(3), 
+rmr_rcv_specific(3), rmr_rts_msg(3), rmr_ready(3), 
+rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), rmr_mk_ring(3), 
+rmr_ring_free(3), rmr_str2meid(3), rmr_str2xact(3), 
+rmr_wh_open(3), rmr_wh_send_msg(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_bytes2payload 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ void rmr_bytes2payload( rmr_mbuf_t* mbuf, unsigned char* src, int len )
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+This is a convenience function as some wrapper languages 
+might not have the ability to directly copy into the payload 
+buffer. The bytes from * src * for the length given are 
+copied to the payload. It is the caller's responsibility to 
+ensure that the payload is large enough. Upon successfully 
+copy, the len field in the message buffer is updated to 
+reflect the number of bytes copied. 
+ 
+There is little error checking, and no error reporting. 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+None. 
+ 
+EXAMPLE 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_bytes2xact(3), rmr_bytes2payload(3), 
+rmr_call(3), rmr_free_msg(3), rmr_get_rcvfd(3), 
+rmr_get_meid(3), rmr_payload_size(3), rmr_send_msg(3), 
+rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), 
+rmr_ready(3), rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), 
+rmr_mk_ring(3), rmr_ring_free(3), rmr_str2meid(3), 
+rmr_str2xact(3), rmr_wh_open(3), rmr_wh_send_msg(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_bytes2xact 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ int rmr_bytes2xact( rmr_mbuf_t* mbuf, unsigned char* src, int len )
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_bytes2xact function will copy up to *len* butes from 
+*src* to the transaction ID (xaction) field in the message. 
+The field is a fixed length, gated by the constant 
+RMR_MAX_XID and if len is larger than this value, only 
+RMR_MAX_XID bytes will actually be copied. 
+ 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+On success, the actual number of bytes copied is returned, 
+or -1 to indicate a hard error. If the length is less than 
+0, or not the same as length passed in, errno is set to 
+one of the errors described in the *Errors* section. 
+ 
+ERRORS 
+-------------------------------------------------------------------------------------------- 
+ 
+If the returned length does not match the length passed 
+in, errno will be set to one of the following constants 
+with the meaning listed below. 
+ 
+ 
+EINVAL 
+   
+  The message, or an internal portion of the message, was 
+  corrupted or the pointer was invalid. 
+   
+ 
+EOVERFLOW 
+   
+  The length passed in was larger than the maximum length of 
+  the field; only a portion of the source bytes were copied. 
+ 
+ 
+EXAMPLE 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_bytes2meid(3), rmr_call(3), 
+rmr_free_msg(3), rmr_get_meid(3), rmr_get_rcvfd(3), 
+rmr_get_xact(3), rmr_payload_size(3), rmr_send_msg(3), 
+rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), 
+rmr_ready(3), rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), 
+rmr_mk_ring(3), rmr_ring_free(3), rmr_str2meid(3), 
+rmr_wh_open(3), rmr_wh_send_msg(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_call 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ extern rmr_mbuf_t* rmr_call( void* vctx, rmr_mbuf_t* msg );
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_call function sends the user application message to a 
+remote endpoint, and waits for a corresponding response 
+message before returning control to the user application. The 
+user application supplies a completed message buffer, as it 
+would for a rmr_send call, but unlike with the send, the 
+buffer returned will have the response from the application 
+that received the message. 
+ 
+Messages which are received while waiting for the response 
+are queued internally by RMR, and are returned to the user 
+application when rmr_rcv_msg is invoked. These messages are 
+returned in th order received, one per call to rmr_rcv_msg. 
+ 
+Call Timeout 
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
+ 
+The rmr_call function implements a timeout failsafe to 
+prevent, in most cases, the function from blocking forever. 
+The timeout period is **not** based on time (calls to clock 
+are deemed too expensive for a low latency system level 
+library, but instead the period is based on the number of 
+received messages which are not the response. Using a 
+non-time mechanism for *timeout* prevents the async queue 
+from filling (which would lead to message drops) in an 
+environment where there is heavy message traffic. 
+ 
+When the threshold number of messages have been queued 
+without receiving a response message, control is returned to 
+the user application and a NULL pointer is returned to 
+indicate that no message was received to process. Currently 
+the threshold is fixed at 20 messages, though in future 
+versions of the library this might be extended to be a 
+parameter which the user application may set. 
+ 
+Retries 
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
+ 
+The send operations in RMr will retry *soft* send failures 
+until one of three conditions occurs: 
+ 
+ 
+ 
+1. 
+   
+  The message is sent without error 
+   
+ 
+2. 
+   
+  The underlying transport reports a * hard * failure 
+   
+ 
+3. 
+   
+  The maximum number of retry loops has been attempted 
+ 
+ 
+A retry loop consists of approximately 1000 send attemps ** 
+without** any intervening calls to * sleep() * or * usleep(). 
+* The number of retry loops defaults to 1, thus a maximum of 
+1000 send attempts is performed before returning to the user 
+application. This value can be set at any point after RMr 
+initialisation using the * rmr_set_stimeout() * function 
+allowing the user application to completely disable retires 
+(set to 0), or to increase the number of retry loops. 
+ 
+Transport Level Blocking 
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
+ 
+The underlying transport mechanism used to send messages is 
+configured in *non-blocking* mode. This means that if a 
+message cannot be sent immediately the transport mechanism 
+will **not** pause with the assumption that the inability to 
+send will clear quickly (within a few milliseconds). This 
+means that when the retry loop is completely disabled (set to 
+0), that the failure to accept a message for sending by the 
+underlying mechanisms (software or hardware) will be reported 
+immediately to the user application. 
+ 
+It should be noted that depending on the underlying transport 
+mechanism being used, it is extremly possible that during 
+normal operations that retry conditions are very likely to 
+happen. These are completely out of RMr's control, and there 
+is nothing that RMr can do to avoid or midigate these other 
+than by allowing RMr to retry the send operation, and even 
+then it is possible (e.g. during connection reattempts), that 
+a single retry loop is not enough to guarentee a successful 
+send. 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_call function returns a pointer to a message buffer 
+with the state set to reflect the overall state of call 
+processing (see Errors below). In some cases a NULL pointer 
+will be returned; when this is the case only *errno* will be 
+available to describe the reason for failure. 
+ 
+ERRORS 
+-------------------------------------------------------------------------------------------- 
+ 
+These values are reflected in the state field of the returned 
+message. 
+ 
+ 
+ 
+RMR_OK 
+   
+  The call was successful and the message buffer references 
+  the response message. 
+   
+ 
+RMR_ERR_CALLFAILED 
+   
+  The call failed and the value of *errno,* as described 
+  below, should be checked for the specific reason. 
+ 
+ 
+The global "variable" *errno* will be set to one of the 
+following values if the overall call processing was not 
+successful. 
+ 
+ 
+ 
+ETIMEDOUT 
+   
+  Too many messages were queued before receiving the 
+  expected response 
+   
+ 
+ENOBUFS 
+   
+  The queued message ring is full, messages were dropped 
+   
+ 
+EINVAL 
+   
+  A parameter was not valid 
+   
+ 
+EAGAIN 
+   
+  The underlying message system wsa interrupted or the 
+  device was busy; the message was **not** sent, and user 
+  application should call this function with the message 
+  again. 
+ 
+ 
+EXAMPLE 
+-------------------------------------------------------------------------------------------- 
+ 
+The following code bit shows one way of using the rmr_call 
+function, and illustrates how the transaction ID must be set. 
+ 
+ 
+:: 
+  
+     int retries_left = 5;               // max retries on dev not available
+     int retry_delay = 50000;            // retry delay (usec)
+     static rmr_mbuf_t*  mbuf = NULL;    // response msg
+     msg_t*  pm;                         // private message (payload)
+     m// get a send buffer and reference the payload 
+     mbuf = rmr_alloc_msg( mr, RMR_MAX_RCV_BYTES );
+     pm = (msg_t*) mbuf->payload;
+     p// generate an xaction ID and fill in payload with data and msg type
+     snprintf( mbuf->xaction, RMR_MAX_XID, "%s", gen_xaction() );
+     snprintf( pm->req, sizeof( pm->req ), "{ \\"req\\": \\"num users\\"}" );
+     mbuf->mtype = MT_REQ;
+     
+     msg = rmr_call( mr, msg );
+     if( ! msg ) {               // probably a timeout and no msg received
+         return NULL;            // let errno trickle up
+     } 
+     if( mbuf->state != RMR_OK ) {
+         while( retries_left-- > 0 &&             // loop as long as eagain
+                errno == EAGAIN && 
+                (msg = rmr_call( mr, msg )) != NULL && 
+                mbuf->state != RMR_OK ) {
+             usleep( retry_delay );
+         }
+     
+         if( mbuf == NULL || mbuf->state != RMR_OK ) {
+             rmr_free_msg( mbuf );        // safe if nil
+             return NULL;
+         }
+     }
+     // do something with mbuf
+ 
+ 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_free_msg(3), rmr_init(3), 
+rmr_payload_size(3), rmr_send_msg(3), rmr_rcv_msg(3), 
+rmr_rcv_specific(3), rmr_rts_msg(3), rmr_ready(3), 
+rmr_fib(3), rmr_has_str(3), rmr_set_stimeout(3), 
+rmr_tokenise(3), rmr_mk_ring(3), rmr_ring_free(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_wh_open 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ void rmr_close( void* vctx )
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_close function closes the listen socket effectively 
+cutting the application off. The route table listener is also 
+stopped. Calls to rmr_rcv_msg() will fail with unpredictable 
+error codes, and calls to rmr_send_msg(), rmr_call(), and 
+rmr_rts_msg() will have unknown results. 
+ 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), 
+rmr_get_rcvfd(3), rmr_payload_size(3), rmr_send_msg(3), 
+rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), 
+rmr_ready(3), rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), 
+rmr_mk_ring(3), rmr_ring_free(3), rmr_wh_open(3), 
+rmr_wh_send_msg(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_free_msg 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ void rmr_free_msg( rmr_mbuf_t* mbuf );
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The message buffer is returned to the pool, or the associated 
+memory is released depending on the needs of the underlying 
+messaging system. This allows the user application to release 
+a buffer that is not going to be used. It is safe to pass a 
+nil pointer to this function, and doing so does not result in 
+a change to the value of errrno. 
+ 
+After calling, the user application should **not** use any of 
+the pointers (transaction ID, or payload) which were 
+available. 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_call(3), rmr_init(3), 
+rmr_payload_size(3), rmr_send_msg(3), rmr_rcv_msg(3), 
+rmr_rcv_specific(3), rmr_rts_msg(3), rmr_ready(3), 
+rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), rmr_mk_ring(3), 
+rmr_ring_free(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_get_meid 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ char* rmr_get_meid( rmr_mbuf_t* mbuf, unsigned char* dest )
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_get_meid function will copy the managed equipment ID 
+(meid) field from the message into the *dest* buffer provided 
+by the user. The buffer referenced by * dest * is assumed to 
+be at least RMR_MAX_MEID bytes in length. If * dest * is 
+NULL, then a buffer is allocated (the calling application is 
+expected to free when the buffer is no longer needed). 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+On success, a pointer to the extracted string is returned. If 
+* dest * was supplied, then this is just a pointer to the 
+caller's buffer. If * dest * was NULL, this is a pointer to 
+the allocated buffer. If an error occurs, a nil pointer is 
+returned and errno is set as described below. 
+ 
+ERRORS 
+-------------------------------------------------------------------------------------------- 
+ 
+If an error occurs, the value of the global variable errno 
+will be set to one of the following with the indicated 
+meaning. 
+ 
+ 
+ 
+EINVAL 
+   
+  The message, or an internal portion of the message, was 
+  corrupted or the pointer was invalid. 
+   
+ 
+ENOMEM 
+   
+  A nil pointer was passed for * dest, * however it was not 
+  possible to allocate a buffer using malloc(). 
+ 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_bytes2xact(3), rmr_bytes2meid(3), 
+rmr_call(3), rmr_free_msg(3), rmr_get_rcvfd(3), 
+rmr_get_xact(3), rmr_payload_size(3), rmr_send_msg(3), 
+rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), 
+rmr_ready(3), rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), 
+rmr_mk_ring(3), rmr_ring_free(3), rmr_str2meid(3), 
+rmr_str2xact(3), rmr_wh_open(3), rmr_wh_send_msg(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_get_rcvfd 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ void* rmr_get_rcvfd( void* ctx )
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_get_rcvfd function returns a file descriptor which 
+may be given to epoll_wait() by an application that wishes to 
+use event poll in a single thread rather than block on the 
+arrival of a message via calls to rmr_rcv_msg(). When 
+epoll_wait() indicates that this file descriptor is ready, a 
+call to rmr_rcv_msg() will not block as at least one message 
+has been received. 
+ 
+The context (ctx) pointer passed in is the pointer returned 
+by the call to rmr_init(). 
+ 
+**NOTE:** There is no support for epoll in Nanomsg, thus his 
+function is only supported when linking with the NNG version 
+of RMr and the file descriptor returned when using the 
+Nanomsg verfsion will always return an error. 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_get_rcvfd function returns a file descriptor greater 
+or equal to 0 on success and -1 on error. If this function is 
+called from a user application linked against the Nanomsg RMr 
+library, calls will always return -1 with errno set to 
+EINVAL. 
+ 
+ERRORS 
+-------------------------------------------------------------------------------------------- 
+ 
+The following error values are specifically set by this RMR 
+function. In some cases the error message of a system call is 
+propagated up, and thus this list might be incomplete. 
+ 
+ 
+EINVAL 
+   
+  The use of this function is invalid in this environment. 
+ 
+ 
+EXAMPLE 
+-------------------------------------------------------------------------------------------- 
+ 
+The following short code bit illustrates the use of this 
+function. Error checking has been omitted for clarity. 
+ 
+ 
+:: 
+  
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <sys/epoll.h>
+ #include <rmr/rmr.h>
+ int main() {
+     int rcv_fd;     // pollable fd
+     void* mrc;      //msg router context
+     struct epoll_event events[10];          // support 10 events to poll
+     struct epoll_event epe;                 // event definition for event to listen to
+     int     ep_fd = -1;
+     rmr_mbuf_t* msg = NULL;
+     int nready;
+     int i;
+  
+     mrc = rmr_init( "43086", RMR_MAX_RCV_BYTES, RMRFL_NONE );
+     rcv_fd = rmr_get_rcvfd( mrc );
+  
+     rep_fd = epoll_create1( 0 );    _    B    ,// initialise epoll environment
+     epe.events = EPOLLIN;
+     epe.data.fd = rcv_fd;
+     epoll_ctl( ep_fd, EPOLL_CTL_ADD, rcv_fd, &epe );    // add our info to the mix
+  
+     while( 1 ) {
+         nready = epoll_wait( ep_fd, events, 10, -1 );       // -1 == block forever (no timeout)
+         for( i = 0; i < nready && i < 10; i++ ) {           // loop through to find what is ready
+             if( events[i].data.fd == rcv_fd ) {             // RMr has something
+                 msg = rmr_rcv_msg( mrc, msg );
+                 if( msg ) {
+                     // do something with msg
+                 }
+             }
+  
+             // check for other ready fds....
+         }
+     }
+ }
+ 
+ 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), 
+rmr_payload_size(3), rmr_send_msg(3), rmr_rcv_msg(3), 
+rmr_rcv_specific(3), rmr_rts_msg(3), rmr_ready(3), 
+rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), rmr_mk_ring(3), 
+rmr_ring_free(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_get_src 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ unsigned char* rmr_get_src( rmr_mbuf_t* mbuf, unsigned char* dest )
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_get_src function will copy the *source* information 
+from the message to a buffer (dest) supplied by the user. In 
+an RMr message, the source is the sender's information that 
+is used for return to sender function calls, and is generally 
+the hostname and port in the form *name*. The source might be 
+an IP address port combination; the data is populated by the 
+sending process and the only requirement is that it be 
+capable of being used to start a TCP session with the sender. 
+ 
+The maximum size allowed by RMr is 64 bytes (including the 
+nil string terminator), so the user must ensure that the 
+destination buffer given is at least 64 bytes. 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+On success, a pointer to the destination buffer is given as a 
+convenience to the user programme. On failure, a nil pointer 
+is returned and the value of errno is set. 
+ 
+ERRORS 
+-------------------------------------------------------------------------------------------- 
+ 
+If an error occurs, the value of the global variable errno 
+will be set to one of the following with the indicated 
+meaning. 
+ 
+ 
+ 
+EINVAL 
+   
+  The message, or an internal portion of the message, was 
+  corrupted or the pointer was invalid. 
+ 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_bytes2xact(3), rmr_bytes2meid(3), 
+rmr_call(3), rmr_free_msg(3), rmr_get_rcvfd(3), 
+rmr_get_srcip(3), rmr_payload_size(3), rmr_send_msg(3), 
+rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), 
+rmr_ready(3), rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), 
+rmr_mk_ring(3), rmr_ring_free(3), rmr_str2meid(3), 
+rmr_str2xact(3), rmr_wh_open(3), rmr_wh_send_msg(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_get_srcip 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ unsigned char* rmr_get_srcip( rmr_mbuf_t* mbuf, unsigned char* dest )
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_get_srcip function will copy the *source IP address* 
+from the message to a buffer (dest) supplied by the user. In 
+an RMr message, the source IP address is the sender's 
+information that is used for return to sender function calls; 
+this function makes it available to the user application. The 
+address is maintained as IP:port where *IP* could be either 
+an IPv6 or IPv4 address depending on what was provided by the 
+sending application. 
+ 
+The maximum size allowed by RMr is 64 bytes (including the 
+nil string terminator), so the user must ensure that the 
+destination buffer given is at least 64 bytes. The user 
+application should use the RMr constant RMR_MAX_SRC to ensure 
+that the buffer supplied is large enough, and to protect 
+against future RMr enhancements which might increase the 
+address buffer size requirement. 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+On success, a pointer to the destination buffer is given as a 
+convenience to the user programme. On failure, a nil pointer 
+is returned and the value of errno is set. 
+ 
+ERRORS 
+-------------------------------------------------------------------------------------------- 
+ 
+If an error occurs, the value of the global variable errno 
+will be set to one of the following with the indicated 
+meaning. 
+ 
+ 
+ 
+EINVAL 
+   
+  The message, or an internal portion of the message, was 
+  corrupted or the pointer was invalid. 
+ 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_bytes2xact(3), rmr_bytes2meid(3), 
+rmr_call(3), rmr_free_msg(3), rmr_get_rcvfd(3), 
+rmr_get_src(3), rmr_payload_size(3), rmr_send_msg(3), 
+rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), 
+rmr_ready(3), rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), 
+rmr_mk_ring(3), rmr_ring_free(3), rmr_str2meid(3), 
+rmr_str2xact(3), rmr_wh_open(3), rmr_wh_send_msg(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_get_trace 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ int rmr_get_trace( rmr_mbuf_t* mbuf, unsigned char* dest, int size )
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_get_trace function will copy the trace information 
+from the message into the user's allocated memory referenced 
+by dest. The size parameter is assumed to be the maximum 
+number of bytes which can be copied (size of the destination 
+buffer). 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+On success, the number of bytes actually copied is returned. 
+If the return value is 0, no bytes copied, then the reason 
+could be that the message pointer was nil, or the size 
+parameter was <= 0. 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_tralloc_msg(3), rmr_bytes2xact(3), 
+rmr_bytes2meid(3), rmr_call(3), rmr_free_msg(3), 
+rmr_get_rcvfd(3), rmr_get_trlen(3), rmr_init(3), 
+rmr_init_trace(3), rmr_payload_size(3), rmr_send_msg(3), 
+rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), 
+rmr_ready(3), rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), 
+rmr_mk_ring(3), rmr_ring_free(3), rmr_str2meid(3), 
+rmr_str2xact(3), rmr_wh_open(3), rmr_wh_send_msg(3), 
+rmr_set_trace(3), rmr_trace_ref(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_get_trlen 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ int rmr_get_trlen( rmr_mbuf_t* msg );
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+Given a message buffer, this function returns the amount of 
+space (bytes) that have been allocated for trace data. If no 
+trace data has been allocated, then 0 is returned. 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+The number of bytes allocated for trace information in the 
+given message. 
+ 
+ERRORS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+ 
+INVAL 
+   
+  Parameter(s) passed to the function were not valid. 
+ 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), 
+rmr_get_trace(3), rmr_init(3), rmr_init_trace(3), 
+rmr_send_msg(3), rmr_rcv_msg(3), rmr_rcv_specific(3), 
+rmr_rts_msg(3), rmr_ready(3), rmr_fib(3), rmr_has_str(3), 
+rmr_tokenise(3), rmr_mk_ring(3), rmr_ring_free(3), 
+rmr_set_trace(3), rmr_tralloc_msg(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_get_xact 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ char* rmr_get_xact( rmr_mbuf_t* mbuf, unsigned char* dest )
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_get_xact function will copy the transaction field 
+from the message into the *dest* buffer provided by the user. 
+The buffer referenced by * dest * is assumed to be at least 
+RMR_MAX_XID bytes in length. If * dest * is NULL, then a 
+buffer is allocated (the calling application is expected to 
+free when the buffer is no longer needed). 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+On success, a pointer to the extracted string is returned. If 
+* dest * was supplied, then this is just a pointer to the 
+caller's buffer. If * dest * was NULL, this is a pointer to 
+the allocated buffer. If an error occurs, a nil pointer is 
+returned and errno is set as described below. 
+ 
+ERRORS 
+-------------------------------------------------------------------------------------------- 
+ 
+If an error occurs, the value of the global variable errno 
+will be set to one of the following with the indicated 
+meaning. 
+ 
+ 
+ 
+EINVAL 
+   
+  The message, or an internal portion of the message, was 
+  corrupted or the pointer was invalid. 
+   
+ 
+ENOMEM 
+   
+  A nil pointer was passed for * dest, * however it was not 
+  possible to allocate a buffer using malloc(). 
+ 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_bytes2xact(3), rmr_bytes2meid(3), 
+rmr_call(3), rmr_free_msg(3), rmr_get_rcvfd(3), 
+rmr_get_meid(3), rmr_payload_size(3), rmr_send_msg(3), 
+rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), 
+rmr_ready(3), rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), 
+rmr_mk_ring(3), rmr_ring_free(3), rmr_str2meid(3), 
+rmr_str2xact(3), rmr_wh_open(3), rmr_wh_send_msg(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_init 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ void* rmr_init( char* proto_port, int max_msg_size, int flags );
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_init function prepares the environment for sending 
+and receiving messages. It does so by establishing a worker 
+thread (pthread) which subscribes to a route table generator 
+which provides the necessary routing information for the RMR 
+library to send messages. 
+ 
+*Port* is used to listen for connection requests from other 
+RMR based applications. The value of *max_msg_size* will be 
+used when allocating zero copy send buffers which must be 
+allocated, possibly, prior to the application knowing the 
+actual size of a specific message. 
+ 
+*Flags* allows for selection of some RMr options at the time 
+of initialisation. These are set by ORing RMRFL_ constants 
+from the RMr header file. Currently the following flags are 
+supported: 
+ 
+ 
+ 
+RMRFL_NONE 
+   
+  No flags are set. 
+   
+ 
+RMRFL_NOTHREAD 
+   
+  The route table collector thread is not to be started. 
+  This should only be used by the route table generator 
+  application if it is based on RMr. 
+   
+ 
+RMRFL_MTCALL 
+   
+  Enable multi-threaded call support. 
+ 
+ 
+Multi-threaded Calling 
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
+ 
+The support for an application to issue a *blocking call* by 
+the rmr_call() function was limited such that only user 
+applications which were operating in a single thread could 
+safely use the function. Further, timeouts were message count 
+based and not time unit based. Multi-threaded call support 
+adds the ability for a user application with multiple threads 
+to invoke a blocking call function with the guarentee that 
+the correct response message is delivered to the thread. The 
+additional support is implemented with the * rmr_mt_call() * 
+and * rmr_mt_rcv() * function calls. 
+ 
+Multi-threaded call support requires the user application to 
+specifically enable it when RMr is initialised. This is 
+necessary because a second, dedicated, receiver thread must 
+be started, and requires all messages to be examined and 
+queued by this thread. The additional overhead is minimal, 
+queuing information is all in the RMr message header, but as 
+an additional process is necessary the user application must 
+"opt in" to this approach. 
+ 
+ 
+ENVIRONMENT 
+-------------------------------------------------------------------------------------------- 
+ 
+As a part of the initialisation process rmr_init will look 
+into the available environment variables to influence it's 
+setup. The following variables will be used when found. 
+ 
+ 
+ 
+RMR_SEED_RT 
+   
+  Assumes this is the filename of the seed route table file 
+  to use. In normal situations, the library will wait for an 
+  update from the route table generator (expected within a 
+  few seconds of initialisation) before being able to send 
+  messages. However, in some situations where a bootstrap 
+  table is necessary, this is the means to supply it to the 
+  library. 
+   
+ 
+RMR_RTG_SVC 
+   
+  The route table generator assumes that RMr is listening on 
+  a well known port (4561) by default, but this environment 
+  variable can be used to change the listening port if 
+  needed. The value of the variable is expected to be just 
+  the port. 
+ 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_init function returns a void pointer (a contex if you 
+will) that is passed as the first parameter to nearly all 
+other RMR functions. If rmr_init is unable to properly 
+initialise the environment, NULL is returned and errno is set 
+to an appropriate value. 
+ 
+ERRORS 
+-------------------------------------------------------------------------------------------- 
+ 
+The following error values are specifically set by this RMR 
+function. In some cases the error message of a system call is 
+propagated up, and thus this list might be incomplete. 
+ 
+ 
+ENOMEM 
+   
+  Unable to allocate memory. 
+ 
+ 
+EXAMPLE 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+    void*  uh;
+    rmr_mbuf* buf = NULL;
+    uh = rmr_init( "43086", 4096, 0 );
+    buf = rmr_rcv_msg( uh, buf );
+ 
+ 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), 
+rmr_get_rcvfd(3), rmr_mt_call(3), rmr_mt_rcv(3), 
+rmr_payload_size(3), rmr_send_msg(3), rmr_rcv_msg(3), 
+rmr_rcv_specific(3), rmr_rts_msg(3), rmr_ready(3), 
+rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), rmr_mk_ring(3), 
+rmr_ring_free(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_init_trace 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ void* rmr_init_trace( void* ctx )
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_init_trace function establishes the default trace 
+space placed in each message buffer allocated with 
+rmr_alloc_msg(). If this function is never called, then no 
+trace space is allocated by default into any message buffer. 
+ 
+Trace space allows the user application to pass some trace 
+token, or other data with the message, but outside of the 
+payload. Trace data may be added to any message with 
+rmr_set_trace(), and may be extracted from a message with 
+rmr_get_trace(). The number of bytes that a message contains 
+for/with trace data can be determined by invoking 
+rmr_get_trlen(). 
+ 
+This function may be safely called at any time during the 
+life of the user programme to (re)set the default trace space 
+reserved. If the user programme needs to allocate a message 
+with trace space of a different size than is allocated by 
+default, without fear of extra overhead of reallocating a 
+message later, the rmr_tralloc_msg() function can be used. 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+A value of 1 is returned on success, and 0 on failure. A 
+failure indicates that the RMr context (void *) passed to 
+this function was not valid. 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_tr_alloc_msg(3), rmr_call(3), 
+rmr_free_msg(3), rmr_get_rcvfd(3), rmr_get_trace(3), 
+rmr_get_trlen(3), rmr_payload_size(3), rmr_send_msg(3), 
+rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), 
+rmr_ready(3), rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), 
+rmr_mk_ring(3), rmr_ring_free(3), rmr_set_trace(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_mt_call 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ extern rmr_mbuf_t* rmr_mt_call( void* vctx, rmr_mbuf_t* msg, int id, int timeout );
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_mt_call function sends the user application message 
+to a remote endpoint, and waits for a corresponding response 
+message before returning control to the user application. The 
+user application supplies a completed message buffer, as it 
+would for a rmr_send_msg call, but unlike with a send, the 
+buffer returned will have the response from the application 
+that received the message. The thread invoking the * 
+rmr_mt_call()* will block until a message arrives or until 
+*timeout* milliseconds has passed; which ever comes first. 
+Using a timeout value of zero (0) will cause the thread to 
+block without a timeout. 
+ 
+The * id * supplied as the third parameter is an integer in 
+the range of 2 through 255 inclusive. This is a caller 
+defined "thread number" and is used to match the response 
+message with the correct user application thread. If the ID 
+value is not in the proper range, the attempt to make the 
+call will fail. 
+ 
+Messages which are received while waiting for the response 
+are queued on a *normal* receive queue and will be delivered 
+to the user application with the next invocation of * 
+rmr_mt_rcv() * or * rmr_rvv_msg().* by RMR, and are returned 
+to the user application when rmr_rcv_msg is invoked. These 
+messages are returned in th order received, one per call to 
+rmr_rcv_msg. 
+ 
+NOTE: Currently the multi-threaded functions are supported 
+only when the NNG transport mechanism is being used. It will 
+not be possible to link a programme using the Nanomsg version 
+of the library when references to this function are present. 
+ 
+The Transaction ID 
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
+ 
+The user application is responsible for setting the value of 
+the transaction ID field before invoking *rmr_mt_call.* The 
+transaction ID is a RMR_MAX_XID byte field that is used to 
+match the response message when it arrives. RMr will compare 
+**all** of the bytes in the field, so the caller must ensure 
+that they are set correctly to avoid missing the response 
+message. (The application which returns the response message 
+is also expected to ensure that the return buffer has the 
+matching transaction ID. This can be done transparently if 
+the application uses the * rmr_rts_msg() * function and does 
+not adjust the transaction ID. 
+ 
+Retries 
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
+ 
+The send operations in RMr will retry *soft* send failures 
+until one of three conditions occurs: 
+ 
+ 
+ 
+1. 
+   
+  The message is sent without error 
+   
+ 
+2. 
+   
+  The underlying transport reports a * hard * failure 
+   
+ 
+3. 
+   
+  The maximum number of retry loops has been attempted 
+ 
+ 
+A retry loop consists of approximately 1000 send attemps ** 
+without** any intervening calls to * sleep() * or * usleep(). 
+* The number of retry loops defaults to 1, thus a maximum of 
+1000 send attempts is performed before returning to the user 
+application. This value can be set at any point after RMr 
+initialisation using the * rmr_set_stimeout() * function 
+allowing the user application to completely disable retires 
+(set to 0), or to increase the number of retry loops. 
+ 
+Transport Level Blocking 
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
+ 
+The underlying transport mechanism used to send messages is 
+configured in *non-blocking* mode. This means that if a 
+message cannot be sent immediately the transport mechanism 
+will **not** pause with the assumption that the inability to 
+send will clear quickly (within a few milliseconds). This 
+means that when the retry loop is completely disabled (set to 
+0), that the failure to accept a message for sending by the 
+underlying mechanisms (software or hardware) will be reported 
+immediately to the user application. 
+ 
+It should be noted that depending on the underlying transport 
+mechanism being used, it is extremly possible that during 
+normal operations that retry conditions are very likely to 
+happen. These are completely out of RMr's control, and there 
+is nothing that RMr can do to avoid or midigate these other 
+than by allowing RMr to retry the send operation, and even 
+then it is possible (e.g. during connection reattempts), that 
+a single retry loop is not enough to guarentee a successful 
+send. 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_mt_call function returns a pointer to a message 
+buffer with the state set to reflect the overall state of 
+call processing. If the state is RMR_OK then the buffer 
+contains the response message; otherwise the state indicates 
+the error encountered while attempting to send the message. 
+ 
+If no response message is received when the timeout period 
+has expired, a nil pointer will be returned (NULL). 
+ 
+ERRORS 
+-------------------------------------------------------------------------------------------- 
+ 
+These values are reflected in the state field of the returned 
+message. 
+ 
+ 
+ 
+RMR_OK 
+   
+  The call was successful and the message buffer references 
+  the response message. 
+   
+ 
+RMR_ERR_BADARG 
+   
+  An argument passed to the function was invalid. 
+   
+ 
+RMR_ERR_CALLFAILED 
+   
+  The call failed and the value of *errno,* as described 
+  below, should be checked for the specific reason. 
+   
+ 
+RMR_ERR_NOENDPT 
+   
+  An endpoint associated with the message type could not be 
+  found in the route table. 
+   
+ 
+RMR_ERR_RETRY 
+   
+  The underlying transport mechanism was unable to accept 
+  the message for sending. The user application can retry 
+  the call operation if appropriate to do so. 
+ 
+ 
+The global "variable" *errno* will be set to one of the 
+following values if the overall call processing was not 
+successful. 
+ 
+ 
+ 
+ETIMEDOUT 
+   
+  Too many messages were queued before receiving the 
+  expected response 
+   
+ 
+ENOBUFS 
+   
+  The queued message ring is full, messages were dropped 
+   
+ 
+EINVAL 
+   
+  A parameter was not valid 
+   
+ 
+EAGAIN 
+   
+  The underlying message system wsa interrupted or the 
+  device was busy; the message was **not** sent, and user 
+  application should call this function with the message 
+  again. 
+ 
+ 
+EXAMPLE 
+-------------------------------------------------------------------------------------------- 
+ 
+The following code bit shows one way of using the rmr_mt_call 
+function, and illustrates how the transaction ID must be set. 
+ 
+ 
+:: 
+  
+     int retries_left = 5;               // max retries on dev not available
+     static rmr_mbuf_t*  mbuf = NULL;    // response msg
+     msg_t*  pm;                         // private message (payload)
+     m// get a send buffer and reference the payload 
+     mbuf = rmr_alloc_msg( mr, RMR_MAX_RCV_BYTES );
+     pm = (msg_t*) mbuf->payload;
+     p// generate an xaction ID and fill in payload with data and msg type
+     rmr_bytes2xact( mbuf, xid, RMR_MAX_XID );
+     snprintf( pm->req, sizeof( pm->req ), "{ \\"req\\": \\"num users\\"}" );
+     mbuf->mtype = MT_USR_RESP;
+     
+     msg = rmr_mt_call( mr, msg, my_id, 100 );    e    :// wait up to 100ms
+     if( ! msg ) {               // probably a timeout and no msg received
+         return NULL;            // let errno trickle up
+     } 
+     if( mbuf->state != RMR_OK ) {
+         while( retries_left-- > 0 &&             // loop as long as eagain
+                mbuf->state == RMR_ERR_RETRY && 
+                (msg = rmr_mt_call( mr, msg )) != NULL && 
+                mbuf->state != RMR_OK ) {
+             usleep( retry_delay );
+         }
+     
+         if( mbuf == NULL || mbuf->state != RMR_OK ) {
+             rmr_free_msg( mbuf );        // safe if nil
+             return NULL;
+         }
+     }
+     // do something with mbuf
+ 
+ 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_free_msg(3), rmr_init(3), 
+rmr_mt_rcv(3), rmr_payload_size(3), rmr_send_msg(3), 
+rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), 
+rmr_ready(3), rmr_fib(3), rmr_has_str(3), 
+rmr_set_stimeout(3), rmr_tokenise(3), rmr_mk_ring(3), 
+rmr_ring_free(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_mt_rcv 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ rmr_mbuf_t* rmr_mt_rcv( void* vctx, rmr_mbuf_t* old_msg, int timeout );
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_mt_rcv function blocks until a message is received, 
+or the timeout period (milliseconds) has passed. The result 
+is an RMr message buffer which references a received message. 
+In the case of a timeout the state will be reflected in an 
+"empty buffer" (if old_msg was not nil, or simply with the 
+return of a nil pointer. If a timeout value of zero (0) is 
+given, then the function will block until the next message 
+received. 
+ 
+The *vctx* pointer is the pointer returned by the rmr_init 
+function. *Old_msg* is a pointer to a previously used message 
+buffer or NULL. The ability to reuse message buffers helps to 
+avoid alloc/free cycles in the user application. When no 
+buffer is available to supply, the receive function will 
+allocate one. 
+ 
+The *old_msg* parameter allows the user to pass a previously 
+generated RMr message back to RMr for reuse. Optionally, the 
+user application may pass a nil pointer if no reusable 
+message is available. When a timeout occurs, and old_msg was 
+not nil, the state will be returned by returning a pointer to 
+the old message with the state set. 
+ 
+It is possible to use the *rmr_rcv_msg()* function instead of 
+this function. Doing so might be advantagous if the user 
+programme does not always start the multi-threaded mode and 
+the use of *rmr_rcv_msg()* would make the flow of the code 
+more simple. The advantags of using this function are the 
+ability to set a timeout without using epoll, and a small 
+performance gain (if multi-threaded mode is enabled, and the 
+*rmr_rcv_msg()* function is used, it simply invokes this 
+function without a timeout value, thus there is the small 
+cost of a second call that results). Similarly, the 
+*rmr_torcv_msg()* call can be used when in multi-threaded 
+mode with the same "pass through" overhead to using this 
+function directly. 
+ 
+NOTE: Currently the multi-threaded functions are supported 
+only when the NNG transport mechanism is being used. It will 
+not be possible to link a programme using the nanomsg version 
+of the library when references to this function are present. 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+When a message is received before the timeout period expires, 
+a pointer to the RMr message buffer which describes the 
+message is returned. This will, with a high probability, be a 
+different message buffer than *old_msg;* the user application 
+should not continue to use *old_msg* after it is passed to 
+this function. 
+ 
+In the event of a timeout the return value will be the old 
+msg with the state set, or a nil pointer if no old message 
+was provided. 
+ 
+ERRORS 
+-------------------------------------------------------------------------------------------- 
+ 
+The *state* field in the message buffer will be set to one of 
+the following values: 
+ 
+ 
+ 
+RMR_OK 
+   
+  The message was received without error. 
+   
+ 
+RMR_ERR_BADARG 
+   
+  A parameter passed to the function was not valid (e.g. a 
+  nil pointer). indicate either RMR_OK or RMR_ERR_EMPTY if 
+  an empty message was received. 
+   
+ 
+RMR_ERR_EMPTY 
+   
+  The message received had no associated data. The length of 
+  the message will be 0. 
+   
+ 
+RMR_ERR_NOTSUPP 
+   
+  The multi-threaded option was not enabled when RMr was 
+  initialised. See the man page for *rmr_init() * for 
+  details. 
+   
+ 
+RMR_ERR_RCVFAILED 
+   
+  A hard error occurred preventing the receive from 
+  completing. 
+ 
+When a nil pointer is returned, or any other state value was 
+set in the message buffer, errno will be set to one of the 
+following: 
+ 
+ 
+ 
+INVAL 
+   
+  Parameter(s) passed to the function were not valid. 
+   
+ 
+EBADF 
+   
+  The underlying message transport is unable to process the 
+  request. 
+   
+ 
+ENOTSUP 
+   
+  The underlying message transport is unable to process the 
+  request. 
+   
+ 
+EFSM 
+   
+  The underlying message transport is unable to process the 
+  request. 
+   
+ 
+EAGAIN 
+   
+  The underlying message transport is unable to process the 
+  request. 
+   
+ 
+EINTR 
+   
+  The underlying message transport is unable to process the 
+  request. 
+   
+ 
+ETIMEDOUT 
+   
+  The underlying message transport is unable to process the 
+  request. 
+   
+ 
+ETERM 
+   
+  The underlying message transport is unable to process the 
+  request. 
+ 
+ 
+EXAMPLE 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+ 
+:: 
+  
+     rmr_mbuf_t*  mbuf = NULL;   // received msg
+     msg = rmr_mt_recv( mr, mbuf, 100 );     // wait up to 100ms
+     if( msg != NULL ) {
+         switch( msg->state ) {
+             case RMR_OK:
+                 printf( "got a good message\\n" );
+                 break;
+             case RMR_ERR_EMPTY:
+                 printf( "received timed out\\n" );
+                 break;
+             default:
+                 printf( "receive error: %d\\n", mbuf->state );
+                 break;
+         }
+     } else {
+         printf( "receive timeout (nil)\\n" );
+     }
+ 
+ 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), 
+rmr_get_rcvfd(3), rmr_init(3), rmr_mk_ring(3), 
+rmr_mt_call(3), rmr_payload_size(3), rmr_send_msg(3), 
+rmr_torcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), 
+rmr_ready(3), rmr_ring_free(3), rmr_torcv_msg(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_payload_size 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ int rmr_payload_size( rmr_mbuf_t* msg );
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+Given a message buffer, this function returns the amount of 
+space (bytes) available for the user application to consume 
+in the message payload. This is different than the message 
+length available as a field in the message buffer. 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+The number of bytes available in the payload. 
+ 
+ERRORS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+ 
+INVAL 
+   
+  Parameter(s) passed to the function were not valid. 
+ 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), rmr_init(3), 
+rmr_send_msg(3), rmr_rcv_msg(3), rmr_rcv_specific(3), 
+rmr_rts_msg(3), rmr_ready(3), rmr_fib(3), rmr_has_str(3), 
+rmr_tokenise(3), rmr_mk_ring(3), rmr_ring_free(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_rcv_msg 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ rmr_mbuf_t* rmr_rcv_msg( void* vctx, rmr_mbuf_t* old_msg );
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_rcv_msg function blocks until a message is received, 
+returning the message to the caller via a pointer to a 
+rmr_mbuf_t structure type. If messages were queued while 
+waiting for the response to a previous invocation of 
+rmr_call, the oldest message is removed from the queue and 
+returned without delay. 
+ 
+The *vctx* pointer is the pointer returned by the rmr_init 
+function. *Old_msg* is a pointer to a previously used message 
+buffer or NULL. The ability to reuse message buffers helps to 
+avoid alloc/free cycles in the user application. When no 
+buffer is available to supply, the receive function will 
+allocate one. 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+The function returns a pointer to the rmr_mbuf_t structure 
+which references the message information (state, length, 
+payload), or a NULL pointer in the case of an extreme error. 
+ 
+ERRORS 
+-------------------------------------------------------------------------------------------- 
+ 
+The *state* field in the message buffer will indicate either 
+RMR_OK or RMR_ERR_EMPTY if an empty message was received. If 
+a nil pointer is returned, or any other state value was set 
+in the message buffer, errno will be set to one of the 
+following: 
+ 
+ 
+ 
+INVAL 
+   
+  Parameter(s) passed to the function were not valid. 
+   
+ 
+EBADF 
+   
+  The underlying message transport is unable to process the 
+  request. 
+   
+ 
+ENOTSUP 
+   
+  The underlying message transport is unable to process the 
+  request. 
+   
+ 
+EFSM 
+   
+  The underlying message transport is unable to process the 
+  request. 
+   
+ 
+EAGAIN 
+   
+  The underlying message transport is unable to process the 
+  request. 
+   
+ 
+EINTR 
+   
+  The underlying message transport is unable to process the 
+  request. 
+   
+ 
+ETIMEDOUT 
+   
+  The underlying message transport is unable to process the 
+  request. 
+   
+ 
+ETERM 
+   
+  The underlying message transport is unable to process the 
+  request. 
+ 
+ 
+EXAMPLE 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), 
+rmr_get_rcvfd(3), rmr_init(3), rmr_mk_ring(3), 
+rmr_payload_size(3), rmr_send_msg(3), rmr_torcv_msg(3), 
+rmr_rcv_specific(3), rmr_rts_msg(3), rmr_ready(3), 
+rmr_ring_free(3), rmr_torcv_msg(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_ready 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ int rmr_ready( void* vctx );
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_ready function checks to see if a routing table has 
+been successfully received and installed. The return value 
+indicates the state of readiness. 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+A return value of 1 (true) indicates that the routing table 
+is in place and attempts to send messages can be made. When 0 
+is returned (false) the routing table has not been received 
+and thus attempts to send messages will fail with *no 
+endpoint* errors. 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), rmr_init(3), 
+rmr_payload_size(3), rmr_send_msg(3), rmr_rcv_msg(3), 
+rmr_rcv_specific(3), rmr_rts_msg(3), rmr_fib(3), 
+rmr_has_str(3), rmr_tokenise(3), rmr_mk_ring(3), 
+rmr_ring_free(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_realloc_payload 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ extern rmr_mbuf_t* rmr_realloc_payload( rmr_mbuf_t* msg, int new_len, int copy, int clone );
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_realloc_payload function will return a pointer to an 
+RMR message buffer struct (rmr_mbuf_t) which has a payload 
+large enough to accomodate *new_len* bytes. If necessary, the 
+underlying payload is reallocated, and the bytes from the 
+original payload are copied if the *copy* parameter is true 
+(1). If the message passed in has a payload large enough, 
+there is no additional memory allocation and copying. 
+ 
+Cloning The Message Buffer 
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
+ 
+This function can also be used to generate a separate copy of 
+the original message, with the desired payload size, without 
+destroying the original message buffer or the original 
+payload. A standalone copy is made only when the *clone* 
+parameter is true (1). When cloning, the payload is copied to 
+the cloned message **only** if the *copy* parameter is true. 
+ 
+Message Buffer Metadata 
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
+ 
+The metadata in the original message buffer (message type, 
+subscription ID, and payload length) will be preserved if the 
+*copy* parameter is true. When this parameter is not true 
+(0), then these values are set to the uninitialised value 
+(-1) for type and ID, and the length is set to 0. 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_realloc_payload function returns a pointer to the 
+message buffer with the payload which is large enough to hold 
+*new_len* bytes. If the *clone* option is true, this will be 
+a pointer to the newly cloned message buffer; the original 
+message buffer pointer may still be used to referenced that 
+message. It is the calling application's responsibility to 
+free the memory associateed with both messages using the 
+rmr_free_msg() function. 
+ 
+When the *clone* option is not used, it is still good 
+practice by the calling application to capture and use this 
+reference as it is possible that the message buffer, and not 
+just the payload buffer, was reallocated. In the event of an 
+error, a nil pointer will be returned and the value of 
+*errno* will be set to reflect the problem. 
+ 
+ERRORS 
+-------------------------------------------------------------------------------------------- 
+ 
+These value of *errno* will reflect the error condition if a 
+nil pointer is returned: 
+ 
+ 
+ 
+ENOMEM 
+   
+  Memory allocation of the new payload failed. 
+   
+ 
+EINVAL 
+   
+  The pointer passed in was nil, or refrenced an invalid 
+  message, or the required length was not valid. 
+ 
+ 
+EXAMPLE 
+-------------------------------------------------------------------------------------------- 
+ 
+The following code bit illustrates how this function can be 
+used to reallocate a buffer for a return to sender 
+acknowledgement message which is larger than the message 
+received. 
+ 
+ 
+:: 
+  
+   if( rmr_payload_size( msg ) < ack_sz ) {              // received message too small for ack
+     msg = rmr_realloc_payload( msg, ack_sz, 0, 0 );     // reallocate the message with a payload big enough
+     if( msg == NULL ) {
+       fprintf( stderr, "[ERR] realloc returned a nil pointer: %s\\n", strerror( errno ) );
+     } else {
+     }    e// populate and send ack message
+     }}
+ }
+ 
+ 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_free_msg(3), rmr_init(3), 
+rmr_payload_size(3), rmr_send_msg(3), rmr_rcv_msg(3), 
+rmr_rcv_specific(3), rmr_rts_msg(3), rmr_ready(3), 
+rmr_fib(3), rmr_has_str(3), rmr_set_stimeout(3), 
+rmr_tokenise(3), rmr_mk_ring(3), rmr_ring_free(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_rts_msg 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ rmr_mbuf_t*  rmr_rts_msg( void* vctx, rmr_mbuf_t* msg );
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_rts_msg function sends a message returning it to the 
+endpoint which sent the message rather than selecting an 
+endpoint based on the message type and routing table. Other 
+than this small difference, the behaviour is exactly the same 
+as rmr_send_msg. 
+ 
+Retries 
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
+ 
+The send operations in RMr will retry *soft* send failures 
+until one of three conditions occurs: 
+ 
+ 
+ 
+1. 
+   
+  The message is sent without error 
+   
+ 
+2. 
+   
+  The underlying transport reports a * hard * failure 
+   
+ 
+3. 
+   
+  The maximum number of retry loops has been attempted 
+ 
+ 
+A retry loop consists of approximately 1000 send attemps ** 
+without** any intervening calls to * sleep() * or * usleep(). 
+* The number of retry loops defaults to 1, thus a maximum of 
+1000 send attempts is performed before returning to the user 
+application. This value can be set at any point after RMr 
+initialisation using the * rmr_set_stimeout() * function 
+allowing the user application to completely disable retires 
+(set to 0), or to increase the number of retry loops. 
+ 
+Transport Level Blocking 
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
+ 
+The underlying transport mechanism used to send messages is 
+configured in *non-blocking* mode. This means that if a 
+message cannot be sent immediately the transport mechanism 
+will **not** pause with the assumption that the inability to 
+send will clear quickly (within a few milliseconds). This 
+means that when the retry loop is completely disabled (set to 
+0), that the failure to accept a message for sending by the 
+underlying mechanisms (software or hardware) will be reported 
+immediately to the user application. 
+ 
+It should be noted that depending on the underlying transport 
+mechanism being used, it is extremly possible that during 
+normal operations that retry conditions are very likely to 
+happen. These are completely out of RMr's control, and there 
+is nothing that RMr can do to avoid or midigate these other 
+than by allowing RMr to retry the send operation, and even 
+then it is possible (e.g. during connection reattempts), that 
+a single retry loop is not enough to guarentee a successful 
+send. 
+ 
+PAYLOAD SIZE 
+-------------------------------------------------------------------------------------------- 
+ 
+When crafting a response based on a received message, the 
+user application must take care not to write more bytes to 
+the message payload than the allocated message has. In the 
+case of a received message, it is possible that the response 
+needs to be larger than the payload associated with the 
+inbound message. In order to use the return to sender 
+function, the source infomration in the orignal message must 
+be present in the response; information which cannot be added 
+to a message buffer allocated through the standard RMR 
+allocation function. To allocate a buffer with a larger 
+payload, and which retains the necessary sender data needed 
+by this function, the *rmr_realloc_payload()* function must 
+be used to extend the payload to a size suitable for the 
+response. 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+On success, a new message buffer, with an empty payload, is 
+returned for the application to use for the next send. The 
+state in this buffer will reflect the overall send operation 
+state and should be RMR_OK. 
+ 
+If the state in the returned buffer is anything other than 
+UT_OK, the user application may need to attempt a 
+retransmission of the message, or take other action depending 
+on the setting of errno as described below. 
+ 
+In the event of extreme failure, a NULL pointer is returned. 
+In this case the value of errno might be of some use, for 
+documentation, but there will be little that the user 
+application can do other than to move on. 
+ 
+ERRORS 
+-------------------------------------------------------------------------------------------- 
+ 
+The following values may be passed back in the *state* field 
+of the returned message buffer. 
+ 
+ 
+ 
+RMR_ERR_BADARG 
+   
+  The message buffer pointer did not refer to a valid 
+  message. 
+ 
+RMR_ERR_NOHDR 
+   
+  The header in the message buffer was not valid or 
+  corrupted. 
+ 
+RMR_ERR_NOENDPT 
+   
+  The message type in the message buffer did not map to a 
+  known endpoint. 
+ 
+RMR_ERR_SENDFAILED 
+   
+  The send failed; errno has the possible reason. 
+ 
+ 
+The following values may be assigned to errno on failure. 
+ 
+ 
+INVAL 
+   
+  Parameter(s) passed to the function were not valid, or the 
+  underlying message processing environment was unable to 
+  interpret the message. 
+   
+ 
+ENOKEY 
+   
+  The header information in the message buffer was invalid. 
+   
+ 
+ENXIO 
+   
+  No known endpoint for the message could be found. 
+   
+ 
+EMSGSIZE 
+   
+  The underlying transport refused to accept the message 
+  because of a size value issue (message was not attempted 
+  to be sent). 
+   
+ 
+EFAULT 
+   
+  The message referenced by the message buffer is corrupt 
+  (NULL pointer or bad internal length). 
+   
+ 
+EBADF 
+   
+  Internal RMR error; information provided to the message 
+  transport environment was not valid. 
+   
+ 
+ENOTSUP 
+   
+  Sending was not supported by the underlying message 
+  transport. 
+   
+ 
+EFSM 
+   
+  The device is not in a state that can accept the message. 
+   
+ 
+EAGAIN 
+   
+  The device is not able to accept a message for sending. 
+  The user application should attempt to resend. 
+   
+ 
+EINTR 
+   
+  The operation was interrupted by delivery of a signal 
+  before the message was sent. 
+   
+ 
+ETIMEDOUT 
+   
+  The underlying message environment timed out during the 
+  send process. 
+   
+ 
+ETERM 
+   
+  The underlying message environment is in a shutdown state. 
+ 
+ 
+EXAMPLE 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), rmr_init(3), 
+rmr_payload_size(3), rmr_send_msg(3), rmr_rcv_msg(3), 
+rmr_rcv_specific(3), rmr_ready(3), rmr_fib(3), 
+rmr_has_str(3), rmr_set_stimeout(3), rmr_tokenise(3), 
+rmr_mk_ring(3), rmr_ring_free(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_send_msg 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ rmr_mbuf_t* rmr_send_msg( void* vctx, rmr_mbuf_t* msg );
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_send_msg function accepts a message buffer from the 
+user application and attempts to send it. The destination of 
+the message is selected based on the message type specified 
+in the message buffer, and the matching information in the 
+routing tables which are currently in use by the RMR library. 
+This may actually result in the sending of the message to 
+multiple destinations which could degrade expected overall 
+performance of the user application. (Limiting excessive 
+sending of messages is the responsibility of the 
+application(s) responsible for building the routing table 
+used by the RMR library, and not the responsibility of the 
+library.) 
+ 
+Retries 
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
+ 
+The send operations in RMr will retry *soft* send failures 
+until one of three conditions occurs: 
+ 
+ 
+ 
+1. 
+   
+  The message is sent without error 
+   
+ 
+2. 
+   
+  The underlying transport reports a * hard * failure 
+   
+ 
+3. 
+   
+  The maximum number of retry loops has been attempted 
+ 
+ 
+A retry loop consists of approximately 1000 send attemps ** 
+without** any intervening calls to * sleep() * or * usleep(). 
+* The number of retry loops defaults to 1, thus a maximum of 
+1000 send attempts is performed before returning to the user 
+application. This value can be set at any point after RMr 
+initialisation using the * rmr_set_stimeout() * function 
+allowing the user application to completely disable retires 
+(set to 0), or to increase the number of retry loops. 
+ 
+Transport Level Blocking 
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
+ 
+The underlying transport mechanism used to send messages is 
+configured in *non-blocking* mode. This means that if a 
+message cannot be sent immediately the transport mechanism 
+will **not** pause with the assumption that the inability to 
+send will clear quickly (within a few milliseconds). This 
+means that when the retry loop is completely disabled (set to 
+0), that the failure to accept a message for sending by the 
+underlying mechanisms (software or hardware) will be reported 
+immediately to the user application. 
+ 
+It should be noted that depending on the underlying transport 
+mechanism being used, it is extremly possible that during 
+normal operations that retry conditions are very likely to 
+happen. These are completely out of RMr's control, and there 
+is nothing that RMr can do to avoid or midigate these other 
+than by allowing RMr to retry the send operation, and even 
+then it is possible (e.g. during connection reattempts), that 
+a single retry loop is not enough to guarentee a successful 
+send. 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+On success, a new message buffer, with an empty payload, is 
+returned for the application to use for the next send. The 
+state in this buffer will reflect the overall send operation 
+state and should be RMR_OK. 
+ 
+When the message cannot be successfully sent this function 
+will return the unsent (original) message buffer with the 
+state set to indicate the reason for failure. The value of * 
+errno * may also be set to reflect a more detailed failure 
+reason if it is known. 
+ 
+In the event of extreme failure, a NULL pointer is returned. 
+In this case the value of errno might be of some use, for 
+documentation, but there will be little that the user 
+application can do other than to move on. 
+ 
+ERRORS 
+-------------------------------------------------------------------------------------------- 
+ 
+The following values may be passed back in the *state* field 
+of the returned message buffer. 
+ 
+ 
+ 
+RMR_RETRY 
+   
+  The message could not be sent, but the underlying 
+  transport mechanism indicates that the failure is 
+  temporary. If the send operation is tried again it might 
+  be successful. 
+ 
+RMR_SEND_FAILED 
+   
+  The send operation was not successful and the underlying 
+  transport mechanism indicates a permanent (hard) failure; 
+  retrying the send is not possible. 
+ 
+RMR_ERR_BADARG 
+   
+  The message buffer pointer did not refer to a valid 
+  message. 
+ 
+RMR_ERR_NOHDR 
+   
+  The header in the message buffer was not valid or 
+  corrupted. 
+ 
+RMR_ERR_NOENDPT 
+   
+  The message type in the message buffer did not map to a 
+  known endpoint. 
+ 
+ 
+The following values may be assigned to errno on failure. 
+ 
+ 
+INVAL 
+   
+  Parameter(s) passed to the function were not valid, or the 
+  underlying message processing environment was unable to 
+  interpret the message. 
+   
+ 
+ENOKEY 
+   
+  The header information in the message buffer was invalid. 
+   
+ 
+ENXIO 
+   
+  No known endpoint for the message could be found. 
+   
+ 
+EMSGSIZE 
+   
+  The underlying transport refused to accept the message 
+  because of a size value issue (message was not attempted 
+  to be sent). 
+   
+ 
+EFAULT 
+   
+  The message referenced by the message buffer is corrupt 
+  (NULL pointer or bad internal length). 
+   
+ 
+EBADF 
+   
+  Internal RMR error; information provided to the message 
+  transport environment was not valid. 
+   
+ 
+ENOTSUP 
+   
+  Sending was not supported by the underlying message 
+  transport. 
+   
+ 
+EFSM 
+   
+  The device is not in a state that can accept the message. 
+   
+ 
+EAGAIN 
+   
+  The device is not able to accept a message for sending. 
+  The user application should attempt to resend. 
+   
+ 
+EINTR 
+   
+  The operation was interrupted by delivery of a signal 
+  before the message was sent. 
+   
+ 
+ETIMEDOUT 
+   
+  The underlying message environment timed out during the 
+  send process. 
+   
+ 
+ETERM 
+   
+  The underlying message environment is in a shutdown state. 
+ 
+ 
+EXAMPLE 
+-------------------------------------------------------------------------------------------- 
+ 
+The following is a simple example of how the rmr_send_msg 
+function is called. In this example, the send message buffer 
+is saved between calls and reused eliminating alloc/free 
+cycles. 
+ 
+ 
+:: 
+  
+     static rmr_mbuf_t*  send_msg = NULL;        // message to send; reused on each call
+     msg_t*  send_pm;                            // payload for send
+     msg_t*  pm;                                 // our message format in the received payload
+     mif( send_msg  == NULL ) {
+         send_msg = rmr_alloc_msg( mr, MAX_SIZE );    r// new buffer to send
+      }
+      // reference payload and fill in message type
+     pm = (msg_t*) send_msg->payload;
+     send_msg->mtype = MT_ANSWER;    
+     msg->len = generate_data( pm );         e// something that fills the payload in
+     msg = rmr_send_msg( mr, send_msg );
+     mif( ! msg ) {
+     m    !return ERROR;
+     m} else {
+     m    sif( msg->state != RMR_OK ) {
+     m    s    m// check for eagain, and resend if needed
+     m    s    m// else return error
+     m    s}
+     m}
+     mreturn OK;
+     m    r    ;
+ 
+ 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), rmr_init(3), 
+rmr_payload_size(3), rmr_rcv_msg(3), rmr_rcv_specific(3), 
+rmr_rts_msg(3), rmr_ready(3), rmr_mk_ring(3), 
+rmr_ring_free(3), rmr_torcv_rcv(3), rmr_wh_send_msg(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_set_stimeout 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ rmr_mbuf_t* rmr_set_stimeout( void* vctx, int rloops );
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_set_stimeout function sets the configuration for how 
+RMr will retry message send operations which complete with 
+either a * timeout * or * again * completion value. (Send 
+operations include all of the possible message send 
+functions: * rmr_send_msg(), rmr_call(), rmr_rts_msg() * and 
+* rmr_wh_send_msg(). * The * rloops * parameter sets the 
+maximum number of retry loops that will be attempted before 
+giving up and returning the unsuccessful state to the user 
+application. Each retry loop is approximately 1000 attempts, 
+and RMr does ** not ** invoke any sleep function between 
+retries in the loop; a small, 1 mu-sec, sleep is executed 
+between loop sets if the * rloops * value is greater than 1. 
+ 
+ 
+Disabling Retries 
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
+ 
+By default, the send operations will execute with an * rloop 
+* setting of 1; each send operation will attempt to resend 
+the message approximately 1000 times before giving up. If the 
+user application does not want to have send operations retry 
+when the underlying transport mechanism indicates * timeout * 
+or * again, * the application should invoke this function and 
+pass a value of 0 (zero) for * rloops. * With this setting, 
+all RMr send operations will attempt a send operation only ** 
+once, ** returning immediately to the caller with the state 
+of that single attempt. 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+This function returns a -1 to indicate that the * rloops * 
+value could not be set, and the value * RMR_OK * to indicate 
+success. 
+ 
+ERRORS 
+-------------------------------------------------------------------------------------------- 
+ 
+Currently errno is ** not ** set by this function; the only 
+cause of a failure is an invalid context (* vctx *) pointer. 
+ 
+EXAMPLE 
+-------------------------------------------------------------------------------------------- 
+ 
+The following is a simple example of how the rmr_set_stimeout 
+function is called. 
+ 
+ 
+:: 
+  
+     #define NO_FLAGS    0
+     char*    Oport = "43086";     // port for message router listen
+     int         rmax_size = 4096;    // max message size for default allocations
+     void*     mr_context;         // message router context
+     mr_context = rmr_init( port, max_size, NO_FLAGS );
+     if( mr_context != NULL ) {
+         rmr_set_stimeout( mr_context, 0 );    // turn off retries
+     }
+ 
+ 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), rmr_init(3), 
+rmr_payload_size(3), rmr_rcv_msg(3), rmr_rcv_specific(3), 
+rmr_rts_msg(3), rmr_ready(3), rmr_mk_ring(3), 
+rmr_ring_free(3), rmr_send_msg(3), rmr_torcv_rcv(3), 
+rmr_wh_send_msg(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_set_trace 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ int rmr_bytes2payload( rmr_mbuf_t* mbuf, unsigned char* data, int len )
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_set_trace function will copy len bytes from data into 
+the trace portion of mbuf. If the trace area of mbuf is not 
+the correct size, the message buffer will be reallocated to 
+ensure that enough space is available for the trace data. 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_set_trace function returns the number of bytes 
+successfully copied to the message. If 0 is returned either 
+the message pointer was nil, or the size in the parameters 
+was <= 0. 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_tralloc_msg(3), rmr_bytes2xact(3), 
+rmr_bytes2payload(3), rmr_call(3), rmr_free_msg(3), 
+rmr_get_rcvfd(3), rmr_get_meid(3), rmr_get_trace(3), 
+rmr_get_trlen(3), rmr_init(3), rmr_init_trace(3), 
+rmr_payload_size(3), rmr_send_msg(3), rmr_rcv_msg(3), 
+rmr_rcv_specific(3), rmr_rts_msg(3), rmr_ready(3), 
+rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), rmr_mk_ring(3), 
+rmr_ring_free(3), rmr_str2meid(3), rmr_str2xact(3), 
+rmr_wh_open(3), rmr_wh_send_msg(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_str2meid 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ int rmr_str2meid( rmr_mbuf_t* mbuf, unsigned char* src, int len )
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_str2meid function will copy the string pointed to by 
+src to the managed equipment ID (meid) field in the given 
+message. The field is a fixed length, gated by the constant 
+RMR_MAX_MEID and if string length is larger than this value, 
+then **nothing** will be copied. (Note, this differs slightly 
+from the behaviour of the lrmr_bytes2meid() function.) 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+On success, the value RMR_OK is returned. If the string 
+cannot be copied to the message, the return value will be one 
+of the errors listed below. 
+ 
+ERRORS 
+-------------------------------------------------------------------------------------------- 
+ 
+If the return value is not RMR_OK, then it will be set to one 
+of the values below. 
+ 
+ 
+ 
+RMR_ERR_BADARG 
+   
+  The message, or an internal portion of the message, was 
+  corrupted or the pointer was invalid. 
+   
+ 
+RMR_ERR_OVERFLOW 
+   
+  The length passed in was larger than the maximum length of 
+  the field; only a portion of the source bytes were copied. 
+ 
+ 
+EXAMPLE 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), 
+rmr_get_meid(3), rmr_get_rcvfd(3), rmr_payload_size(3), 
+rmr_send_msg(3), rmr_rcv_msg(3), rmr_rcv_specific(3), 
+rmr_rts_msg(3), rmr_ready(3), rmr_fib(3), rmr_has_str(3), 
+rmr_tokenise(3), rmr_mk_ring(3), rmr_ring_free(3), 
+rmr_bytes2meid(3), rmr_wh_open(3), rmr_wh_send_msg(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_str2xact 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ int rmr_str2xact( rmr_mbuf_t* mbuf, unsigned char* src, int len )
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_str2xact function will copy the string pointed to by 
+src to the transaction ID (xaction) field in the given 
+message. The field is a fixed length, gated by the constant 
+RMR_MAX_XID and if string length is larger than this value, 
+then **nothing** will be copied. (Note, this differs slightly 
+from the behaviour of the lrmr_bytes2xact() function.) 
+ 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+On success, the value RMR_OK is returned. If the string 
+cannot be copied to the message, the return value will be 
+one of the errors listed below. 
+ 
+ERRORS 
+-------------------------------------------------------------------------------------------- 
+ 
+If the return value is not RMR_OK, then it will be set to 
+one of the values below. 
+ 
+ 
+RMR_ERR_BADARG 
+   
+  The message, or an internal portion of the message, was 
+  corrupted or the pointer was invalid. 
+   
+ 
+RMR_ERR_OVERFLOW 
+   
+  The length passed in was larger than the maximum length of 
+  the field; only a portion of the source bytes were copied. 
+ 
+ 
+EXAMPLE 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_bytes2meid(3), rmr_bytes2xact(3), 
+rmr_call(3), rmr_free_msg(3), rmr_get_meid(3), 
+rmr_get_rcvfd(3), rmr_get_xact(3), rmr_payload_size(3), 
+rmr_send_msg(3), rmr_rcv_msg(3), rmr_rcv_specific(3), 
+rmr_rts_msg(3), rmr_ready(3), rmr_fib(3), rmr_has_str(3), 
+rmr_tokenise(3), rmr_mk_ring(3), rmr_ring_free(3), 
+rmr_str2meid(3), rmr_wh_open(3), rmr_wh_send_msg(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+RMR support functions 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ #include <rmr/ring_inline.h>
+ char* rmr_fib( char* fname );
+ int rmr_has_str( char const* buf, char const* str, char sep, int max );
+ int rmr_tokenise( char* buf, char** tokens, int max, char sep );
+ void* rmr_mk_ring( int size );
+ void rmr_ring_free( void* vr );
+ static inline void* rmr_ring_extract( void* vr )
+ static inline int rmr_ring_insert( void* vr, void* new_data )
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+These functions support the RMR library, and are made 
+available to user applications as some (e.g. route table 
+generators) might need and/or want to make use of them. The 
+rmr_fib function accepts a file name and reads the entire 
+file into a single buffer. The intent is to provide an easy 
+way to load a static route table without a lot of buffered 
+I/O hoops. 
+ 
+The rmr_has_str function accepts a *buffer* containing a set 
+of delimited tokens (e.g. foo,bar,goo) and returns true if 
+the target string, *str,* matches one of the tokens. The 
+*sep* parameter provides the separation character in the 
+buffer (e.g a comma) and *max* indicates the maximum number 
+of tokens to split the buffer into before checking. 
+ 
+The rmr_tokenise function is a simple tokeniser which splits 
+*buf* into tokens at each occurrence of *sep*. Multiple 
+occurrences of the separator character (e.g. a,,b) result in 
+a nil token. Pointers to the tokens are placed into the 
+*tokens* array provided by the caller which is assumed to 
+have at least enough space for *max* entries. 
+ 
+The rmr_mk_ring function creates a buffer ring with *size* 
+entries. 
+ 
+The rmr_ring_free function accepts a pointer to a ring 
+context and frees the associated memory. 
+ 
+The rmr_ring_insert and rmr_ring_extract functions are 
+provided as static inline functions via the 
+*rmr/ring_inline.h* header file. These functions both accept 
+the ring *context* returned by mk_ring, and either insert a 
+pointer at the next available slot (tail) or extract the data 
+at the head. 
+ 
+RETURN VALUES 
+-------------------------------------------------------------------------------------------- 
+ 
+The following are the return values for each of these 
+functions. 
+ 
+The rmr_fib function returns a pointer to the buffer 
+containing the contents of the file. The buffer is terminated 
+with a single nil character (0) making it a legitimate C 
+string. If the file was empty or nonexistent, a buffer with 
+an immediate nil character. If it is important to the calling 
+programme to know if the file was empty or did not exist, the 
+caller should use the system stat function call to make that 
+determination. 
+ 
+The rmr_has_str function returns 1 if *buf* contains the 
+token referenced by &ita and false (0) if it does not. On 
+error, a -1 value is returned and errno is set accordingly. 
+ 
+The rmr_tokenise function returns the actual number of token 
+pointers placed into *tokens* 
+ 
+The rmr_mk_ring function returns a void pointer which is the 
+*context* for the ring. 
+ 
+The rmr_ring_insert function returns 1 if the data was 
+successfully inserted into the ring, and 0 if the ring is 
+full and the pointer could not be deposited. 
+ 
+The rmr_ring_extract will return the data which is at the 
+head of the ring, or NULL if the ring is empty. 
+ 
+ERRORS 
+-------------------------------------------------------------------------------------------- 
+ 
+Not many of these functions set the value in errno, however 
+the value may be one of the following: 
+ 
+ 
+INVAL 
+   
+  Parameter(s) passed to the function were not valid. 
+ 
+ 
+EXAMPLE 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), rmr_init(3), 
+rmr_payload_size(3), rmr_send_msg(3), rmr_rcv_msg(3), 
+rmr_rcv_specific(3), rmr_rts_msg(3), rmr_ready(3), 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_torcv_msg 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ rmr_mbuf_t* rmr_torcv_msg( void* vctx, rmr_mbuf_t* old_msg, int ms_to );
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_torcv_msg function will pause for *ms_to* 
+milliseconds waiting for a message to arrive. If a message 
+arrives before the timeout expires the message buffer 
+returned will have a status of RMR_OK and the payload will 
+contain the data received. If the timeout expires before the 
+message is received, the status will have the value 
+RMR_ERR_TIMEOUT. When a received message is returned the 
+message buffer will also contain the message type and length 
+set by the sender. If messages were queued while waiting for 
+the response to a previous invocation of rmr_call, the oldest 
+message is removed from the queue and returned without delay. 
+ 
+The *vctx* pointer is the pointer returned by the rmr_init 
+function. *Old_msg* is a pointer to a previously used message 
+buffer or NULL. The ability to reuse message buffers helps to 
+avoid alloc/free cycles in the user application. When no 
+buffer is available to supply, the receive function will 
+allocate one. 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+The function returns a pointer to the rmr_mbuf_t structure 
+which references the message information (state, length, 
+payload), or a NULL pointer in the case of an extreme error. 
+ 
+ERRORS 
+-------------------------------------------------------------------------------------------- 
+ 
+The *state* field in the message buffer will be one of the 
+following: 
+ 
+ 
+ 
+RMR_OK 
+   
+  The message buffer (payload) references the received data. 
+   
+ 
+RMR_ERR_INITFAILED 
+   
+  The first call to this function must initialise an 
+  underlying system notification mechanism. On failure, this 
+  error is returned and errno will have the system error 
+  status set. If this function fails to intialise, the poll 
+  mechansim, it is likely that message receives will never 
+  be successful. 
+   
+ 
+RMR_ERR_TIMEOUT 
+   
+  The timeout expired before a complete message was 
+  received. All other fields in the message buffer are not 
+  valid. 
+   
+ 
+RMR_ERR_EMPTY 
+   
+  A message was received, but it had no payload. All other 
+  fields in the message buffer are not valid. 
+ 
+ 
+ 
+ 
+INVAL 
+   
+  Parameter(s) passed to the function were not valid. 
+   
+ 
+EBADF 
+   
+  The underlying message transport is unable to process the 
+  request. 
+   
+ 
+ENOTSUP 
+   
+  The underlying message transport is unable to process the 
+  request. 
+   
+ 
+EFSM 
+   
+  The underlying message transport is unable to process the 
+  request. 
+   
+ 
+EAGAIN 
+   
+  The underlying message transport is unable to process the 
+  request. 
+   
+ 
+EINTR 
+   
+  The underlying message transport is unable to process the 
+  request. 
+   
+ 
+ETIMEDOUT 
+   
+  The underlying message transport is unable to process the 
+  request. 
+   
+ 
+ETERM 
+   
+  The underlying message transport is unable to process the 
+  request. 
+ 
+ 
+EXAMPLE 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), 
+rmr_get_rcvfd(3), rmr_init(3), rmr_payload_size(3), 
+rmr_rcv_msg(3), rmr_send_msg(3), rmr_rcv_specific(3), 
+rmr_rts_msg(3), rmr_ready(3), rmr_fib(3), rmr_has_str(3), 
+rmr_tokenise(3), rmr_mk_ring(3), rmr_ring_free(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_trace_ref 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ int rmr_trace_ref( rmr_mbuf_t* mbuf, int* sizeptr )
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_trace_ref function return a pointer to the trace area 
+in the message, and optionally populate the user programme 
+supplied size integer with the trace area size, if *sizeptr* 
+is not nil. 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+On success, a void pointer to the trace area of the message 
+is returned. A nil pointer is returned if the message has no 
+trace data area allocated, or if the message itself is 
+invalid. 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_tralloc_msg(3), rmr_bytes2xact(3), 
+rmr_bytes2meid(3), rmr_call(3), rmr_free_msg(3), 
+rmr_get_rcvfd(3), rmr_get_trlen(3), rmr_init(3), 
+rmr_init_trace(3), rmr_payload_size(3), rmr_send_msg(3), 
+rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), 
+rmr_ready(3), rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), 
+rmr_mk_ring(3), rmr_ring_free(3), rmr_str2meid(3), 
+rmr_str2xact(3), rmr_wh_open(3), rmr_wh_send_msg(3), 
+rmr_set_trace(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_tralloc_msg 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ rmr_mbuf_t* rmr_tralloc_msg( void* vctx, int size, 
+                              int trace_size, unsigned const char *tr_data );
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_alloc_msg function is used to allocate a buffer which 
+the user programme can write into and then send through the a 
+library. The buffer is allocated such that sending it 
+requires no additional copying from the buffer as it passes 
+through the underlying transport mechanism. 
+ 
+The *size* parameter is used to set the payload length in the 
+message and If it is 0, then the default size supplied on the 
+*rmr_init* call will be used. In addition to allocating the 
+payload, a space in the buffer is reserved for *trace* data 
+(tr_size bytes), and the bytes pointed to by *tr_data* are 
+copied into that portion of the message. The *vctx* parameter 
+is the void context pointer that was returned by the 
+*rmr_init* function. 
+ 
+The pointer to the message buffer returned is a structure 
+which has some user application visible fields; the structure 
+is described in rmr.h, and is illustrated below. 
+ 
+ 
+:: 
+  
+ typedef struct {
+     int state;
+     int mtype;
+     int len;
+     unsigned char* payload;
+     unsigned char* xaction;
+ } rmr_mbuf_t;
+ 
+ 
+ 
+ 
+ 
+state 
+   
+  Is the current buffer state. Following a call to 
+  rmr_send_msg the state indicates whether the buffer was 
+  successfully sent which determines exactly what the 
+  payload points to. If the send failed, the payload 
+  referenced by the buffer is the message that failed to 
+  send (allowing the application to attempt a 
+  retransmission). When the state is a_OK the buffer 
+  represents an empty buffer that the application may fill 
+  in in preparation to send. 
+   
+ 
+mtype 
+   
+  When sending a message, the application is expected to set 
+  this field to the appropriate message type value (as 
+  determined by the user programme). Upon send this value 
+  determines how the a library will route the message. For a 
+  buffer which has been received, this field will contain 
+  the message type that was set by the sending application. 
+   
+ 
+len 
+   
+  The application using a buffer to send a message is 
+  expected to set the length value to the actual number of 
+  bytes that it placed into the message. This is likely less 
+  than the total number of bytes that the message can carry. 
+  For a message buffer that is passed to the application as 
+  the result of a receive call, this will be the value that 
+  the sending application supplied and should indicate the 
+  number of bytes in the payload which are valid. 
+   
+ 
+payload 
+   
+  The payload is a pointer to the actual received data. The 
+  user programme may read and write from/to the memory 
+  referenced by the payload up until the point in time that 
+  the buffer is used on a rmr_send, rmr_call or rmr_reply 
+  function call. Once the buffer has been passed back to a a 
+  library function the user programme should **NOT** make 
+  use of the payload pointer. 
+   
+ 
+xaction 
+   
+  The *xaction* field is a pointer to a fixed sized area in 
+  the message into which the user may write a transaction 
+  ID. The ID is optional with the exception of when the user 
+  application uses the rmr_call function to send a message 
+  and wait for the reply; the underlying a processing 
+  expects that the matching reply message will also contain 
+  the same data in the *xaction* field. 
+ 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+The function returns a pointer to a rmr_mbuf structure, or 
+NULL on error. 
+ 
+ERRORS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+ 
+ENOMEM 
+   
+  Unable to allocate memory. 
+ 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_mbuf(3) rmr_call(3), rmr_free_msg(3), 
+rmr_init(3), rmr_init_trace(3), rmr_get_trace(3), 
+rmr_get_trlen(3), rmr_payload_size(3), rmr_send_msg(3), 
+rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), 
+rmr_ready(3), rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), 
+rmr_mk_ring(3), rmr_ring_free(3), rmr_set_trace(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_wh_open 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ void rmr_close( void* vctx, rmr_whid_t whid )
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_wh_close function closes the wormhole associated with 
+the wormhole id passed in. Future calls to rmr_wh_send_msg 
+with this ID will fail. 
+ 
+The underlying TCP connection to the remote endpoint is 
+**not** closed as this session may be reqruired for 
+regularlly routed messages (messages routed based on message 
+type). There is no way to force a TCP session to be closed at 
+this point in time. 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), 
+rmr_get_rcvfd(3), rmr_payload_size(3), rmr_send_msg(3), 
+rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), 
+rmr_ready(3), rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), 
+rmr_mk_ring(3), rmr_ring_free(3), rmr_wh_open(3), 
+rmr_wh_send_msg(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_wh_open 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ void* rmr_wh_open( void* vctx, char* target )
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_wh_open function creates a direct link for sending, a 
+wormhole, to another RMr based process. Sending messages 
+through a wormhole requires that the connection be 
+established overtly by the user application (via this 
+function), and that the ID returned by rmr_wh_open be passed 
+to the rmr_wh_send_msg function. 
+ 
+*Target* is the *name* or *IP-address* combination of the 
+processess that the wormhole should be connected to. *Vctx* 
+is the RMr void context pointer that was returned by the 
+rmr_init function. 
+ 
+When invoked, this function immediatly attempts to connect to 
+the target process. If the connection cannot be established, 
+an error is returned to the caller, and no direct messages 
+can be sent to the target. Once a wormhole is connected, the 
+underlying transport mechanism (e.g. NNG) will provide 
+reconnects should the connection be lost, however the 
+handling of messages sent when a connection is broken is 
+undetermined as each underlying transport mechanism may 
+handle buffering and retries differently. 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_wh_open function returns a type rmr_whid_t which must 
+be passed to the rmr_wh_send_msg function when sending a 
+message. The id may also be tested to determine success or 
+failure of the connection by using the RMR_WH_CONNECTED macro 
+and passing the ID as the parameter; a result of 1 indicates 
+that the connection was esablished and that the ID is valid. 
+ 
+ERRORS 
+-------------------------------------------------------------------------------------------- 
+ 
+The following error values are specifically set by this RMR 
+function. In some cases the error message of a system call is 
+propagated up, and thus this list might be incomplete. 
+ 
+ 
+EINVAL 
+   
+  A parameter passed was not valid. 
+ 
+EACCESS 
+   
+  The user applicarion does not have the ability to 
+  establish a wormhole to the indicated target (or maybe any 
+  target). 
+ 
+ECONNREFUSED 
+   
+  The connection was refused. 
+ 
+ 
+EXAMPLE 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+    void*  rmc;
+    rmr_whid_t wh;
+    rmc = rmr_init( "43086", 4096, 0 ); // init context
+    wh = rmr_wh_open( rmc, "localhost:6123" );
+    if( !RMR_WH_CONNECTED( wh ) ) { 
+     f fprintf( stderr, "unable to connect wormhole: %s\\n",
+              strerror( errno ) );
+    }
+ 
+ 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), 
+rmr_get_rcvfd(3), rmr_payload_size(3), rmr_send_msg(3), 
+rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), 
+rmr_ready(3), rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), 
+rmr_mk_ring(3), rmr_ring_free(3), rmr_wh_send_msg(3), 
+rmr_wh_close(3) 
+ 
+ 
+NAME 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_wh_send_msg 
+ 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>
+ rmr_mbuf_t* rmr_wh_send_msg( void* vctx, rmr_whid_t id, rmr_mbuf_t* msg );
+ 
+ 
+ 
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+ 
+The rmr_wh_send_msg function accepts a message buffer from 
+the user application and attempts to send it using the 
+wormhole ID provided (id). Unlike *rmr_send_msg,* this 
+function attempts to send the message directly to a process 
+at the other end of a wormhole which was created with 
+*rmr_wh-open().* When sending message via wormholes, the 
+normal RMr routing based on message type is ignored, and the 
+caller may leave the message type unspecified in the message 
+buffer (unless it is needed by the receiving process). 
+ 
+The message buffer (msg) used to send is the same format as 
+used for regular RMr send and reply to sender operations, 
+thus any buffer allocated by these means, or calls to 
+*rmr_rcv_msg()* can be passed to this function. 
+ 
+Retries 
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
+ 
+The send operations in RMr will retry *soft* send failures 
+until one of three conditions occurs: 
+ 
+ 
+ 
+1. 
+   
+  The message is sent without error 
+   
+ 
+2. 
+   
+  The underlying transport reports a * hard * failure 
+   
+ 
+3. 
+   
+  The maximum number of retry loops has been attempted 
+ 
+ 
+A retry loop consists of approximately 1000 send attemps ** 
+without** any intervening calls to * sleep() * or * usleep(). 
+* The number of retry loops defaults to 1, thus a maximum of 
+1000 send attempts is performed before returning to the user 
+application. This value can be set at any point after RMr 
+initialisation using the * rmr_set_stimeout() * function 
+allowing the user application to completely disable retires 
+(set to 0), or to increase the number of retry loops. 
+ 
+Transport Level Blocking 
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
+ 
+The underlying transport mechanism used to send messages is 
+configured in *non-blocking* mode. This means that if a 
+message cannot be sent immediately the transport mechanism 
+will **not** pause with the assumption that the inability to 
+send will clear quickly (within a few milliseconds). This 
+means that when the retry loop is completely disabled (set to 
+0), that the failure to accept a message for sending by the 
+underlying mechanisms (software or hardware) will be reported 
+immediately to the user application. 
+ 
+It should be noted that depending on the underlying transport 
+mechanism being used, it is extremly possible that during 
+normal operations that retry conditions are very likely to 
+happen. These are completely out of RMr's control, and there 
+is nothing that RMr can do to avoid or midigate these other 
+than by allowing RMr to retry the send operation, and even 
+then it is possible (e.g. during connection reattempts), that 
+a single retry loop is not enough to guarentee a successful 
+send. 
+ 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+ 
+On success, a new message buffer, with an empty payload, is 
+returned for the application to use for the next send. The 
+state in this buffer will reflect the overall send operation 
+state and should be RMR_OK. 
+ 
+If the state in the returned buffer is anything other than 
+RMR_OK, the user application may need to attempt a 
+retransmission of the message, or take other action depending 
+on the setting of errno as described below. 
+ 
+In the event of extreme failure, a NULL pointer is returned. 
+In this case the value of errno might be of some use, for 
+documentation, but there will be little that the user 
+application can do other than to move on. 
+ 
+ERRORS 
+-------------------------------------------------------------------------------------------- 
+ 
+The following values may be passed back in the *state* field 
+of the returned message buffer. 
+ 
+ 
+ 
+RMR_ERR_WHID 
+   
+  The wormhole ID passed in was not associated with an open 
+  wormhole, or was out of range for a valid ID. 
+ 
+RMR_ERR_NOWHOPEN 
+   
+  No wormholes exist, further attempt to validate the ID are 
+  skipped. 
+ 
+RMR_ERR_BADARG 
+   
+  The message buffer pointer did not refer to a valid 
+  message. 
+ 
+RMR_ERR_NOHDR 
+   
+  The header in the message buffer was not valid or 
+  corrupted. 
+ 
+ 
+The following values may be assigned to errno on failure. 
+ 
+ 
+INVAL 
+   
+  Parameter(s) passed to the function were not valid, or the 
+  underlying message processing environment was unable to 
+  interpret the message. 
+   
+ 
+ENOKEY 
+   
+  The header information in the message buffer was invalid. 
+   
+ 
+ENXIO 
+   
+  No known endpoint for the message could be found. 
+   
+ 
+EMSGSIZE 
+   
+  The underlying transport refused to accept the message 
+  because of a size value issue (message was not attempted 
+  to be sent). 
+   
+ 
+EFAULT 
+   
+  The message referenced by the message buffer is corrupt 
+  (NULL pointer or bad internal length). 
+   
+ 
+EBADF 
+   
+  Internal RMR error; information provided to the message 
+  transport environment was not valid. 
+   
+ 
+ENOTSUP 
+   
+  Sending was not supported by the underlying message 
+  transport. 
+   
+ 
+EFSM 
+   
+  The device is not in a state that can accept the message. 
+   
+ 
+EAGAIN 
+   
+  The device is not able to accept a message for sending. 
+  The user application should attempt to resend. 
+   
+ 
+EINTR 
+   
+  The operation was interrupted by delivery of a signal 
+  before the message was sent. 
+   
+ 
+ETIMEDOUT 
+   
+  The underlying message environment timed out during the 
+  send process. 
+   
+ 
+ETERM 
+   
+  The underlying message environment is in a shutdown state. 
+ 
+ 
+EXAMPLE 
+-------------------------------------------------------------------------------------------- 
+ 
+The following is a simple example of how the a wormhole is 
+created (rmr_wh_open) and then how rmr_wh_send_msg function 
+is used to send messages. Some error checking is omitted for 
+clarity. 
+ 
+ 
+:: 
+  
+ #include <rmr/rmr.h>    .// system headers omitted for clarity
+ int main() {
+    rmr_whid_t whid = -1;   // wormhole id for sending
+    void* mrc;      //msg router context
+         int i;
+    rmr_mbuf_t*  sbuf;      // send buffer
+    int     count = 0;
+    mrc = rmr_init( "43086", RMR_MAX_RCV_BYTES, RMRFL_NONE );
+    if( mrc == NULL ) {
+       fprintf( stderr, "[FAIL] unable to initialise RMr environment\\n" );
+       exit( 1 );
+    }
+    while( ! rmr_ready( mrc ) ) {    e    i// wait for routing table info
+       sleep( 1 );
+    }
+    sbuf = rmr_alloc_msg( mrc, 2048 );
+    while( 1 ) {
+      if( whid < 0 ) {
+        whid = rmr_wh_open( mrc, "localhost:6123" );  // open fails if endpoint refuses conn
+        w   if( RMR_WH_CONNECTED( wh ) ) { 
+            snprintf( sbuf->payload, 1024, "periodic update from sender: %d", count++ );
+            sbuf->len =  strlen( sbuf->payload );
+            sbuf = rmr_wh_send_msg( mrc, whid, sbuf );
+           }
+       }
+       sleep( 5 );
+    }
+ }
+ 
+ 
+ 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+ 
+rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), rmr_init(3), 
+rmr_payload_size(3), rmr_rcv_msg(3), rmr_rcv_specific(3), 
+rmr_rts_msg(3), rmr_ready(3), rmr_fib(3), rmr_has_str(3), 
+rmr_tokenise(3), rmr_mk_ring(3), rmr_ring_free(3), 
+rmr_set_stimeout(3), rmr_wh_open(3), rmr_wh_close(3) 
+ 
diff --git a/src/rmr/README b/src/rmr/README
new file mode 100644
index 0000000..757b115
--- /dev/null
+++ b/src/rmr/README
@@ -0,0 +1,104 @@
+#
+#==================================================================================
+#       Copyright (c) 2019 Nokia
+#       Copyright (c) 2018-2019 AT&T Intellectual Property.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#==================================================================================
+#
+
+
+Source for the RIC Messaging Library -- RMR.
+
+C does not provide the concept of package names,  yet we have
+a desire not to maintain all of the static code in a single large
+file, we use the following convention:
+
+	<name>.c --		C code which builds separately and generates an object
+					that is ultimately added to the archive.
+
+	<name>_static.c - File containing nothing but static functions (a.k.a package
+					only functions). These files should be included by other *.c
+					files and should not generate object.
+
+	<name>.h		Header file that user applications are expected to include
+					in order to make use of the library
+
+	<name>_inline.h Header files containing inline static functions that the
+					user application is expected to include.
+
+	<name>_private.h Header file meant only to be included by the package.
+
+Further, as this code is used to generate libraries which make use of different
+transport mechanisms, there are some modules which are specific to the
+underlying transport being used.  The original code supported both Nanomsg and
+NNG, however Nanomsg has been phased out (starting with 1.0.45).  File naming
+convention for modules which are transport specific originally included a
+suffix (e.g. _nng), however as the directory structure was reorganised, and
+transport specific directories, plus a common directory, have been created,
+the need for the suffix has been eliminated (existing files were not changed).
+
+
+External Names
+All externally facing function names and constants will start with rmr_ or
+RMR_ respectively (RIC Message Router).    For the time being, there is a
+set of mappings from the old uta_* names to rmr_* names. The user code must
+define UTA_COMPAT to have these enabled.
+
+Internal Names
+Internal (static) functions have no mandated convention. There are some
+names which are prefixed with uta_.  These are left over from the original
+prototype library which had the name Uta.  The uta_ prefixes were mostly on
+functions which were initially external, but were pulled back for this release.
+
+
+
+Requirements
+To build the RMR libraries, NNG must be installed, or the external references
+in the source tree must be used to pull and build the NNG library. It might
+be necessary to alter the values of C_INCLUDE_PATH,  LD_LIBRARY_PATH, or
+LIBRARY_PATH to reflect the installation location when the installed version
+of NNG is being used.
+
+To install see the instructions on their html sites:
+	https://github.com/nanomsg/nng
+
+The default CMake build will not require NNG to be installed, and this is the
+easiest way to build.
+
+Unit Testing
+The script ../test/unit_test.ksh should be used for running unit tests. With no
+parameters it will attempt to build any file in this directory which has the
+name *_test.c.  Build is attempted with either mk or make and enables the
+necessary compiler flags to support coverage output (gcov).  Once built, the
+test program is executed and if the return code is success (0), the
+coverage data is interpreted.
+
+The test programs may make use of ../test/tools.c which provide simple
+validation check functions.  These programs should also directly include
+the module(s) under test.  This ensures that they are not linked, and are
+compiled with the proper coverage flags. In addition, it allows modules that
+are not under test to be linked from the archive and (most importantly) not
+reported on from a coverage perspective. In cases where two modules depend on
+each other, and are static functions, they will need to be tested from a single
+unit test program (see the rt_tool test program).
+
+It might be necessary to write a higher level test driver as some of the modules
+(e.g. route table) have threaded daemons which might not be easy to drive
+completely or at all, and thus the code coverage for a passing test might need
+to be lower for this type of module.
+
+Containerized Build
+The Dockerfile defines an environment to build and test this library.  It uses
+a base image with the C toolchain.  The Dockerfile is NOT intended to create a
+distributable image.