Add safe connect, fix possible seg fault in RTC
[ric-plt/lib/rmr.git] / docs / user-guide.rst
index a59239d..c201dcb 100644 (file)
@@ -1,4 +1,5 @@
  
 .. 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. 
@@ -6,21 +7,26 @@
 .. 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 available via the 
-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 
-:) 
+The RIC Message Router (RMR) is a library for peer-to-peer 
+communication. Applications use the library to send and 
+receive messages where the message routing and endpoint 
+selection is based on the message type rather than DNS host 
+name-IP port combinations. 
+This document contains information that developers need to 
+know to use the RMR library. Because the primary 
+documentation for the RMR library is a collection of UNIX 
+manpages (included in the development package, and available 
+via the 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 :) 
  
  
  
@@ -47,10 +53,16 @@ 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. 
+value passed in size is less than or equal to 0, then the 
+*normal maximum size* supplied on the *rmr_init* call will be 
+used. When *size* is greater than zero, the message allocated 
+will have at least the indicated number of bytes in the 
+payload. There is no maximum size imposed by RMR, however the 
+underlying system memory managerment (e.g. malloc) functions 
+may impose a limit. 
+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 
@@ -65,8 +77,8 @@ is described in rmr.h, and is illustrated below.
      int len;
      unsigned char* payload;
      unsigned char* xaction;
-     uint sub_id;
-     uint tp_state;
+     int sub_id;
+     int tp_state;
  } rmr_mbuf_t;
  
  
@@ -403,16 +415,16 @@ 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. 
+returned in the 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 
+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 
@@ -420,16 +432,16 @@ 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 
+the user application and a nil 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 
+The send operations in RMR will retry *soft* send failures 
 until one of three conditions occurs: 
  
  
@@ -441,7 +453,7 @@ until one of three conditions occurs:
  
 2. 
    
-  The underlying transport reports a * hard * failure 
+  The underlying transport reports a *hard* failure 
    
  
 3. 
@@ -449,17 +461,17 @@ until one of three conditions occurs:
   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 
+A retry loop consists of approximately 1000 send attempts 
+**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 
+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 
@@ -472,21 +484,20 @@ 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. 
+mechanism being used, it is extremely likely that retry 
+conditions will happen during normal operations. These are 
+completely out of RMR's control, and there is nothing that 
+RMR can do to avoid or mitigate 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 guarantee 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 
+processing (see Errors below). In some cases a nil pointer 
 will be returned; when this is the case only *errno* will be 
 available to describe the reason for failure. 
  
@@ -534,17 +545,18 @@ EINVAL
  
 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 messag
-  again. 
+  The underlying message system was interrupted or the 
+  device was busy; the message was **not** sent, and the 
+  user application should call this function with th
+  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. 
+The following code snippet shows one way of using the 
+rmr_call function, and illustrates how the transaction ID 
+must be set. 
  
  
 :: 
@@ -552,27 +564,25 @@ 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 );
+     msg_t*  pm;                         // application struct for payload
+     // get a send buffer and reference the payload
+     mbuf = rmr_alloc_msg( mr, sizeof( pm->req ) );
      pm = (msg_t*) mbuf->payload;
-     p// generate an xaction ID and fill in payload with data and msg type
+     // 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 && 
+                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;
@@ -595,7 +605,7 @@ rmr_tokenise(3), rmr_mk_ring(3), rmr_ring_free(3)
 NAME 
 -------------------------------------------------------------------------------------------- 
  
-rmr_wh_open 
+rmr_close 
  
 SYNOPSIS 
 -------------------------------------------------------------------------------------------- 
@@ -669,6 +679,59 @@ rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), rmr_mk_ring(3),
 rmr_ring_free(3) 
  
  
