X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=docs%2Fuser-guide.rst;h=e815bea19ea802688d4fce335cd27619fdb711bc;hb=4f3e23473e3453d4b9c24d1cd727c481e5f59c74;hp=e4cb20c0eda8d26ceb52d72929d6634209951c68;hpb=fe6a856df463a0d7e06b28aac8590ac9c0f08dd6;p=ric-plt%2Flib%2Frmr.git diff --git a/docs/user-guide.rst b/docs/user-guide.rst index e4cb20c..e815bea 100644 --- a/docs/user-guide.rst +++ b/docs/user-guide.rst @@ -1,4378 +1,1647 @@ - -.. 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 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 :) - - - -NAME --------------------------------------------------------------------------------------------- - -rmr_alloc_msg - -SYNOPSIS --------------------------------------------------------------------------------------------- - - -:: - - #include - 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 - 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 entity 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 - 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 - 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 - 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 - 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 - 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 - char* rmr_get_meid( rmr_mbuf_t* mbuf, unsigned char* dest ) - - - -DESCRIPTION --------------------------------------------------------------------------------------------- - -The rmr_get_meid function will copy the managed entity 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 - 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 - #include - #include - #include - 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 - 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 - 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 - 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 - 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 - 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 - 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 *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 -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. - - -RMRFL_NOLOCK - - Some underlying transport providers (e.g. SI95) enable - locking to be turned off if the user application is single - threaded, or otherwise can guarantee that RMR functions - will not be invoked concurrently from different threads. - Turning off locking can help make message receipt more - efficient. If this flag is set when the underlying - transport does not support disabling locks, it will be - ignored. - - -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 guarantee 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_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) - 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_CTL_PORT - - This variable defines the port that RMR should open for - communications with Route Manager, and other RMR control - applications. If not defined, the port 4561 is assumed. - - Previously, the RMR_RTG_SVC (route table generator service - 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. - - 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. - - 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 - manager is used (routemgr:4561). - - When RMR_CTL_PORT is **undefined:** RMR assumes that Route - Manager will connect and push table updates, thus the - default listen port (4561) is used. - - To avoid any possible misinterpretation and/or incorrect - assumptions on the part of RMR, it is recommended that - both the RMR_CTL_PORT and RMR_RTG_SVC be defined. In the - case where both variables are defined, RMR will behave - exactly as is communicated with the variable's values. - - -RMR_RTG_SVC - - The value of this variable depends on the Route Manager in - use. - - When the Route Manager is expecting to connect to an xAPP - and push route tables, this variable must indicate the - port which RMR should use to listen for these connections. - - When the Route Manager is expecting RMR to connect and - request a table update during initialisation, the variable - should be the host of the Route Manager process. - - The RMR_CTL_PORT variable (added with the support of - sending table update requests to Route manager), controls - the behaviour if this variable is not set. See the - description of that variable for details. - - -RMR_HR_LOG - - By default RMR writes messages to standard error - (incorrectly referred to as log messages) in human - readable format. If this environment variable is set to 0, - the format of standard error messages might be written in - some format not easily read by humans. If missing, a value - of 1 is assumed. - - -RMR_LOG_VLEVEL - - This is a numeric value which corresponds to the verbosity - level used to limit messages written to standard error. - The lower the number the less chatty RMR functions are - during execution. The following is the current - relationship between the value set on this variable and - the messages written: - - -0 - - Off; no messages of any sort are written. - - -1 - - Only critical messages are written (default if this - variable does not exist) - - -2 - - Errors and all messages written with a lower value. - - -3 - - Warnings and all messages written with a lower value. - - -4 - - Informational and all messages written with a lower - value. - - -5 - - Debugging mode -- all messages written, however this - requires RMR to have been compiled with debugging - support enabled. - - - -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. - - This variable is only recognised when using the NNG - transport library as it is not possible to support NNG - "raw" communications with other transport libraries. It is - also necessary to match the value of this variable with - the capabilities of the Route Manager; at some point in - the future RMR will assume that all Route Manager messages - will arrive via an RMR connection and will ignore this - variable. - -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. 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) - -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. - - The value of this variable is also used for Route Manager - messages which are sent via an RMR connection. - -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. - - -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 - 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 (a void pointer 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 - 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_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 - 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_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 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: - - - -RMR_ERR_EMPTY - - The message received had no payload, or was completely - empty. - - -RMR_ERR_TIMEOUT - - For some transport mechanisms, or if reading the receive - queue from multiple threads, it is possible for one thread - to find no data waiting when it queries the queue. When - this state is reported, the message buffer does not - contain message data and the user application should - reinvoke the receive function. - - -When an RMR error state is reported, the underlying errno -value might provide more information. The following is a list -of possible values that might accompany the states listed -above: - -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 - 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 - 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_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_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 will be RMR_OK when the send was successful. - -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. - -**CAUTION:** In some cases it is extremely likely that the -message returned by the send function does **not** reference -the same memory structure. Thus is important for the user -programme to capture the new pointer for future use or to be -passed to rmr_free(). If you are experiencing either double -free errors or segment faults in either rmr_free() or -rmr_send_msg(), ensure that the return value from this -function is being captured and used. - -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 +.. 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. + +============================================================================================ +User's Guide +============================================================================================ +-------------------------------------------------------------------------------------------- +RIC Message Router -- RMR +-------------------------------------------------------------------------------------------- + + +Overview +======== + +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. The library provides the following +major features: + + +* Routing and endpoint selection is based on *message type.* + +* Application is insulated from the underlying transport + mechanism and/or protocols. + +* Message distribution (round robin or fanout) is selectable + by message type. + +* Route management updates are received and processed + asynchronously and without overt application involvement. + + + + +Purpose +------- + +RMR's main purpose is to provide an application with the +ability to send and receive messages to/from other peer +applications with minimal effort on the application's part. +To achieve this, RMR manages all endpoint information, +connections, and routing information necessary to establish +and maintain communication. From the application's point of +view, all that is required to send a message is to allocate +(via RMR) a message buffer, add the payload data, and set the +message type. To receive a message, the application needs +only to invoke the receive function; when a message arrives a +message buffer will be returned as the function result. + + +Message Routing +--------------- + +Applications are required to place a message type into a +message before sending, and may optionally add a subscription +ID when appropriate. The combination of message type, and +subscription ID are refered to as the *message key,* and is +used to match an entry in a routing table which provides the +possible endpoints expecting to receive messages with the +matching key. + + +Round Robin Delivery +-------------------- + +An endpoint from RMR's perspective is an application to which +RMR may establish a connection, and expect to send messages +with one or more defined message keys. Each entry in the +route table consists of one or more endpoint groups, called +round robin groups. When a message matches a specific entry, +the entry's groups are used to select the destination of the +message. A message is sent once to each group, with messages +being *balanced* across the endpoints of a group via round +robin selection. Care should be taken when defining multiple +groups for a message type as there is extra overhead required +and thus the overall message latency is somewhat increased. + + +Routing Table Updates +--------------------- + +Route table information is made available to RMR a static +file (loaded once), or by updates sent from a separate route +manager application. If a static table is provided, it is +loaded during RMR initialization and will remain in use until +an external process connects and delivers a route table +update (often referred to as a dynamic update). Dynamic +updates are listened for in a separate process thread and +applied automatically; the application does not need to allow +for, or trigger, updates. + + +Latency And Throughput +---------------------- + +While providing insulation from the underlying message +transport mechanics, RMR must also do so in such a manner +that message latency and throughput are not impacted. In +general, the RMR induced overhead, incurred due to the +process of selecting an endpoint for each message, is minimal +and should not impact the overall latency or throughput of +the application. This impact has been measured with test +applications running on the same physical host and the +average latency through RMR for a message was on the order of +0.02 milliseconds. + +As an application's throughput increases, it becomes easy for +the application to overrun the underlying transport mechanism +(e.g. NNG), consume all available TCP transmit buffers, or +otherwise find itself in a situation where a send might not +immediately complete. RMR offers different *modes* which +allow the application to manage these states based on the +overall needs of the application. These modes are discussed +in the *Configuration* section of this document. + + +General Use +=========== + +To use, the RMR based application simply needs to initialise +the RMR environment, wait for RMR to have received a routing +table (become ready), and then invoke either the send or +receive functions. These steps, and some behind the scenes +details, are described in the following paragraphs. + + +Initialisation +-------------- + +The RMR function ``rmr_init()`` is used to set up the RMR +environment and must be called before messages can be sent or +received. One of the few parameters that the application must +communicate to RMR is the port number that will be used as +the listen port for new connections. The port number is +passed on the initialisation function call and a TCP listen +socket will be opened with this port. If the port is already +in use RMR will report a failure; the application will need +to reinitialise with a different port number, abort, or take +some other action appropriate for the application. + +In addition to creating a TCP listen port, RMR will start a +process thread which will be responsible for receiving +dynamic updates to the route table. This thread also causes a +TCP listen port to be opened as it is expected that the +process which generates route table updates will connect and +send new information when needed. The route table update port +is **not** supplied by the application, but is supplied via +an environment variable as this value is likely determined by +the mechanism which is starting and configuring the +application. + + +The RMR Context +--------------- + +On successful initialisation, a void pointer, often called a +*handle* by some programming languages, is returned to the +application. This is a reference to the RMR control +information and must be passed as the first parameter on most +RMR function calls. RMR refers to this as the context, or +ctx. + + +Wait For Ready +-------------- + +An application which is only receiving messages does not need +to wait for RMR to *become ready* after the call to the +initialization function. However, before the application can +successfully send a message, RMR must have loaded a route +table, and the application must wait for RMR to report that +it has done so. The RMR function ``rmr_ready()`` will return +the value *true* (1) when a complete route table has been +loaded and can be used to determine the endpoint for a send +request. + + +Receiving Messages +------------------ + +The process of receiving is fairly straight forward. The +application invokes the RMR ``rmr_rcv_msg()`` function which +will block until a message is received. The function returns +a pointer to a message block which provides all of the +details about the message. Specifically, the application has +access to the following information either directly or +indirectly: + + +* The payload (actual data) + +* The total payload length in bytes + +* The number of bytes of the payload which contain valid data + +* The message type and subscription ID values + +* The hostname and IP address of the source of the message + (the sender) + +* The transaction ID + +* Tracing data (if provided) + + + + +The Message Payload +------------------- + +The message payload contains the *raw* data that was sent by +the peer application. The format will likely depend on the +message type, and is expected to be known by the application. +A direct pointer to the payload is available from the message +buffer (see appendix B for specific message buffer details). + +Two payload-related length values are also directly +available: the total payload length, and the number of bytes +actually filled with data. The used length is set by the +caller, and may or not be an accurate value. The total +payload length is determined when the buffer is created for +sending, and is the maximum number of bytes that the +application may modify should the buffer be used to return a +response. + + +Message Type and Subscription ID +-------------------------------- + +The message type and subscription ID are both directly +available from the message buffer, and are the values which +were used to by RMR in the sending application to select the +endpoint. If the application resends the message, as opposed +to returning the message buffer as a response, the message +number and/or the subscription ID might need to be changed to +avoid potential issues[1]. + + +Sender Information +------------------ + +The source, or sender information, is indirectly available to +the application via the ``rmr_get_src()`` and +``rmr_get_ip()`` functions. The former returns a string +containing ``hostname:port,`` while the string +``ip:port`` is returned by the latter. + + +Transaction ID +-------------- + +The message buffer contains a fixed length set of bytes which +applications can set to track related messages across the +application concept of a transaction. RMR will use the +transaction ID for matching a response message when the +``rmr_call()`` function is used to send a message. + + +Trace Information +----------------- + +RMR supports the addition of an optional trace information to +any message. The presence and size is controlled by the +application, and can vary from message to message if desired. +The actual contents of the trace information is determined by +the application; RMR provides only the means to set, extract, +and obtain a direct reference to the trace bytes. The trace +data field in a message buffer is discussed in greater detail +in the *Trace Data* section. + + +Sending Messages +---------------- + +Sending requires only slightly more work on the part of the +application than receiving a message. The application must +allocate an RMR message buffer, populate the message payload +with data, set the message type and length, and optionally +set the subscription ID. Information such as the source IP +address, hostname, and port are automatically added to the +message buffer by RMR, so there is no need for the +application to worry about these. + + +Message Buffer Allocation +------------------------- + +The function ``rmr_msg_alloc()`` allocates a *zero copy* +buffer and returns a pointer to the RMR ``rmr_mbuf_t`` +structure. The message buffer provides direct access to the +payload, length, message type and subscription ID fields. The +buffer must be preallocated in order to allow the underlying +transport mechanism to allocate the payload space from its +internal memory pool; this eliminates multiple copies as the +message is sent, and thus is more efficient. + +If a message buffer has been received, and the application +wishes to use the buffer to send a response, or to forward +the buffer to another application, a new buffer does **not** +need to be allocated. The application may set the necessary +information (message type, etc.), and adjust the payload, as +is necessary and then pass the message buffer to +``rmr_send_msg()`` or ``rmr_rts_msg()`` to be sent or +returned to the sender. + + +Populating the Message Buffer +----------------------------- + +The application has direct access to several of the message +buffer fields, and should set them appropriately. + + + .. list-table:: + :widths: 15,80 + :header-rows: 0 + :class: borderless + + * - **len** + - + This is the number of bytes that the application placed into + the payload. Setting length to 0 is allowed, and length may + be less than the allocated payload size. + + * - **mtype** + - + The message type that RMR will use to determine the endpoint + used as the target of the send. + + * - **sub_id** + - + The subscription ID if the message is to be routed based on + the combination of message type and subscription ID. If no + subscription ID is valid for the message, the application + should set the field with the RMR constant + ``RMR_VOID_SUBID.`` + + * - **payload** + - + The application should obtain the reference (pointer) to the + payload from the message buffer and place any data into the + payload. The application is responsible for ensuring that the + maximum payload size is not exceeded. The application may + obtain the maximum size via the ``rmr_payload_size()`` + function. + + * - **trace data** + - + Optionally, the application may add trace information to the + message buffer. + + + + + +Sending a Message Buffer +------------------------ + +Once the application has populated the necessary bits of a +message, it may be sent by passing the buffer to the +``rmr_send_msg()`` function. This function will select an +endpoint to receive the message, based on message type and +subscription ID, and will pass the message to the underlying +transport mechanism for actual transmission on the +connection. (Depending on the underlying transport mechanism, +the actual connection to the endpoint may happen at the time +of the first message sent to the endpoint, and thus the +latency of the first send might be longer than expected.) + +On success, the send function will return a reference to a +message buffer; the status within that message buffer will +indicate what the message buffer contains. When the status is +``RMR_OK`` the reference is to a **new** message buffer for +the application to use for the next send; the payload size is +the same as the payload size allocated for the message that +was just sent. This is a convenience as it eliminates the +need for the application to call the message allocation +function at some point in the future, and assumes the +application will send many messages which will require the +same payload dimensions. + +If the message contains any status other than ``RMR_OK,`` +then the message could **not** be sent, and the reference is +to the unsent message buffer. The value of the status will +indicate whether the nature of the failure was transient ( +``RMR_ERR_RETRY``) or not. Transient failures are likely to +be successful if the application attempts to send the message +at a later time. Unfortunately, it is impossible for RMR to +know the exact transient failure (e.g. connection being +established, or TCP buffer shortage), and thus it is not +possible to communicate how long the application should wait +before attempting to resend, if the application wishes to +resend the message. (More discussion with respect to message +retries can be found in the *Handling Failures* section.) + + +Advanced Usage +============== + +Several forms of usage fall into a more advanced category and +are described in the following sections. These include +blocking call, return to sender and wormhole functions. + + +The Call Function +----------------- + +The RMR function ``rmr_call()`` sends a message in the exact +same manner as the ``rmr_send_msg()()`` function, with the +endpoint selection based on the message key. But unlike the +send function, ``rmr_call()`` will block and wait for a +response from the application that is selected to receive the +message. The matching message is determined by the +transaction ID which the application must place into the +message buffer prior to invoking ``rmr_call()``. Similarly, +the responding application must ensure that the same +transaction ID is placed into the message buffer before +returning its response. + +The return from the call is a message buffer with the +response message; there is no difference between a message +buffer returned by the receive function and one returned by +the ``rmr_call()`` function. If a response is not received in +a reasonable amount of time, a nil message buffer is returned +to the calling application. + + +Returning a Response +-------------------- + +Because of the nature of RMR's routing policies, it is +generally not possible for an application to control exactly +which endpoint is sent a message. There are cases, such as +responding to a message delivered via ``rmr_call()`` that the +application must send a message and guarantee that RMR routes +it to an exact destination. To enable this, RMR provides the +``rmr_rts_msg(),`` return to sender, function. Upon receipt +of any message, an application may alter the payload, and if +necessary the message type and subscription ID, and pass the +altered message buffer to the ``rmr_rts_msg()`` function to +return the altered message to the application which sent it. +When this function is used, RMR will examine the message +buffer for the source information and use that to select the +connection on which to write the response. + + +Multi-threaded Calls +-------------------- + +The basic call mechanism described above is **not** thread +safe, as it is not possible to guarantee that a response +message is delivered to the correct thread. The RMR function +``rmr_mt_call()`` accepts an additional parameter which +identifies the calling thread in order to ensure that the +response is delivered properly. In addition, the application +must specifically initialise the multi-threaded call +environment by passing the ``RMRFL_MTCALL`` flag as an option +to the ``rmr_init()`` function. + +One advantage of the multi-threaded call capability in RMR is +the fact that only the calling thread is blocked. Messages +received which are not responses to the call are continued to +be delivered via normal ``rmr_rcv_msg()`` calls. + +While the process is blocked waiting for the response, it is +entirely possible that asynchronous, non-matching, messages +will arrive. When this happens, RMR will queues the messages +and return them to the application over the next calls to +``rmr_rcv_msg().`` + + +Wormholes +--------- + +As was mentioned earlier, the design of RMR is to eliminate +the need for an application to know a specific endpoint, even +when a response message is being sent. In some rare cases it +may be necessary for an application to establish a direct +connection to an RMR-based application rather than relying on +message type and subscription ID based routing. The +*wormhole* functions provide an application with the ability +to create a direct connection and then to send and receive +messages across the connection. The following are the RMR +functions which provide wormhole communications: + + + .. list-table:: + :widths: auto + :header-rows: 0 + :class: borderless + + * - **rmr_wh_open** + - + Open a connection to an endpoint. Name or IP address and port + of the endpoint is supplied. Returns a wormhole ID that the + application must use when sending a direct message. + + * - **rmr_wh_send_msg** + - + Sends an RMR message buffer to the connected application. The + message type and subscription ID may be set in the message, + but RMR will ignore both. + + * - **rmr_wh_close** + - + Closes the direct connection. + + + + + +Handling Failures +================= + +The vast majority of states reported by RMR are fatal; if +encountered during setup or initialization, then it is +unlikely that any message oriented processing should +continue, and when encountered on a message operation +continued operation on that message should be abandoned. +Specifically with regard to message sending, it is very +likely that the underlying transport mechanism will report a +*soft,* or transient, failure which might be successful if +the operation is retried at a later point in time. The +paragraphs below discuss the methods that an application +might deal with these soft failures. + + +Failure Notification +-------------------- + +When a soft failure is reported, the returned message buffer +returned by the RMR function will be ``RMR_ERR_RETRY.`` These +types of failures can occur for various reasons; one of two +reasons is typically the underlying cause: + + +* The session to the targeted recipient (endpoint) is not + connected. + +* The transport mechanism buffer pool is full and cannot + accept another buffer. + + + +Unfortunately, it is not possible for RMR to determine which +of these two cases is occurring, and equally as unfortunate +the time to resolve each is different. The first, no +connection, may require up to a second before a message can +be accepted, while a rejection because of buffer shortage is +likely to resolve in less than a millisecond. + + +Application Response +-------------------- + +The action which an application takes when a soft failure is +reported ultimately depends on the nature of the application +with respect to factors such as tolerance to extended message +latency, dropped messages, and over all message rate. + + +RMR Retry Modes +--------------- + +In an effort to reduce the workload of an application +developer, RMR has a default retry policy such that RMR will +attempt to retransmit a message up to 1000 times when a soft +failure is reported. These retries generally take less than 1 +millisecond (if all 1000 are attempted) and in most cases +eliminates nearly all reported soft failures to the +application. When using this mode, it might allow the +application to simply treat all bad return values from a send +attempt as permanent failures. + +If an application is so sensitive to any delay in RMR, or the +underlying transport mechanism, it is possible to set RMR to +return a failure immediately on any kind of error (permanent +failures are always reported without retry). In this mode, +RMR will still set the state in the message buffer to +``RMR_ERR_RETRY,`` but will **not** make any attempts to +resend the message. This zero-retry policy is enabled by +invoking the ``rmr_set_stimeout()`` with a value of 0; this +can be done once immediately after ``rmr_init()`` is invoked. + +Regardless of the retry mode which the application sets, it +will ultimately be up to the application to handle failures +by queuing the message internally for resend, retrying +immediately, or dropping the send attempt all together. As +stated before, only the application can determine how to best +handle send failures. + + +Other Failures +-------------- + +RMR will return the state of processing for message based +operations (send/receive) as the status in the message +buffer. For non-message operations, state is returned to the +caller as the integer return value for all functions which +are not expected to return a pointer (e.g. +``rmr_init()``.) The following are the RMR state constants +and a brief description of their meaning. + + + .. list-table:: + :widths: auto + :header-rows: 0 + :class: borderless + + * - **RMR_OK** + - + state is good; operation finished successfully + + * - **RMR_ERR_BADARG** + - + argument passed to function was unusable + + * - **RMR_ERR_NOENDPT** + - + send/call could not find an endpoint based on msg type + + * - **RMR_ERR_EMPTY** + - + msg received had no payload; attempt to send an empty message + + * - **RMR_ERR_NOHDR** + - + message didn't contain a valid header + + * - **RMR_ERR_SENDFAILED** + - + send failed; errno may contain the transport provider reason + + * - **RMR_ERR_CALLFAILED** + - + unable to send the message for a call function; errno may + contain the transport provider reason + + * - **RMR_ERR_NOWHOPEN** + - + no wormholes are open + + * - **RMR_ERR_WHID** + - + the wormhole id provided was invalid + + * - **RMR_ERR_OVERFLOW** + - + operation would have busted through a buffer/field size + + * - **RMR_ERR_RETRY** + - + request (send/call/rts) failed, but caller should retry + (EAGAIN for wrappers) + + * - **RMR_ERR_RCVFAILED** + - + receive failed (hard error) + + * - **RMR_ERR_TIMEOUT** + - + response message not received in a reasonable amount of time + + * - **RMR_ERR_UNSET** + - + the message hasn't been populated with a transport buffer + + * - **RMR_ERR_TRUNC** + - + length in the received buffer is longer than the size of the + allocated payload, received message likely truncated (length + set by sender could be wrong, but we can't know that) + + * - **RMR_ERR_INITFAILED** + - + initialisation of something (probably message) failed + + * - **RMR_ERR_NOTSUPP** + - + the request is not supported, or RMR was not initialised for + the request + + + +Depending on the underlying transport mechanism, and the +nature of the call that RMR attempted, the system +``errno`` value might reflect additional detail about the +failure. Applications should **not** rely on errno as some +transport mechanisms do not set it with any consistency. + + +Configuration and Control +========================= + +With the assumption that most RMR based applications will be +executed in a containerised environment, there are some +underlying mechanics which the developer may need to know in +order to properly provide a configuration specification to +the container management system. The following paragraphs +briefly discuss these. + + + +TCP Ports +--------- + +RMR requires two (2) TCP listen ports: one for general +application-to-application communications and one for +route-table updates. The general communication port is +specified by the application at the time RMR is initialised. +The port used to listen for route table updates is likely to +be a constant port shared by all applications provided they +are running in separate containers. To that end, the port +number defaults to 4561, but can be configured with an +environment variable (see later paragraph in this section). + + +Host Names +---------- + +RMR is typically host name agnostic. Route table entries may +contain endpoints defined either by host name or IP address. +In the container world the concept of a *service name* might +exist, and likely is different than a host name. RMR's only +requirement with respect to host names is that a name used on +a route table entry must be resolvable via the +``gethostbyname`` system call. + + +Environment Variables +--------------------- + +Several environment variables are recognised by RMR which, in +general, are used to define interfaces and listen ports (e.g. +the route table update listen port), or debugging +information. Generally this information is system controlled +and thus RMR expects this information to be defined in the +environment rather than provided by the application. The +following is a list of the environment variables which RMR +recognises: + + + .. list-table:: + :widths: auto + :header-rows: 0 + :class: borderless + + * - **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) mode. This + will likely result in many "soft failures" (retry) until the + connection is established, but allows 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. + + * - **RMR_CTL_PORT** + - + This variable defines the port that RMR should open for + communications with Route Manager, and other RMR control + applications. If not defined, the port 4561 is assumed. + + Previously, the ``RMR_RTG_SVC`` (route table generator + service 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's well-known address and port. + + 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 manager is + used (routemgr:4561). + + When ``RMR_CTL_PORT`` is **undefined:** RMR assumes that + Route Manager will connect and push table updates, thus the + default listen port (4561) is used. + + To avoid any possible misinterpretation and/or incorrect + assumptions on the part of RMR, it is recommended that both + the ``RMR_CTL_PORT`` and ``RMR_RTG_SVC`` be defined. In the + case where both variables are defined, RMR will behave + exactly as is communicated with the variable's values. + + * - **RMR_RTREQ_FREQ** + - + When RMR needs a new route table it will send a request once + every ``n`` seconds. The default value for ``n`` is 5, but + can be changed if this variable is set prior to invoking the + process. Accepted values are between 1 and 300 inclusive. + + * - **RMR_RTG_SVC** + - + The value of this variable depends on the Route Manager in + use. + + When the Route Manager is expecting to connect to an xAPP and + push route tables, this variable must indicate the + ``port`` which RMR should use to listen for these + connections. + + When the Route Manager is expecting RMR to connect and + request a table update during initialisation, the variable + should be the ``host`` of the Route Manager process. + + The ``RMR_CTL_PORT`` variable (added with the support of + sending table update requests to Route manager), controls the + behaviour if this variable is not set. See the description of + that variable for details. + + * - **RMR_HR_LOG** + - + By default RMR writes messages to standard error (incorrectly + referred to as log messages) in human readable format. If + this environment variable is set to 0, the format of standard + error messages might be written in some format not easily + read by humans. If missing, a value of 1 is assumed. + + * - **RMR_LOG_VLEVEL** + - + This is a numeric value which corresponds to the verbosity + level used to limit messages written to standard error. The + lower the number the less chatty RMR functions are during + execution. The following is the current relationship between + the value set on this variable and the messages written: + + + .. list-table:: + :widths: auto + :header-rows: 0 + :class: borderless + + * - **0** + - + Off; no messages of any sort are written. + + * - **1** + - + Only critical messages are written (default if this variable + does not exist) + + * - **2** + - + Errors and all messages written with a lower value. + + * - **3** + - + Warnings and all messages written with a lower value. + + * - **4** + - + Informational and all messages written with a lower value. + + * - **5** + - + Debugging mode -- all messages written, however this requires + RMR to have been compiled with debugging support enabled. + + + + * - **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. + + This variable is only recognised when using the NNG transport + library as it is not possible to support NNG "raw" + communications with other transport libraries. It is also + necessary to match the value of this variable with the + capabilities of the Route Manager; at some point in the + future RMR will assume that all Route Manager messages will + arrive via an RMR connection and will ignore this variable. + + * - **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. 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). + + * - **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. + + The value of this variable is also used for Route Manager + messages which are sent via an RMR connection. + + * - **RMR_STASH_RT** + - + Names the file where RMR should write the latest update it + receives from the source of route tables (generally Route + Manager). This is meant to assist with debugging and/or + troubleshooting when it is suspected that route information + isn't being sent and/or received correctly. If this variable + is not given, RMR will save the last update using the + ``RMR_SEED_RT`` variable value and adding a ``.stash`` suffix + to the filename so as not to overwrite the static table. + + * - **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. + + + +There are other, non-RMR, variables which may exist and are +used by RMR. These variable names are not under the control +of RMR, so they are subject to change without potentiallyb +being reflected in either RMR's code, or this document. The +following is a list of these environment variables. + + + .. list-table:: + :widths: auto + :header-rows: 0 + :class: borderless + + * - **ALARM_MANAGER_SERVICE_NAME** + - + This is the DNS name, or IP address, of the process which is + listening for RMR alarm messages. If this variable is + missing, ``service-ricplt-alarmmanager-rmr`` is assumed. + + * - **ALARM_MANAGER_SERVICE_PORT** + - + This is the port that the alarm manager is using to accept + RMR messages. If the environment variable is missing the + value ``4560`` is assumed. + + + + +Logging and Alarms +------------------ + +As with nearly all UNIX libraries, errors, warnings and +informational messages are written in plain text to the +standard error device (stderr). All RMR messages are prefixed +with the current time (in milliseconds past the standard UNIX +epoch), the process ID, and a severity indicator. RMR +messages are written with one of three severity strings: + + + .. list-table:: + :widths: auto + :header-rows: 0 + :class: borderless + + * - **[CRI]** + - + The event is of a critical nature and it is unlikely that RMR + will continue to operate correctly if at all. It is almost + certain that immediate action will be needed to resolve the + issue. + + * - **[ERR]** + - + The event is not expected and RMR is not able to handle it. + There is a small chance that continued operation will be + negatively impacted. Eventual action to diagnose and correct + the issue will be necessary. + + * - **[WRN]** + - + The event was not expected by RMR, but can be worked round. + Normal operation will continue, but it is recommended that + the cause of the problem be investigated. + + + + + +Log message supression +---------------------- + +For the most part, the *fast path* code in RMR does no +logging; even when messages are squelched, there is a +non-zero cosst to check for the setting each time a potential +message is to be written. To that end, RMRM will log only +severe errors once initialisation has completed. An exception +to this policy exists in the route table collection thread. +The thread of execution which collects route table updates +does not need to be concerned with performance, and as such +has the potential to log its actions in a very verbose +manner. The environment variable `` RMR_VCTL_FILE `` can be +used to define a file where the desired verbosity level (0 to +4 where 0 is off) can be placed. If the environment variable +is not set when the process starts, RMR will assume that the +file ``/tmp/rmr.v`` will be used. Beginning with version +4.6.0 this file does **not** need to exist when the process +is started. To change the verbosity level, the desired value +is written to the file on the first line. + + +Alarms +------ + +The route table colleciton thread is also responsible for +watching for situations which need to be reported as alarms +to the platform's alarm management service. When a state +exists RMR will create and send an alarm (via RMR message) to +the alarm service, and will send a *clear* message when the +state no longer exists. Currently RMR will alarm only when +the application is not removing messages from the receive +ring quicklye enough causing RMR to drop messages as they are +received. + + +Notes +===== + + + [1] It is entirely possible to design a routing table, and + application group, such that the same message type is is + left unchanged and the message is forwarded by an + application after updating the payload. This type of + behaviour is often referred to as service chaining, and can + be done without any "knowledge" by an application with + respect to where the message goes next. Service chaining is + supported by RMR in as much as it allows the message to be + resent, but the actual complexities of designing and + implementing service chaining lie with the route table + generator process. + + + + + + +Appendix A -- Quick Reference +============================= + +Please refer to the RMR manual pages on the Read the Docs +site + +https://docs.o-ran-sc.org/projects/o-ran-sc-ric-plt-lib-rmr/en/latest/index.html + + + +Appendix B -- Message Buffer Details +==================================== + +The RMR message buffer is a C structure which is exposed in +the ``rmr.h`` header file. It is used to manage a message +received from a peer endpoint, or a message that is being +sent to a peer. Fields include payload length, amount of +payload actually used, status, and a reference to the +payload. There are also fields which the application should +ignore, and could be hidden in the header file, but we chose +not to. These fields include a reference to the RMR header +information, and to the underlying transport mechanism +message struct which may or may not be the same as the RMR +header reference. + + +The Structure +------------- + +The following is the C structure. Readers are cautioned to +examine the ``rmr.h`` header file directly; the information +here may be out of date (old document in some cache), and +thus it may be incorrect. + + +:: + + + typedef struct { + int state; // state of processing + int mtype; // message type + int len; // length of data in the payload (send or received) + unsigned char* payload; // transported data + unsigned char* xaction; // pointer to fixed length transaction id bytes + int sub_id; // subscription id + int tp_state; // transport state (errno) + + // these things are off limits to the user application + void* tp_buf; // underlying transport allocated pointer (e.g. nng message) + void* header; // internal message header (whole buffer: header+payload) + unsigned char* id; // if we need an ID in the message separate from the xaction id + int flags; // various MFL_ (private) flags as needed + int alloc_len; // the length of the allocated space (hdr+payload) + void* ring; // ring this buffer should be queued back to + int rts_fd; // SI fd for return to sender + int cookie; // cookie to detect user misuse of free'd msg + } rmr_mbuf_t; + + + + +State vs Transport State +------------------------ + +The state field reflects the state at the time the message +buffer is returned to the calling application. For a send +operation, if the state is not ``RMR_OK`` then the message +buffer references the payload that could not be sent, and +when the state is ``RMR_OK`` the buffer references a *fresh* +payload that the application may fill in. + +When the state is not ``RMR_OK,`` C programmes may examine +the global ``errno`` value which RMR will have left set, if +it was set, by the underlying transport mechanism. In some +cases, wrapper modules are not able to directly access the +C-library ``errno`` value, and to assist with possible +transport error details, the send and receive operations +populate ``tp_state`` with the value of ``errno.`` + +Regardless of whether the application makes use of the +``tp_state,`` or the ``errno`` value, it should be noted that +the underlying transport mechanism may not actually update +the errno value; in other words: it might not be accurate. In +addition, RMR populates the ``tp_state`` value in the message +buffer **only** when the state is not ``RMR_OK.`` + + +Field References +---------------- + +The transaction field was exposed in the first version of +RMR, and in hindsight this shouldn't have been done. Rather +than break any existing code the reference was left, but +additional fields such as trace data, were not directly +exposed to the application. The application developer is +strongly encouraged to use the functions which get and set +the transaction ID rather than using the pointer directly; +any data overruns will not be detected if the reference is +used directly. + +In contrast, the payload reference should be used directly by +the application in the interest of speed and ease of +programming. The same care to prevent writing more bytes to +the payload buffer than it can hold must be taken by the +application. By the nature of the allocation of the payload +in transport space, RMR is unable to add guard bytes and/or +test for data overrun. + + +Actual Transmission +------------------- + +When RMR sends the application's message, the message buffer +is **not** transmitted. The transport buffer (tp_buf) which +contains the RMR header and application payload is the only +set of bytes which are transmitted. While it may seem to the +caller like the function ``rmr_send_msg()`` is returning a +new message buffer, the same struct is reused and only a new +transport buffer is allocated. The intent is to keep the +alloc/free cycles to a minimum. + + + +Appendix C -- Glossary +====================== + +Many terms in networking can be interpreted with multiple +meanings, and several terms used in various RMR documentation +are RMR specific. The following definitions are the meanings +of terms used within RMR documentation and should help the +reader to understand the intent of meaning. + + .. list-table:: + :widths: 25,70 + :header-rows: 0 + :class: borderless + + * - **application** + - + A programme which uses RMR to send and/or receive messages + to/from another RMR based application. + + * - **Critical error** + - + An error that RMR has encountered which will prevent further + successful processing by RMR. Critical errors usually + indicate that the application should abort. + + * - **Endpoint** + - + An RMR based application that is defined as being capable of + receiving one or more types of messages (as defined by a + *routing key.*) + + * - **Environment variable** + - + A key/value pair which is set externally to the application, + but which is available to the application (and referenced + libraries) through the ``getenv`` system call. Environment + variables are the main method of communicating information + such as port numbers to RMR. + + * - **Error** + - + An abnormal condition that RMR has encountered, but will not + affect the overall processing by RMR, but may impact certain + aspects such as the ability to communicate with a specific + endpoint. Errors generally indicate that something, usually + external to RMR, must be addressed. + + * - **Host name** + - + The name of the host as returned by the ``gethostbyname`` + system call. In a containerised environment this might be the + container or service name depending on how the container is + started. From RMR's point of view, a host name can be used to + resolve an *endpoint* definition in a *route* table.) + + * - **IP** + - + Internet protocol. A low level transmission protocol which + governs the transmission of datagrams across network + boundaries. + + * - **Listen socket** + - + A *TCP* socket used to await incoming connection requests. + Listen sockets are defined by an interface and port number + combination where the port number is unique for the + interface. + + * - **Message** + - + A series of bytes transmitted from the application to another + RMR based application. A message is comprised of RMR specific + data (a header), and application data (a payload). + + * - **Message buffer** + - + A data structure used to describe a message which is to be + sent or has been received. The message buffer includes the + payload length, message type, message source, and other + information. + + * - **Message type** + - + A signed integer (0-32000) which identifies the type of + message being transmitted, and is one of the two components + of a *routing key.* See *Subscription ID.* + + * - **Payload** + - + The portion of a message which holds the user data to be + transmitted to the remote *endpoint.* The payload contents + are completely application defined. + + * - **RMR context** + - + A set of information which defines the current state of the + underlying transport connections that RMR is managing. The + application will be give a context reference (pointer) that + is supplied to most RMR functions as the first parameter. + + * - **Round robin** + - + The method of selecting an *endpoint* from a list such that + all *endpoints* are selected before starting at the head of + the list. + + * - **Route table** + - + A series of "rules" which define the possible *endpoints* for + each *routing key.* + + * - **Route table manager** + - + An application responsible for building a *route table* and + then distributing it to all applicable RMR based + applications. + + * - **Routing** + - + The process of selecting an *endpoint* which will be the + recipient of a message. + + * - **Routing key** + - + A combination of *message type* and *subscription ID* which + RMR uses to select the destination *endpoint* when sending a + message. + + * - **Source** + - + The sender of a message. + + * - **Subscription ID** + - + A signed integer value (0-32000) which identifies the + subscription characteristic of a message. It is used in + conjunction with the *message type* to determine the *routing + key.* + + * - **Target** + - + The *endpoint* selected to receive a message. + + * - **TCP** + - + Transmission Control Protocol. A connection based internet + protocol which provides for lossless packet transportation, + usually over IP. + + * - **Thread** + - + Also called a *process thread, or pthread.* This is a + lightweight process which executes in concurrently with the + application and shares the same address space. RMR uses + threads to manage asynchronous functions such as route table + updates. + + * - **Trace information** + - + An optional portion of the message buffer that the + application may populate with data that allows for tracing + the progress of the transaction or application activity + across components. RMR makes no use of this data. + + * - **Transaction ID** + - + A fixed number of bytes in the *message* buffer) which the + application may populate with information related to the + transaction. RMR makes use of the transaction ID for matching + response messages with the &c function is used to send a + message. + + * - **Transient failure** + - + An error state that is believed to be short lived and that + the operation, if retried by the application, might be + successful. C programmers will recognise this as + ``EAGAIN.`` + + * - **Warning** + - + A warning occurs when RMR has encountered something that it + believes isn't correct, but has a defined work round. + + * - **Wormhole** + - + A direct connection managed by RMR between the user + application and a remote, RMR based, application. + + + + + +Appendix D -- Code Examples +=========================== + +The following snippet of code illustrate some of the basic +operation of the RMR library. Please refer to the examples +and test directories in the RMR repository for complete RMR +based programmes. + + +Sender Sample +------------- + +The following code segment shows how a message buffer can be +allocated, populated, and sent. The snippet also illustrates +how the result from the ``rmr_send_msg()`` function is used +to send the next message. It does not illustrate error and/or +retry handling. + + +:: + + + #include + #include + #include + #include + #include + #include + #include + + #include + + int main( int argc, char** argv ) { + void* mrc; // msg router context + struct epoll_event events[1]; // list of events to give to epoll + struct epoll_event epe; // event definition for event to listen to + int ep_fd = -1; // epoll's file des (given to epoll_wait) + int rcv_fd; // file des for epoll checks + int nready; // number of events ready for receive + rmr_mbuf_t* sbuf; // send buffer + rmr_mbuf_t* rbuf; // received buffer + int count = 0; + int rcvd_count = 0; + char* listen_port = "43086"; + int delay = 1000000; // mu-sec delay between messages + int mtype = 0; + int stats_freq = 100; + + if( argc > 1 ) { // simplistic arg picking + listen_port = argv[1]; } - // 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; - - - -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_fack - -SYNOPSIS --------------------------------------------------------------------------------------------- - - -:: - - #include - void rmr_set_fack( void* vctx ); - - - -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 -maximum rate. - -RETURN VALUE --------------------------------------------------------------------------------------------- - -There is no return value. - -ERRORS --------------------------------------------------------------------------------------------- - -This function does not generate any errors. - -SEE ALSO --------------------------------------------------------------------------------------------- - -rmr_init(3), - - -NAME --------------------------------------------------------------------------------------------- - -rmr_set_stimeout - -SYNOPSIS --------------------------------------------------------------------------------------------- - - -:: - - #include - 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 - int rmr_set_trace( 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_set_trace - -SYNOPSIS --------------------------------------------------------------------------------------------- - - -:: - - #include - #include - void rmr_set_vlevel( int new_level ) - - - -DESCRIPTION --------------------------------------------------------------------------------------------- - -The rmr_set_vlevel allows the user programme to set the -verbosity level which is used to determine the messages RMR -writes to standard error. The new_vlevel value must be one of -the following constants which have the indicated meanings: - - -RMR_VL_OFF - - Turns off all message writing. This includes the stats and - debugging messages generated by the route collector thread - which are normally affected only by the externally managed - verbose level file (and related environment variable). - - -RMR_VL_CRIT - - Write only messages of critical importance. From the point - of view of RMR, when a critical proper behaviour of the - library cannot be expected or guaranteed. - -RMR_VL_ERR - - Include error messages in the output. An error is an event - from which RMR has no means to recover. Continued proper - execution is likely except where the affected connection - and/or component mentioned in the error is concerned. - -RMR_VL_WARN - - Include warning messages in the output. A warning - indicates an event which is not considered to be normal, - but is expected and continued acceptable behaviour of the - system is assured. - -RMR_VL_INFO - - Include informational messagees in the output. - Informational messages include some diagnostic information - which explain the activities of RMR. - -RMR_VL_DEBUG - - Include all debugging messages in the output. Debugging - must have also been enabled during the build as a - precaution to accidentally enabling this level of output - as it can grossly affect performance. - - -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. - -Messages written from the route table collection thread are -still governed by the value placed into the verbose level -control file (see the man page for rmr_init()); those -messages are affected only when logging is completely -disabled by passing RMR_VL_OFF to this function. - -The verbosity level can also be set via an environment -variable prior to the start of the RMR based application. The -environment variable is read only during initialisation; if -the programme must change the value during execution, this -function must be used. The default value, if this function is -never called, and the environment variable is not present, is -RMR_VL_ERR. - -SEE ALSO --------------------------------------------------------------------------------------------- - -rmr_init(3) - - -NAME --------------------------------------------------------------------------------------------- - -rmr_str2meid - -SYNOPSIS --------------------------------------------------------------------------------------------- - - -:: - - #include - 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 entity 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 - 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 - #include - 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_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 - 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_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_call - -SYNOPSIS --------------------------------------------------------------------------------------------- - - -:: - - #include - 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 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, 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 .// 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_call( mrc, whid, sbuf, 1000 ); f s// expect a response in 1s or less - if( sbuf != NULL && sbuf->state = RMR_OK ) { - sprintf( stderr, "response: %s\\n", sbuf->payload ); x// 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_open - -SYNOPSIS --------------------------------------------------------------------------------------------- - - -:: - - #include - 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 - 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_close(3), -rmr_wh_send_msg(3), rmr_wh_state(3) - - -NAME --------------------------------------------------------------------------------------------- - -rmr_wh_send_msg - -SYNOPSIS --------------------------------------------------------------------------------------------- - - -:: - - #include - 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 .// 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), -rmr_wh_state(3) - - -NAME --------------------------------------------------------------------------------------------- - -rmr_wh_state - -SYNOPSIS --------------------------------------------------------------------------------------------- - - -:: - - #include - int rmr_wh_state( void* vctx, rmr_whid_t whid ) - - - -DESCRIPTION --------------------------------------------------------------------------------------------- - -The rmr_wh_state function will return the current state of -the connection associated with the given wormhole (whid). The -return value indicates whether the connection is open -(RMR_OK), or closed (any other return value). - -When using some transport mechanisms (e.g. NNG), it may not -be possible for RMR to know the actual state and the -connection may always be reported as "open." - -RETURN --------------------------------------------------------------------------------------------- - -The following values are potential return values. - - - -RMR_OK - - The wormhole ID is valid and the connection is "open." - - -RMR_ERR_WHID - - THe wormhole ID passed into the function was not valid. - - -RMR_ERR_NOENDPT - - The wormhole is not open (not connected). - - -RMR_ERR_BADARG - - The context passed to the function was nil or invalid. - - -RMR_ERR_NOWHOPEN - - Wormholes have not been initialised (no wormhole open call - has been made). - - - -SEE ALSO --------------------------------------------------------------------------------------------- - -rmr_wh_open(3), rmr_wh_send_msg(3), rmr_wh_close(3) + if( argc > 2 ) { + delay = atoi( argv[2] ); + } + if( argc > 3 ) { + mtype = atoi( argv[3] ); + } + + fprintf( stderr, " listen port: %s; mtype: %d; delay: %d\\n", + listen_port, mtype, delay ); + + if( (mrc = rmr_init( listen_port, 1400, RMRFL_NONE )) == NULL ) { + fprintf( stderr, " unable to initialise RMR\\n" ); + exit( 1 ); + } + + rcv_fd = rmr_get_rcvfd( mrc ); // set up epoll things, start by getting the FD from RMR + if( rcv_fd < 0 ) { + fprintf( stderr, " unable to set up polling fd\\n" ); + exit( 1 ); + } + if( (ep_fd = epoll_create1( 0 )) < 0 ) { + fprintf( stderr, "[FAIL] unable to create epoll fd: %d\\n", errno ); + exit( 1 ); + } + epe.events = EPOLLIN; + epe.data.fd = rcv_fd; + + if( epoll_ctl( ep_fd, EPOLL_CTL_ADD, rcv_fd, &epe ) != 0 ) { + fprintf( stderr, "[FAIL] epoll_ctl status not 0 : %s\\n", strerror( errno ) ); + exit( 1 ); + } + + sbuf = rmr_alloc_msg( mrc, 256 ); // alloc 1st send buf; subsequent bufs alloc on send + rbuf = NULL; // don't need to alloc receive buffer + + while( ! rmr_ready( mrc ) ) { // must have route table + sleep( 1 ); // wait til we get one + } + fprintf( stderr, " rmr is ready\\n" ); + + + while( 1 ) { // send messages until the cows come home + snprintf( sbuf->payload, 200, + "count=%d received= %d ts=%lld %d stand up and cheer!", // create the payload + count, rcvd_count, (long long) time( NULL ), rand() ); + + sbuf->mtype = mtype; // fill in the message bits + sbuf->len = strlen( sbuf->payload ) + 1; // send full ascii-z string + sbuf->state = 0; + sbuf = rmr_send_msg( mrc, sbuf ); // send & get next buf to fill in + while( sbuf->state == RMR_ERR_RETRY ) { // soft failure (device busy?) retry + sbuf = rmr_send_msg( mrc, sbuf ); // w/ simple spin that doesn't give up + } + count++; + + // check to see if anything was received and pull all messages in + while( (nready = epoll_wait( ep_fd, events, 1, 0 )) > 0 ) { // 0 is non-blocking + if( events[0].data.fd == rcv_fd ) { // waiting on 1 thing, so [0] is ok + errno = 0; + rbuf = rmr_rcv_msg( mrc, rbuf ); // receive and ignore; just count + if( rbuf ) { + rcvd_count++; + } + } + } + + if( (count % stats_freq) == 0 ) { // occasional stats out to tty + fprintf( stderr, " sent %d received %d\\n", count, rcvd_count ); + } + + usleep( delay ); + } + } + + + + +Receiver Sample +--------------- + +The receiver code is even simpler than the sender code as it +does not need to wait for a route table to arrive (only +senders need to do that), nor does it need to allocate an +initial buffer. The example assumes that the sender is +transmitting a zero terminated string as the payload. + + +:: + + + #include + #include + #include + #include + #include + + #include + + + int main( int argc, char** argv ) { + void* mrc; // msg router context + long long total = 0; + rmr_mbuf_t* msg = NULL; // message received + int stat_freq = 10; // write stats after reciving this many messages + int i; + char* listen_port = "4560"; // default to what has become the standard RMR port + long long count = 0; + long long bad = 0; + long long empty = 0; + + if( argc > 1 ) { + listen_port = argv[1]; + } + if( argc > 2 ) { + stat_freq = atoi( argv[2] ); + } + fprintf( stderr, " listening on port: %s\\n", listen_port ); + fprintf( stderr, " stats will be reported every %d messages\\n", stat_freq ); + + mrc = rmr_init( listen_port, RMR_MAX_RCV_BYTES, RMRFL_NONE ); + if( mrc == NULL ) { + fprintf( stderr, " ABORT: unable to initialise RMr\\n" ); + exit( 1 ); + } + + while( ! rmr_ready( mrc ) ) { // wait for RMR to get a route table + fprintf( stderr, " waiting for ready\\n" ); + sleep( 3 ); + } + fprintf( stderr, " rmr now shows ready\\n" ); + + while( 1 ) { // receive until killed + msg = rmr_rcv_msg( mrc, msg ); // block until one arrives + + if( msg ) { + if( msg->state == RMR_OK ) { + count++; // nothing fancy, just count + } else { + bad++; + } + } else { + empty++; + } + + if( (count % stat_freq) == 0 ) { + fprintf( stderr, " total received: %lld; errors: %lld; empty: %lld\\n", + count, bad, empty ); + } + } + } + + + + +Receive and Send Sample +----------------------- + +The following code snippet receives messages and responds to +the sender if the message type is odd. The code illustrates +how the received message may be used to return a message to +the source. Variable type definitions are omitted for clarity +and should be obvious. + +It should also be noted that things like the message type +which id returned to the sender (99) is a random value that +these applications would have agreed on in advance and is +**not** an RMR definition. + + +:: + + mrc = rmr_init( listen_port, MAX_BUF_SZ, RMRFL_NOFLAGS ); + rmr_set_stimeout( mrc, 1 ); // allow RMR to retry failed sends for ~1ms + + while( ! rmr_ready( mrc ) ) { // we send, therefore we need a route table + sleep( 1 ); + } + + mbuf = NULL; // ensure our buffer pointer is nil for 1st call + + while( TRUE ) { + mbuf = rmr_rcv_msg( mrc, mbuf ); // wait for message + + if( mbuf == NULL || mbuf->state != RMR_OK ) { + break; + } + + if( mbuf->mtype % 2 ) { // respond to odd message types + plen = rmr_payload_size( mbuf ); // max size + + // reset necessary fields in msg + mbuf->mtype = 99; // response type + mbuf->sub_id = RMR_VOID_SUBID; // we turn subid off + mbuf->len = snprintf( mbuf->payload, plen, "pong: %s", get_info() ); + + mbuf = rmr_rts_msg( mrc, mbuf ); // return to sender + if( mbuf == NULL || mbuf->state != RMR_OK ) { + fprintf( stderr, "return to sender failed\\n" ); + } + } + } + + fprintf( stderr, "abort: receive failure\\n" ); + rmr_close( mrc ); + + +