Man Page: rmr_wh_call





#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 )


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.


The send operations in RMR will retry soft send failures until one of three conditions occurs:

  • The message is sent without error

  • The underlying transport reports a hard failure

  • 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.


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.


The following values may be passed back in the state field of the returned message buffer.


The wormhole ID passed in was not associated with an open wormhole, or was out of range for a valid ID.


No wormholes exist, further attempt to validate the ID are skipped.


The message buffer pointer did not refer to a valid message.


The header in the message buffer was not valid or corrupted.


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 );


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)