+NAME 
+-------------------------------------------------------------------------------------------- 
+rmr_get_const 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+:: 
+  
+ #include <rmr/rmr.h>
+ unsigned char* rmr_get_const();
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+The rmr_get_const function is a convenience function for 
+wrappers which do not have the ability to "compile in" RMR 
+constants. The function will build a nil terminated string 
+containing JSON which defines the RMR constants that C and Go 
+applications have at compile time via the rmr.h header file. 
+All values are represented as strings and the JSON format is 
+illustrated in the following (partial) example: 
+:: 
+  
+ {
+   "RMR_MAX_XID": "32",
+   "RMR_OK": "0",
+   "RMR_ERR_BADARG", "1",
+   "RMR_ERR_NOENDPT" "2"
+ }
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+On success, a pointer to a string containing the JSON 
+defining constant and value pairs. On failure a nil pointer 
+is returned. 
+SEE ALSO 
+-------------------------------------------------------------------------------------------- 
+rmr(7) 
 NAME 
 -------------------------------------------------------------------------------------------- 
  
@@ -767,19 +830,11 @@ 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. 
+or equal to 0 on success and -1 on error. 
  
 ERRORS 
 -------------------------------------------------------------------------------------------- 
@@ -816,25 +871,22 @@ function. Error checking has been omitted for clarity.
      rmr_mbuf_t* msg = NULL;
      int nready;
      int i;
-  
-     mrc = rmr_init( "43086", RMR_MAX_RCV_BYTES, RMRFL_NONE );
+     int norm_msg_size = 1500;               // 95% messages are less than this
+     mrc = rmr_init( "43086", norm_msg_size, RMRFL_NONE );
      rcv_fd = rmr_get_rcvfd( mrc );
-  
-     rep_fd = epoll_create1( 0 );    _    B    ,// initialise epoll environment
+     ep_fd = epoll_create1( 0 );             // 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
+         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....
          }
      }
@@ -873,14 +925,14 @@ 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 
+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 
+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. 
  
@@ -939,19 +991,19 @@ 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 
+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 
+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 
+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 
+against future RMR enhancements which might increase the 
 address buffer size requirement. 
  
 RETURN VALUE 
@@ -1165,7 +1217,7 @@ SYNOPSIS
 :: 
   
  #include <rmr/rmr.h>
- void* rmr_init( char* proto_port, int max_msg_size, int flags );
+ void* rmr_init( char* proto_port, int norm_msg_size, int flags );
  
  
  
@@ -1179,20 +1231,34 @@ 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 *max_msg_size* parameter is used 
-to allocate receive buffers and is the maximum message size 
-which the application expects to receive. This value is the 
-sum of **both** the maximum payload size **and** the maximum 
-trace data size. This value is also used as the default 
-message size when allocating message buffers. Messages 
-arriving which are longer than the given maximum will be 
-dropped without notification to the application. A warning is 
-written to standard error for the first message which is too 
-large on each connection. 
-*Flags* allows for selection of some RMr options at the time 
+RMR based applications. The *norm_msg_size* parameter is used 
+to allocate receive buffers and should be set to what the 
+user application expects to be a size which will hold the 
+vast majority of expected messages. When computing the size, 
+the application should consider the usual payload size 
+**and** the maximum trace data size that will be used. This 
+value is also used as the default message size when 
+allocating message buffers (when a zero size is given to 
+rmr_alloc_msg(); see the rmr_alloc_msg() manual page). 
+Messages arriving which are longer than the given normal size 
+will cause RMR to allocate a new buffer which is large enough 
+for the arriving message. 
+Starting with version 3.8.0 RMR no longer places a maximum 
+buffer size for received messages. The underlying system 
+memory manager might impose such a limit and the attempt to 
+allocate a buffer larger than that limit will likely result 
+in an application abort. Other than the potential performance 
+impact from extra memory allocation and release, there is no 
+penality to the user programme for specifyning a normal 
+buffer size which is usually smaller than received buffers. 
+Similarly, the only penality to the application for over 
+specifying the normal buffer size might be a larger memory 
+footprint. 
+*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 
+from the RMR header file. Currently the following flags are 
 supported: 
  
  
@@ -1206,7 +1272,7 @@ 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
+  application if it is based on RMR
    
  
 RMRFL_MTCALL 
@@ -1227,7 +1293,7 @@ RMRFL_NOLOCK
  
  
 Multi-threaded Calling 
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  
 The support for an application to issue a *blocking call* by 
 the rmr_call() function was limited such that only user 
@@ -1241,11 +1307,11 @@ 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 
+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 
+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. 
  
@@ -1253,32 +1319,32 @@ an additional process is necessary the user application must
 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. 
+As a part of the initialisation process rmr_init reads 
+environment variables to configure itself. The following 
+variables are used if found. 
  
  
  
 RMR_ASYNC_CONN 
    
   Allows the async 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 (async) 
+  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 (async) 
   mode. This will likely result in many "soft failures" 
   (retry) until the connection is established, but allows 
-  the application to continue unimpeeded should the 
+  the application to continue unimpeded 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. 
+  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_CTL_PORT 
@@ -1291,17 +1357,16 @@ RMR_CTL_PORT
   port) was used to define this port. However, a future 
   version of Route Manager will require RMR to connect and 
   request tables, thus that variable is now used to supply 
-  the Route Manager well known address and port. 
+  the Route Manager's well-known address and port. 
    
-  To maintain backwards compatablibility with the older 
-  Route Manager versions, the presence of this variable in 
-  the environment will shift RMR's behaviour with respect to 
-  the default value used when RMR_RTG_SVC is **not** 
-  defined. 
+  To maintain backwards compatibility with the older Route 
+  Manager versions, the presence of this variable in the 
+  environment will shift RMR's behaviour with respect to the 
+  default value used when RMR_RTG_SVC is **not** defined. 
    
   When RMR_CTL_PORT is **defined:** RMR assumes that Route 
   Manager requires RMR to connect and request table updates 
-  is made, and the default well known address for Route 
+  is made, and the default well-known address for Route 
   manager is used (routemgr:4561). 
    
   When RMR_CTL_PORT is **undefined:** RMR assumes that Route 
@@ -1393,8 +1458,8 @@ RMR_RTG_ISRAW
    
   **Deprecated.** Should be 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. 
+  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. 
    
   This variable is only recognised when using the NNG 
   transport library as it is not possible to support NNG 
@@ -1414,7 +1479,7 @@ RMR_SEED_RT
   report *ready* until a table is received. The static route 
   table may contain both the route table (between newrt 
   start and end records), and the MEID map (between meid_map 
-  start and end records) 
+  start and end records). 
  
 RMR_SRC_ID 
    
@@ -1538,7 +1603,7 @@ RETURN VALUE
 -------------------------------------------------------------------------------------------- 
  
 A value of 1 is returned on success, and 0 on failure. A 
-failure indicates that the RMr context (a void pointer passed 
+failure indicates that the RMR context (a void pointer passed 
 to this function was not valid. 
  
 SEE ALSO 
@@ -1595,33 +1660,28 @@ 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 
+messages are returned in the 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 
+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 
+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 
+The send operations in RMR will retry *soft* send failures 
 until one of three conditions occurs: 
  
  
@@ -1633,7 +1693,7 @@ until one of three conditions occurs:
  
 2. 
    
-  The underlying transport reports a * hard * failure 
+  The underlying transport reports a *hard* failure 
    
  
 3. 
@@ -1641,17 +1701,17 @@ until one of three conditions occurs:
   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 
+A retry loop consists of approximately 1000 send attempts 
+**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 
+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 
@@ -1664,14 +1724,13 @@ 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. 
+mechanism being used, it is extremely likely that retry 
+conditions will happen during normal operations. These are 
+completely out of RMR's control, and there is nothing that 
+RMR can do to avoid or mitigate 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 guarantee a successful send. 
  
 RETURN VALUE 
 -------------------------------------------------------------------------------------------- 
@@ -1764,27 +1823,25 @@ 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 );
+     msg_t*  pm;                         // appl message struct (payload)
+     // get a send buffer and reference the payload
+     mbuf = rmr_alloc_msg( mr, sizeof( pm->req ) );
      pm = (msg_t*) mbuf->payload;
-     p// generate an xaction ID and fill in payload with data and msg type
+     // 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
+     msg = rmr_mt_call( mr, msg, my_id, 100 );        // 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_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;
@@ -1826,7 +1883,7 @@ 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. 
+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 
@@ -1841,17 +1898,17 @@ 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 
+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 
+this function. Doing so might be advantageous 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 
+more simple. The advantages 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 
@@ -1861,16 +1918,11 @@ cost of a second call that results). Similarly, the
 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 
+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 
@@ -1908,7 +1960,7 @@ RMR_ERR_EMPTY
  
 RMR_ERR_NOTSUPP 
    
-  The multi-threaded option was not enabled when RMr was 
+  The multi-threaded option was not enabled when RMR was 
   initialised. See the man page for *rmr_init()* for 
   details. 
    
@@ -2094,14 +2146,14 @@ 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. 
+payload), or a nil pointer in the case of an extreme error. 
  
 ERRORS 
 -------------------------------------------------------------------------------------------- 
  
-The *state* field in the message buffer will indicate either 
-RMR_OK when the message receive process was successful and 
-the message can be used by the caller. Depending on the 
+The *state* field in the message buffer will indicate RMR_OK 
+when the message receive process was successful and the 
+message can be used by the caller. Depending on the 
 underlying transport mechanism, one of the following RMR 
 error stats may be returned: 
  
@@ -2265,7 +2317,7 @@ original payload are copied if the *copy* parameter is true
 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 
@@ -2275,7 +2327,7 @@ 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 
@@ -2290,7 +2342,7 @@ 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 buffer pointer may still be used to reference that 
 message. It is the calling application's responsibility to 
 free the memory associateed with both messages using the 
 rmr_free_msg() function. 
@@ -2337,8 +2389,8 @@ received.
      if( msg == NULL ) {
        fprintf( stderr, "[ERR] realloc returned a nil pointer: %s\\n", strerror( errno ) );
      } else {
-     }    e// populate and send ack message
-     }}
+       // populate and send ack message
+     }
  }
  
  
@@ -2379,9 +2431,9 @@ 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 
+The send operations in RMR will retry *soft* send failures 
 until one of three conditions occurs: 
  
  
@@ -2393,7 +2445,7 @@ until one of three conditions occurs:
  
 2. 
    
-  The underlying transport reports a * hard * failure 
+  The underlying transport reports a *hard* failure 
    
  
 3. 
@@ -2401,17 +2453,17 @@ until one of three conditions occurs:
   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 
+A retry loop consists of approximately 1000 send attempts 
+**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 
+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 
@@ -2424,14 +2476,13 @@ 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. 
+mechanism being used, it is extremely likely that retry 
+conditions will happen during normal operations. These are 
+completely out of RMR's control, and there is nothing that 
+RMR can do to avoid or mitigate 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 guarantee a successful send. 
  
 PAYLOAD SIZE 
 -------------------------------------------------------------------------------------------- 
@@ -2442,7 +2493,7 @@ 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 
+function, the source information in the original 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 
@@ -2460,11 +2511,11 @@ 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 
+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 the event of extreme failure, a nil 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. 
@@ -2527,7 +2578,7 @@ EMSGSIZE
 EFAULT 
    
   The message referenced by the message buffer is corrupt 
-  (NULL pointer or bad internal length). 
+  (nil pointer or bad internal length). 
    
  
 EBADF 
@@ -2617,9 +2668,9 @@ used by the RMR library, and not the responsibility of the
 library.) 
  
 Retries 
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
  
-The send operations in RMr will retry *soft* send failures 
+The send operations in RMR will retry *soft* send failures 
 until one of three conditions occurs: 
  
  
@@ -2631,7 +2682,7 @@ until one of three conditions occurs:
  
 2. 
    
-  The underlying transport reports a * hard * failure 
+  The underlying transport reports a *hard* failure 
    
  
 3. 
@@ -2639,17 +2690,17 @@ until one of three conditions occurs:
   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 
+A retry loop consists of approximately 1000 send attempts 
+**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 
+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 
@@ -2662,14 +2713,13 @@ 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. 
+mechanism being used, it is extremely likely that retry 
+conditions will happen during normal operations. These are 
+completely out of RMR's control, and there is nothing that 
+RMR can do to avoid or mitigate 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 guarantee a successful send. 
  
 RETURN VALUE 
 -------------------------------------------------------------------------------------------- 
@@ -2685,7 +2735,7 @@ 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 the event of extreme failure, a nil 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. 
@@ -2766,7 +2816,7 @@ EMSGSIZE
 EFAULT 
    
   The message referenced by the message buffer is corrupt 
-  (NULL pointer or bad internal length). 
+  (nil pointer or bad internal length). 
    
  
 EBADF 
@@ -2823,23 +2873,23 @@ 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
+     if( send_msg  == NULL ) {
+         send_msg = rmr_alloc_msg( mr, MAX_SIZE ); // 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 );       // something that fills the payload in
      msg = rmr_send_msg( mr, send_msg );   // ensure new pointer used after send
-     mif( ! msg ) {
-     m    !return ERROR;
-     m} else {
-     m    sif( msg->state != RMR_OK ) {
-     m    s    m// check for RMR_ERR_RETRY, and resend if needed
-     m    s    m// else return error
-     m    s}
-     m}
-     mreturn OK;
+     if( ! msg ) {
+         return ERROR;
+     } else {
+         if( msg->state != RMR_OK ) {
+             // check for RMR_ERR_RETRY, and resend if needed
+             // else return error
+         }
+     }
+     return OK;
  
  
  
@@ -2873,7 +2923,7 @@ DESCRIPTION
  
 The rmr_set_fack function enables *fast TCP acknowledgements* 
 if the underlying transport library supports it. This might 
-be useful for applications which must send messages as a 
+be useful for applications which must send messages at a 
 maximum rate. 
  
 RETURN VALUE 
@@ -2912,21 +2962,21 @@ DESCRIPTION
 -------------------------------------------------------------------------------------------- 
  
 The rmr_set_stimeout function sets the configuration for how 
-RMr will retry message send operations which complete with 
+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 
+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 
@@ -2935,7 +2985,7 @@ 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 
+RMR send operations will attempt a send operation only 
 **once,** returning immediately to the caller with the state 
 of that single attempt. 
  
@@ -2962,9 +3012,9 @@ 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
+     char* port = "43086";     // port for message router listen
+     int   max_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
@@ -3031,7 +3081,7 @@ rmr_wh_open(3), rmr_wh_send_msg(3)
 NAME 
 -------------------------------------------------------------------------------------------- 
  
-rmr_set_trace 
+rmr_set_vlevel 
  
 SYNOPSIS 
 -------------------------------------------------------------------------------------------- 
@@ -3096,10 +3146,10 @@ RMR_VL_DEBUG
   as it can grossly affect performance. 
  
  
-generally RMR does not write messages to the standard error 
+Generally RMR does not write messages to the standard error 
 device from *critical path* functions, therefore it is 
 usually not harmful to enable a verbosity level of either 
-RMR_VL_CRIT, or RMR_VL_ERR. 
+RMR_VL_CRIT or RMR_VL_ERR. 
  
 Messages written from the route table collection thread are 
 still governed by the value placed into the verbose level 
@@ -3418,7 +3468,7 @@ 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. 
+payload), or a nil pointer in the case of an extreme error. 
  
 ERRORS 
 -------------------------------------------------------------------------------------------- 
@@ -3538,10 +3588,10 @@ SYNOPSIS
 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. 
+The rmr_trace_ref function returns a pointer to the trace 
+area in the message, and optionally populates the user 
+programme supplied size integer with the trace area size, if 
+*sizeptr* is not nil. 
  
 RETURN VALUE 
 -------------------------------------------------------------------------------------------- 
@@ -3577,7 +3627,7 @@ SYNOPSIS
 :: 
   
  #include <rmr/rmr.h>
- rmr_mbuf_t* rmr_tralloc_msg( void* vctx, int size, 
+ rmr_mbuf_t* rmr_tralloc_msg( void* vctx, int size,
                               int trace_size, unsigned const char *tr_data );
  
  
@@ -3585,14 +3635,14 @@ SYNOPSIS
 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 
+The rmr_tralloc_msg function is used to allocate a buffer 
+which the user programme can write into and then send through 
+the 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 
+message. 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 
@@ -3671,9 +3721,9 @@ xaction
   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. 
+  and wait for the reply; the underlying processing expects 
+  that the matching reply message will also contain the same 
+  data in the *xaction* field. 
  
  
 RETURN VALUE 
@@ -3706,7 +3756,206 @@ rmr_mk_ring(3), rmr_ring_free(3), rmr_set_trace(3)
 NAME 
 -------------------------------------------------------------------------------------------- 
  
-rmr_wh_open 
+rmr_wh_call 
+SYNOPSIS 
+-------------------------------------------------------------------------------------------- 
+:: 
+  
+ #include <rmr/rmr.h>
+ rmr_mbuf_t* rmr_wh_call( void* vctx, rmr_whid_t whid, rmr_mbuf_t* msg, int call_id, int max_wait )
+DESCRIPTION 
+-------------------------------------------------------------------------------------------- 
+The rmr_wh_call function accepts a message buffer (msg) from 
+the user application and attempts to send it using the 
+wormhole ID provided (whid). If the send is successful, the 
+call will block until either a response message is received, 
+or the max_wait number of milliseconds has passed. In order 
+for the response to be recognised as a response, the remote 
+process **must** use rmr_rts_msg() to send their response. 
+Like *rmr_wh_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 call_id parameter is a number in the 
+range of 2 through 255 and is used to identify the calling 
+thread in order to properly match a response message when it 
+arrives. Providing this value, and ensuring the proper 
+uniqueness, is the responsibility of the user application and 
+as such the ability to use the rmr_wh_call() function from 
+potentially non-threaded concurrent applications (such as 
+Go's goroutines) is possible. 
+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 attempts 
+**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 extremely likely that retry 
+conditions will happen during normal operations. These are 
+completely out of RMR's control, and there is nothing that 
+RMR can do to avoid or mitigate 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 guarantee a successful send. 
+RETURN VALUE 
+-------------------------------------------------------------------------------------------- 
+On success, new message buffer, with the payload containing 
+the response from the remote endpoint is returned. The state 
+in this buffer will reflect the overall send operation state 
+and should be RMR_OK. 
+If a message is returned with a state which is anything other 
+than RMR_OK, the indication is that the send was not 
+successful. The user application must check the state and 
+determine the course of action. If the return value is NULL, 
+no message, the indication is that there was no response 
+received within the timeout (max_wait) period of time. 
+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. 
+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;
+    int     norm_msg_size = 1500;    // most messages fit in this size
+    mrc = rmr_init( "43086", norm_msg_size, RMRFL_NONE );
+    if( mrc == NULL ) {
+       fprintf( stderr, "[FAIL] unable to initialise RMR environment\\n" );
+       exit( 1 );
+    }
+    while( ! rmr_ready( mrc ) ) {        // 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
+           if( RMR_WH_CONNECTED( wh ) ) {
+            snprintf( sbuf->payload, 1024, "periodic update from sender: %d", count++ );
+            sbuf->len =  strlen( sbuf->payload );
+            sbuf = rmr_wh_call( mrc, whid, sbuf, 1000 );        // expect a response in 1s or less
+            if( sbuf != NULL && sbuf->state = RMR_OK ) {
+              sprintf( stderr, "response: %s\\n", sbuf->payload );    // assume they sent a string
+            } else {
+              sprintf( stderr, "response not received, or send error\\n" );
+            }
+         }
+       }
+       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), 
+rmr_wh_state(3) 
+NAME 
+-------------------------------------------------------------------------------------------- 
+rmr_wh_close 
  
 SYNOPSIS 
 -------------------------------------------------------------------------------------------- 
@@ -3727,10 +3976,10 @@ 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. 
+**not** closed as this session may be required for regularly 
+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 
 -------------------------------------------------------------------------------------------- 
@@ -3763,7 +4012,7 @@ DESCRIPTION
 -------------------------------------------------------------------------------------------- 
  
 The rmr_wh_open function creates a direct link for sending, a 
-wormhole, to another RMr based process. Sending messages 
+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 
@@ -3771,7 +4020,7 @@ 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 
+is the RMR void context pointer that was returned by the 
 rmr_init function. 
  
 When invoked, this function immediatly attempts to connect to 
@@ -3808,7 +4057,7 @@ EINVAL
  
 EACCESS 
    
-  The user applicarion does not have the ability to 
+  The user application does not have the ability to 
   establish a wormhole to the indicated target (or maybe any 
   target). 
  
@@ -3827,8 +4076,8 @@ EXAMPLE
     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",
+    if( !RMR_WH_CONNECTED( wh ) ) {
+      fprintf( stderr, "unable to connect wormhole: %s\\n",
               strerror( errno ) );
     }
  
@@ -3869,20 +4118,20 @@ 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 
+*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, 
+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 
+The send operations in RMR will retry *soft* send failures 
 until one of three conditions occurs: 
  
  
@@ -3894,7 +4143,7 @@ until one of three conditions occurs:
  
 2. 
    
-  The underlying transport reports a * hard * failure 
+  The underlying transport reports a *hard* failure 
    
  
 3. 
@@ -3902,17 +4151,17 @@ until one of three conditions occurs:
   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 
+A retry loop consists of approximately 1000 send attempts 
+**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 
+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 
@@ -3925,14 +4174,13 @@ 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. 
+mechanism being used, it is extremely likely that retry 
+conditions will happen during normal operations. These are 
+completely out of RMR's control, and there is nothing that 
+RMR can do to avoid or mitigate 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 guarantee a successful send. 
  
 RETURN VALUE 
 -------------------------------------------------------------------------------------------- 
@@ -3947,7 +4195,7 @@ 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 the event of extreme failure, a nil 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. 
@@ -4011,7 +4259,7 @@ EMSGSIZE
 EFAULT 
    
   The message referenced by the message buffer is corrupt 
-  (NULL pointer or bad internal length). 
+  (nil pointer or bad internal length). 
    
  
 EBADF 
@@ -4065,32 +4313,33 @@ clarity.
  
 :: 
   
- #include <rmr/rmr.h>    .// system headers 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 );
+    int     norm_msg_size = 1500;  // most msg fit in this size
+    mrc = rmr_init( "43086", norm_msg_size, RMRFL_NONE );
     if( mrc == NULL ) {
-       fprintf( stderr, "[FAIL] unable to initialise RMr environment\\n" );
+       fprintf( stderr, "[FAIL] unable to initialise RMR environment\\n" );
        exit( 1 );
     }
-    while( ! rmr_ready( mrc ) ) {    e    i// wait for routing table info
+    while( ! rmr_ready( mrc ) ) {        // 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 ) ) { 
+           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 );
+         }
+      }
+      sleep( 5 );
     }
  }