Add link to RTD index
[ric-plt/lib/rmr.git] / docs / user-guide.rst
1 .. This work is licensed under a Creative Commons Attribution 4.0 International License. 
2 .. SPDX-License-Identifier: CC-BY-4.0 
3 .. CAUTION: this document is generated from source in doc/src/rtd. 
4 .. To make changes edit the source and recompile the document. 
5 .. Do NOT make changes directly to .rst or .md files. 
6  
7 ============================================================================================ 
8 User's Guide 
9 ============================================================================================ 
10 -------------------------------------------------------------------------------------------- 
11 RIC Message Router -- RMR 
12 -------------------------------------------------------------------------------------------- 
13
14
15 Overview
16 ========
17
18 The RIC Message Router (RMR) is a library for peer-to-peer 
19 communication. Applications use the library to send and 
20 receive messages where the message routing and endpoint 
21 selection is based on the message type rather than DNS host 
22 name-IP port combinations. The library provides the following 
23 major features: 
24  
25  
26 * Routing and endpoint selection is based on *message type.* 
27    
28 * Application is insulated from the underlying transport 
29   mechanism and/or protocols. 
30    
31 * Message distribution (round robin or fanout) is selectable 
32   by message type. 
33    
34 * Route management updates are received and processed 
35   asynchronously and without overt application involvement. 
36  
37  
38
39
40 Purpose
41 -------
42
43 RMR's main purpose is to provide an application with the 
44 ability to send and receive messages to/from other peer 
45 applications with minimal effort on the application's part. 
46 To achieve this, RMR manages all endpoint information, 
47 connections, and routing information necessary to establish 
48 and maintain communication. From the application's point of 
49 view, all that is required to send a message is to allocate 
50 (via RMR) a message buffer, add the payload data, and set the 
51 message type. To receive a message, the application needs 
52 only to invoke the receive function; when a message arrives a 
53 message buffer will be returned as the function result. 
54
55
56 Message Routing
57 ---------------
58
59 Applications are required to place a message type into a 
60 message before sending, and may optionally add a subscription 
61 ID when appropriate. The combination of message type, and 
62 subscription ID are refered to as the *message key,* and is 
63 used to match an entry in a routing table which provides the 
64 possible endpoints expecting to receive messages with the 
65 matching key. 
66
67
68 Round Robin Delivery
69 --------------------
70
71 An endpoint from RMR's perspective is an application to which 
72 RMR may establish a connection, and expect to send messages 
73 with one or more defined message keys. Each entry in the 
74 route table consists of one or more endpoint groups, called 
75 round robin groups. When a message matches a specific entry, 
76 the entry's groups are used to select the destination of the 
77 message. A message is sent once to each group, with messages 
78 being *balanced* across the endpoints of a group via round 
79 robin selection. Care should be taken when defining multiple 
80 groups for a message type as there is extra overhead required 
81 and thus the overall message latency is somewhat increased. 
82
83
84 Routing Table Updates
85 ---------------------
86
87 Route table information is made available to RMR a static 
88 file (loaded once), or by updates sent from a separate route 
89 manager application. If a static table is provided, it is 
90 loaded during RMR initialization and will remain in use until 
91 an external process connects and delivers a route table 
92 update (often referred to as a dynamic update). Dynamic 
93 updates are listened for in a separate process thread and 
94 applied automatically; the application does not need to allow 
95 for, or trigger, updates. 
96
97
98 Latency And Throughput
99 ----------------------
100
101 While providing insulation from the underlying message 
102 transport mechanics, RMR must also do so in such a manner 
103 that message latency and throughput are not impacted. In 
104 general, the RMR induced overhead, incurred due to the 
105 process of selecting an endpoint for each message, is minimal 
106 and should not impact the overall latency or throughput of 
107 the application. This impact has been measured with test 
108 applications running on the same physical host and the 
109 average latency through RMR for a message was on the order of 
110 0.02 milliseconds. 
111  
112 As an application's throughput increases, it becomes easy for 
113 the application to overrun the underlying transport mechanism 
114 (e.g. NNG), consume all available TCP transmit buffers, or 
115 otherwise find itself in a situation where a send might not 
116 immediately complete. RMR offers different *modes* which 
117 allow the application to manage these states based on the 
118 overall needs of the application. These modes are discussed 
119 in the *Configuration* section of this document. 
120
121
122 General Use
123 ===========
124
125 To use, the RMR based application simply needs to initialise 
126 the RMR environment, wait for RMR to have received a routing 
127 table (become ready), and then invoke either the send or 
128 receive functions. These steps, and some behind the scenes 
129 details, are described in the following paragraphs. 
130
131
132 Initialisation
133 --------------
134
135 The RMR function ``rmr_init()`` is used to set up the RMR 
136 environment and must be called before messages can be sent or 
137 received. One of the few parameters that the application must 
138 communicate to RMR is the port number that will be used as 
139 the listen port for new connections. The port number is 
140 passed on the initialisation function call and a TCP listen 
141 socket will be opened with this port. If the port is already 
142 in use RMR will report a failure; the application will need 
143 to reinitialise with a different port number, abort, or take 
144 some other action appropriate for the application. 
145  
146 In addition to creating a TCP listen port, RMR will start a 
147 process thread which will be responsible for receiving 
148 dynamic updates to the route table. This thread also causes a 
149 TCP listen port to be opened as it is expected that the 
150 process which generates route table updates will connect and 
151 send new information when needed. The route table update port 
152 is **not** supplied by the application, but is supplied via 
153 an environment variable as this value is likely determined by 
154 the mechanism which is starting and configuring the 
155 application. 
156
157
158 The RMR Context
159 ---------------
160
161 On successful initialisation, a void pointer, often called a 
162 *handle* by some programming languages, is returned to the 
163 application. This is a reference to the RMR control 
164 information and must be passed as the first parameter on most 
165 RMR function calls. RMR refers to this as the context, or 
166 ctx. 
167
168
169 Wait For Ready
170 --------------
171
172 An application which is only receiving messages does not need 
173 to wait for RMR to *become ready* after the call to the 
174 initialization function. However, before the application can 
175 successfully send a message, RMR must have loaded a route 
176 table, and the application must wait for RMR to report that 
177 it has done so. The RMR function ``rmr_ready()`` will return 
178 the value *true* (1) when a complete route table has been 
179 loaded and can be used to determine the endpoint for a send 
180 request. 
181
182
183 Receiving Messages
184 ------------------
185
186 The process of receiving is fairly straight forward. The 
187 application invokes the RMR ``rmr_rcv_msg()`` function which 
188 will block until a message is received. The function returns 
189 a pointer to a message block which provides all of the 
190 details about the message. Specifically, the application has 
191 access to the following information either directly or 
192 indirectly: 
193  
194  
195 * The payload (actual data) 
196    
197 * The total payload length in bytes 
198    
199 * The number of bytes of the payload which contain valid data 
200    
201 * The message type and subscription ID values 
202    
203 * The hostname and IP address of the source of the message 
204   (the sender) 
205    
206 * The transaction ID 
207    
208 * Tracing data (if provided) 
209  
210  
211
212
213 The Message Payload
214 -------------------
215
216 The message payload contains the *raw* data that was sent by 
217 the peer application. The format will likely depend on the 
218 message type, and is expected to be known by the application. 
219 A direct pointer to the payload is available from the message 
220 buffer (see appendix B for specific message buffer details). 
221  
222 Two payload-related length values are also directly 
223 available: the total payload length, and the number of bytes 
224 actually filled with data. The used length is set by the 
225 caller, and may or not be an accurate value. The total 
226 payload length is determined when the buffer is created for 
227 sending, and is the maximum number of bytes that the 
228 application may modify should the buffer be used to return a 
229 response. 
230
231
232 Message Type and Subscription ID
233 --------------------------------
234
235 The message type and subscription ID are both directly 
236 available from the message buffer, and are the values which 
237 were used to by RMR in the sending application to select the 
238 endpoint. If the application resends the message, as opposed 
239 to returning the message buffer as a response, the message 
240 number and/or the subscription ID might need to be changed to 
241 avoid potential issues[1]. 
242
243
244 Sender Information
245 ------------------
246
247 The source, or sender information, is indirectly available to 
248 the application via the ``rmr_get_src()`` and 
249 ``rmr_get_ip()`` functions. The former returns a string 
250 containing ``hostname:port,`` while the string 
251 ``ip:port`` is returned by the latter. 
252
253
254 Transaction ID
255 --------------
256
257 The message buffer contains a fixed length set of bytes which 
258 applications can set to track related messages across the 
259 application concept of a transaction. RMR will use the 
260 transaction ID for matching a response message when the 
261 ``rmr_call()`` function is used to send a message. 
262
263
264 Trace Information
265 -----------------
266
267 RMR supports the addition of an optional trace information to 
268 any message. The presence and size is controlled by the 
269 application, and can vary from message to message if desired. 
270 The actual contents of the trace information is determined by 
271 the application; RMR provides only the means to set, extract, 
272 and obtain a direct reference to the trace bytes. The trace 
273 data field in a message buffer is discussed in greater detail 
274 in the *Trace Data* section. 
275
276
277 Sending Messages
278 ----------------
279
280 Sending requires only slightly more work on the part of the 
281 application than receiving a message. The application must 
282 allocate an RMR message buffer, populate the message payload 
283 with data, set the message type and length, and optionally 
284 set the subscription ID. Information such as the source IP 
285 address, hostname, and port are automatically added to the 
286 message buffer by RMR, so there is no need for the 
287 application to worry about these. 
288
289
290 Message Buffer Allocation
291 -------------------------
292
293 The function ``rmr_msg_alloc()`` allocates a *zero copy* 
294 buffer and returns a pointer to the RMR ``rmr_mbuf_t`` 
295 structure. The message buffer provides direct access to the 
296 payload, length, message type and subscription ID fields. The 
297 buffer must be preallocated in order to allow the underlying 
298 transport mechanism to allocate the payload space from its 
299 internal memory pool; this eliminates multiple copies as the 
300 message is sent, and thus is more efficient. 
301  
302 If a message buffer has been received, and the application 
303 wishes to use the buffer to send a response, or to forward 
304 the buffer to another application, a new buffer does **not** 
305 need to be allocated. The application may set the necessary 
306 information (message type, etc.), and adjust the payload, as 
307 is necessary and then pass the message buffer to 
308 ``rmr_send_msg()`` or ``rmr_rts_msg()`` to be sent or 
309 returned to the sender. 
310
311
312 Populating the Message Buffer
313 -----------------------------
314
315 The application has direct access to several of the message 
316 buffer fields, and should set them appropriately. 
317  
318  
319     .. list-table:: 
320       :widths: 15,80 
321       :header-rows: 0 
322       :class: borderless 
323        
324       * - **len** 
325         - 
326           This is the number of bytes that the application placed into 
327           the payload. Setting length to 0 is allowed, and length may 
328           be less than the allocated payload size. 
329        
330       * - **mtype** 
331         - 
332           The message type that RMR will use to determine the endpoint 
333           used as the target of the send. 
334        
335       * - **sub_id** 
336         - 
337           The subscription ID if the message is to be routed based on 
338           the combination of message type and subscription ID. If no 
339           subscription ID is valid for the message, the application 
340           should set the field with the RMR constant 
341           ``RMR_VOID_SUBID.`` 
342        
343       * - **payload** 
344         - 
345           The application should obtain the reference (pointer) to the 
346           payload from the message buffer and place any data into the 
347           payload. The application is responsible for ensuring that the 
348           maximum payload size is not exceeded. The application may 
349           obtain the maximum size via the ``rmr_payload_size()`` 
350           function. 
351        
352       * - **trace data** 
353         - 
354           Optionally, the application may add trace information to the 
355           message buffer. 
356            
357  
358  
359
360
361 Sending a Message Buffer
362 ------------------------
363
364 Once the application has populated the necessary bits of a 
365 message, it may be sent by passing the buffer to the 
366 ``rmr_send_msg()`` function. This function will select an 
367 endpoint to receive the message, based on message type and 
368 subscription ID, and will pass the message to the underlying 
369 transport mechanism for actual transmission on the 
370 connection. (Depending on the underlying transport mechanism, 
371 the actual connection to the endpoint may happen at the time 
372 of the first message sent to the endpoint, and thus the 
373 latency of the first send might be longer than expected.) 
374  
375 On success, the send function will return a reference to a 
376 message buffer; the status within that message buffer will 
377 indicate what the message buffer contains. When the status is 
378 ``RMR_OK`` the reference is to a **new** message buffer for 
379 the application to use for the next send; the payload size is 
380 the same as the payload size allocated for the message that 
381 was just sent. This is a convenience as it eliminates the 
382 need for the application to call the message allocation 
383 function at some point in the future, and assumes the 
384 application will send many messages which will require the 
385 same payload dimensions. 
386  
387 If the message contains any status other than ``RMR_OK,`` 
388 then the message could **not** be sent, and the reference is 
389 to the unsent message buffer. The value of the status will 
390 indicate whether the nature of the failure was transient ( 
391 ``RMR_ERR_RETRY``) or not. Transient failures are likely to 
392 be successful if the application attempts to send the message 
393 at a later time. Unfortunately, it is impossible for RMR to 
394 know the exact transient failure (e.g. connection being 
395 established, or TCP buffer shortage), and thus it is not 
396 possible to communicate how long the application should wait 
397 before attempting to resend, if the application wishes to 
398 resend the message. (More discussion with respect to message 
399 retries can be found in the *Handling Failures* section.) 
400
401
402 Advanced Usage
403 ==============
404
405 Several forms of usage fall into a more advanced category and 
406 are described in the following sections. These include 
407 blocking call, return to sender and wormhole functions. 
408
409
410 The Call Function
411 -----------------
412
413 The RMR function ``rmr_call()`` sends a message in the exact 
414 same manner as the ``rmr_send_msg()()`` function, with the 
415 endpoint selection based on the message key. But unlike the 
416 send function, ``rmr_call()`` will block and wait for a 
417 response from the application that is selected to receive the 
418 message. The matching message is determined by the 
419 transaction ID which the application must place into the 
420 message buffer prior to invoking ``rmr_call()``. Similarly, 
421 the responding application must ensure that the same 
422 transaction ID is placed into the message buffer before 
423 returning its response. 
424  
425 The return from the call is a message buffer with the 
426 response message; there is no difference between a message 
427 buffer returned by the receive function and one returned by 
428 the ``rmr_call()`` function. If a response is not received in 
429 a reasonable amount of time, a nil message buffer is returned 
430 to the calling application. 
431
432
433 Returning a Response
434 --------------------
435
436 Because of the nature of RMR's routing policies, it is 
437 generally not possible for an application to control exactly 
438 which endpoint is sent a message. There are cases, such as 
439 responding to a message delivered via ``rmr_call()`` that the 
440 application must send a message and guarantee that RMR routes 
441 it to an exact destination. To enable this, RMR provides the 
442 ``rmr_rts_msg(),`` return to sender, function. Upon receipt 
443 of any message, an application may alter the payload, and if 
444 necessary the message type and subscription ID, and pass the 
445 altered message buffer to the ``rmr_rts_msg()`` function to 
446 return the altered message to the application which sent it. 
447 When this function is used, RMR will examine the message 
448 buffer for the source information and use that to select the 
449 connection on which to write the response. 
450
451
452 Multi-threaded Calls
453 --------------------
454
455 The basic call mechanism described above is **not** thread 
456 safe, as it is not possible to guarantee that a response 
457 message is delivered to the correct thread. The RMR function 
458 ``rmr_mt_call()`` accepts an additional parameter which 
459 identifies the calling thread in order to ensure that the 
460 response is delivered properly. In addition, the application 
461 must specifically initialise the multi-threaded call 
462 environment by passing the ``RMRFL_MTCALL`` flag as an option 
463 to the ``rmr_init()`` function. 
464  
465 One advantage of the multi-threaded call capability in RMR is 
466 the fact that only the calling thread is blocked. Messages 
467 received which are not responses to the call are continued to 
468 be delivered via normal ``rmr_rcv_msg()`` calls. 
469  
470 While the process is blocked waiting for the response, it is 
471 entirely possible that asynchronous, non-matching, messages 
472 will arrive. When this happens, RMR will queues the messages 
473 and return them to the application over the next calls to 
474 ``rmr_rcv_msg().`` 
475
476
477 Wormholes
478 ---------
479
480 As was mentioned earlier, the design of RMR is to eliminate 
481 the need for an application to know a specific endpoint, even 
482 when a response message is being sent. In some rare cases it 
483 may be necessary for an application to establish a direct 
484 connection to an RMR-based application rather than relying on 
485 message type and subscription ID based routing. The 
486 *wormhole* functions provide an application with the ability 
487 to create a direct connection and then to send and receive 
488 messages across the connection. The following are the RMR 
489 functions which provide wormhole communications: 
490  
491  
492     .. list-table:: 
493       :widths: auto 
494       :header-rows: 0 
495       :class: borderless 
496        
497       * - **rmr_wh_open** 
498         - 
499           Open a connection to an endpoint. Name or IP address and port 
500           of the endpoint is supplied. Returns a wormhole ID that the 
501           application must use when sending a direct message. 
502        
503       * - **rmr_wh_send_msg** 
504         - 
505           Sends an RMR message buffer to the connected application. The 
506           message type and subscription ID may be set in the message, 
507           but RMR will ignore both. 
508        
509       * - **rmr_wh_close** 
510         - 
511           Closes the direct connection. 
512            
513  
514  
515
516
517 Handling Failures
518 =================
519
520 The vast majority of states reported by RMR are fatal; if 
521 encountered during setup or initialization, then it is 
522 unlikely that any message oriented processing should 
523 continue, and when encountered on a message operation 
524 continued operation on that message should be abandoned. 
525 Specifically with regard to message sending, it is very 
526 likely that the underlying transport mechanism will report a 
527 *soft,* or transient, failure which might be successful if 
528 the operation is retried at a later point in time. The 
529 paragraphs below discuss the methods that an application 
530 might deal with these soft failures. 
531
532
533 Failure Notification
534 --------------------
535
536 When a soft failure is reported, the returned message buffer 
537 returned by the RMR function will be ``RMR_ERR_RETRY.`` These 
538 types of failures can occur for various reasons; one of two 
539 reasons is typically the underlying cause: 
540  
541  
542 * The session to the targeted recipient (endpoint) is not 
543   connected. 
544    
545 * The transport mechanism buffer pool is full and cannot 
546   accept another buffer. 
547    
548  
549  
550 Unfortunately, it is not possible for RMR to determine which 
551 of these two cases is occurring, and equally as unfortunate 
552 the time to resolve each is different. The first, no 
553 connection, may require up to a second before a message can 
554 be accepted, while a rejection because of buffer shortage is 
555 likely to resolve in less than a millisecond. 
556
557
558 Application Response
559 --------------------
560
561 The action which an application takes when a soft failure is 
562 reported ultimately depends on the nature of the application 
563 with respect to factors such as tolerance to extended message 
564 latency, dropped messages, and over all message rate. 
565
566
567 RMR Retry Modes
568 ---------------
569
570 In an effort to reduce the workload of an application 
571 developer, RMR has a default retry policy such that RMR will 
572 attempt to retransmit a message up to 1000 times when a soft 
573 failure is reported. These retries generally take less than 1 
574 millisecond (if all 1000 are attempted) and in most cases 
575 eliminates nearly all reported soft failures to the 
576 application. When using this mode, it might allow the 
577 application to simply treat all bad return values from a send 
578 attempt as permanent failures. 
579  
580 If an application is so sensitive to any delay in RMR, or the 
581 underlying transport mechanism, it is possible to set RMR to 
582 return a failure immediately on any kind of error (permanent 
583 failures are always reported without retry). In this mode, 
584 RMR will still set the state in the message buffer to 
585 ``RMR_ERR_RETRY,`` but will **not** make any attempts to 
586 resend the message. This zero-retry policy is enabled by 
587 invoking the ``rmr_set_stimeout()`` with a value of 0; this 
588 can be done once immediately after ``rmr_init()`` is invoked. 
589  
590 Regardless of the retry mode which the application sets, it 
591 will ultimately be up to the application to handle failures 
592 by queuing the message internally for resend, retrying 
593 immediately, or dropping the send attempt all together. As 
594 stated before, only the application can determine how to best 
595 handle send failures. 
596
597
598 Other Failures
599 --------------
600
601 RMR will return the state of processing for message based 
602 operations (send/receive) as the status in the message 
603 buffer. For non-message operations, state is returned to the 
604 caller as the integer return value for all functions which 
605 are not expected to return a pointer (e.g. 
606 ``rmr_init()``.) The following are the RMR state constants 
607 and a brief description of their meaning. 
608  
609  
610     .. list-table:: 
611       :widths: auto 
612       :header-rows: 0 
613       :class: borderless 
614        
615       * - **RMR_OK** 
616         - 
617           state is good; operation finished successfully 
618        
619       * - **RMR_ERR_BADARG** 
620         - 
621           argument passed to function was unusable 
622        
623       * - **RMR_ERR_NOENDPT** 
624         - 
625           send/call could not find an endpoint based on msg type 
626        
627       * - **RMR_ERR_EMPTY** 
628         - 
629           msg received had no payload; attempt to send an empty message 
630        
631       * - **RMR_ERR_NOHDR** 
632         - 
633           message didn't contain a valid header 
634        
635       * - **RMR_ERR_SENDFAILED** 
636         - 
637           send failed; errno may contain the transport provider reason 
638        
639       * - **RMR_ERR_CALLFAILED** 
640         - 
641           unable to send the message for a call function; errno may 
642           contain the transport provider reason 
643        
644       * - **RMR_ERR_NOWHOPEN** 
645         - 
646           no wormholes are open 
647        
648       * - **RMR_ERR_WHID** 
649         - 
650           the wormhole id provided was invalid 
651        
652       * - **RMR_ERR_OVERFLOW** 
653         - 
654           operation would have busted through a buffer/field size 
655        
656       * - **RMR_ERR_RETRY** 
657         - 
658           request (send/call/rts) failed, but caller should retry 
659           (EAGAIN for wrappers) 
660        
661       * - **RMR_ERR_RCVFAILED** 
662         - 
663           receive failed (hard error) 
664        
665       * - **RMR_ERR_TIMEOUT** 
666         - 
667           response message not received in a reasonable amount of time 
668        
669       * - **RMR_ERR_UNSET** 
670         - 
671           the message hasn't been populated with a transport buffer 
672        
673       * - **RMR_ERR_TRUNC** 
674         - 
675           length in the received buffer is longer than the size of the 
676           allocated payload, received message likely truncated (length 
677           set by sender could be wrong, but we can't know that) 
678        
679       * - **RMR_ERR_INITFAILED** 
680         - 
681           initialisation of something (probably message) failed 
682        
683       * - **RMR_ERR_NOTSUPP** 
684         - 
685           the request is not supported, or RMR was not initialised for 
686           the request 
687            
688  
689  
690 Depending on the underlying transport mechanism, and the 
691 nature of the call that RMR attempted, the system 
692 ``errno`` value might reflect additional detail about the 
693 failure. Applications should **not** rely on errno as some 
694 transport mechanisms do not set it with any consistency. 
695
696
697 Configuration and Control
698 =========================
699
700 With the assumption that most RMR based applications will be 
701 executed in a containerised environment, there are some 
702 underlying mechanics which the developer may need to know in 
703 order to properly provide a configuration specification to 
704 the container management system. The following paragraphs 
705 briefly discuss these. 
706  
707
708
709 TCP Ports
710 ---------
711
712 RMR requires two (2) TCP listen ports: one for general 
713 application-to-application communications and one for 
714 route-table updates. The general communication port is 
715 specified by the application at the time RMR is initialised. 
716 The port used to listen for route table updates is likely to 
717 be a constant port shared by all applications provided they 
718 are running in separate containers. To that end, the port 
719 number defaults to 4561, but can be configured with an 
720 environment variable (see later paragraph in this section). 
721
722
723 Host Names
724 ----------
725
726 RMR is typically host name agnostic. Route table entries may 
727 contain endpoints defined either by host name or IP address. 
728 In the container world the concept of a *service name* might 
729 exist, and likely is different than a host name. RMR's only 
730 requirement with respect to host names is that a name used on 
731 a route table entry must be resolvable via the 
732 ``gethostbyname`` system call. 
733
734
735 Environment Variables
736 ---------------------
737
738 Several environment variables are recognised by RMR which, in 
739 general, are used to define interfaces and listen ports (e.g. 
740 the route table update listen port), or debugging 
741 information. Generally this information is system controlled 
742 and thus RMR expects this information to be defined in the 
743 environment rather than provided by the application. The 
744 following is a list of the environment variables which RMR 
745 recognises: 
746  
747  
748     .. list-table:: 
749       :widths: auto 
750       :header-rows: 0 
751       :class: borderless 
752        
753       * - **RMR_BIND_IF** 
754         - 
755           The interface to bind to listen ports to. If not defined 
756           0.0.0.0 (all interfaces) is assumed. 
757        
758       * - **RMR_RTG_SVC** 
759         - 
760           The port RMR will listen on for route manager connections. If 
761           not defined 4561 is used. 
762        
763       * - **RMR_SEED_RT** 
764         - 
765           Where RMR expects to find the name of the seed (static) route 
766           table. If not defined no static table is read. 
767        
768       * - **RMR_RTG_ISRAW** 
769         - 
770           If the value set to 0, RMR expects the route table manager 
771           messages to be messages with and RMR header. If this is not 
772           defined messages are assumed to be "raw" (without an RMR 
773           header. 
774        
775       * - **RMR_VCTL_FILE** 
776         - 
777           Provides a file which is used to set the verbose level of the 
778           route table collection thread. The first line of the file is 
779           read and expected to contain an integer value to set the 
780           verbose level. The value may be changed at any time and the 
781           route table thread will adjust accordingly. 
782        
783       * - **RMR_SRC_NAMEONLY** 
784         - 
785           If the value of this variable is greater than 0, RMR will not 
786           permit the IP address to be sent as the message source. Only 
787           the host name will be sent as the source in the message 
788           header. 
789            
790  
791  
792
793
794 Logging
795 -------
796
797 RMR does **not** use any logging libraries; any error or 
798 warning messages are written to standard error. RMR messages 
799 are written with one of three prefix strings: 
800  
801  
802     .. list-table:: 
803       :widths: auto 
804       :header-rows: 0 
805       :class: borderless 
806        
807       * - **[CRI]** 
808         - 
809           The event is of a critical nature and it is unlikely that RMR 
810           will continue to operate correctly if at all. It is almost 
811           certain that immediate action will be needed to resolve the 
812           issue. 
813        
814       * - **[ERR]** 
815         - 
816           The event is not expected and RMR is not able to handle it. 
817           There is a small chance that continued operation will be 
818           negatively impacted. Eventual action to diagnose and correct 
819           the issue will be necessary. 
820        
821       * - **[WRN]** 
822         - 
823           The event was not expected by RMR, but can be worked round. 
824           Normal operation will continue, but it is recommended that 
825           the cause of the problem be investigated. 
826            
827  
828  
829
830
831 Notes
832 =====
833
834  
835  [1] It is entirely possible to design a routing table, and 
836  application group, such that the same message type is is 
837  left unchanged and the message is forwarded by an 
838  application after updating the payload. This type of 
839  behaviour is often referred to as service chaining, and can 
840  be done without any "knowledge" by an application with 
841  respect to where the message goes next. Service chaining is 
842  supported by RMR in as much as it allows the message to be 
843  resent, but the actual complexities of designing and 
844  implementing service chaining lie with the route table 
845  generator process. 
846  
847  
848  
849  
850
851
852 Appendix A -- Quick Reference
853 =============================
854
855 Please  refer  to  the RMR manual pages on the Read the Docs 
856 site 
857  
858 https://docs.o-ran-sc.org/projects/o-ran-sc-ric-plt-lib-rmr/en/latest/index.html 
859  
860
861
862 Appendix B -- Message Buffer Details
863 ====================================
864
865 The RMR message buffer is a C structure which is exposed  in 
866 the  ``rmr.h``  header  file. It is used to manage a message 
867 received from a peer endpoint, or a message  that  is  being 
868 sent  to  a  peer.  Fields include payload length, amount of 
869 payload actually  used,  status,  and  a  reference  to  the 
870 payload.  There are also fields which the application should 
871 ignore, and could be hidden in the header file, but we chose 
872 not  to.  These fields include a reference to the RMR header 
873 information,  and  to  the  underlying  transport  mechanism 
874 message  struct  which may or may not be the same as the RMR 
875 header reference. 
876
877
878 The Structure
879 -------------
880
881 The following is the C structure. Readers are  cautioned  to 
882 examine  the ``rmr.h`` header file directly; the information 
883 here may be out of date (old document in  some  cache),  and 
884 thus it may be incorrect. 
885  
886  
887 :: 
888  
889    
890   typedef struct {
891       int    state;            // state of processing
892       int    mtype;            // message type
893       int    len;              // length of data in the payload (send or received)
894       unsigned char* payload;  // transported data
895       unsigned char* xaction;  // pointer to fixed length transaction id bytes
896       int    sub_id;           // subscription id
897       int    tp_state;         // transport state (errno)
898    
899                                // these things are off limits to the user application
900       void*    tp_buf;         // underlying transport allocated pointer (e.g. nng message)
901       void*    header;         // internal message header (whole buffer: header+payload)
902       unsigned char* id;       // if we need an ID in the message separate from the xaction id
903       int      flags;          // various MFL_ (private) flags as needed
904       int      alloc_len;      // the length of the allocated space (hdr+payload)
905       void*    ring;           // ring this buffer should be queued back to
906       int      rts_fd;         // SI fd for return to sender
907       int      cookie;         // cookie to detect user misuse of free'd msg
908   } rmr_mbuf_t;
909  
910  
911
912
913 State vs Transport State
914 ------------------------
915
916 The  state  field reflects the state at the time the message 
917 buffer is returned to the calling application.  For  a  send 
918 operation,  if  the state is not ``RMR_OK`` then the message 
919 buffer references the payload that could not  be  sent,  and 
920 when the state is ``RMR_OK`` the buffer references a *fresh* 
921 payload that the application may fill in. 
922  
923 When the state is not ``RMR_OK,`` C programmes  may  examine 
924 the  global ``errno`` value which RMR will have left set, if 
925 it was set, by the underlying transport mechanism.  In  some 
926 cases,  wrapper  modules are not able to directly access the 
927 C-library ``errno``  value,  and  to  assist  with  possible 
928 transport  error  details,  the  send and receive operations 
929 populate ``tp_state`` with the value of ``errno.`` 
930  
931 Regardless of whether  the  application  makes  use  of  the 
932 ``tp_state,`` or the ``errno`` value, it should be noted that 
933 the underlying transport mechanism may not  actually  update 
934 the errno value; in other words: it might not be accurate. In 
935 addition, RMR populates the ``tp_state`` value in the message 
936 buffer **only** when the state is not ``RMR_OK.`` 
937
938
939 Field References
940 ----------------
941
942 The  transaction  field  was exposed in the first version of 
943 RMR, and in hindsight this shouldn't have been done.  Rather 
944 than  break  any  existing  code the reference was left, but 
945 additional fields such as  trace  data,  were  not  directly 
946 exposed  to  the  application.  The application developer is 
947 strongly encouraged to use the functions which get  and  set 
948 the  transaction  ID rather than using the pointer directly; 
949 any data overruns will not be detected if the  reference  is 
950 used directly. 
951  
952 In contrast, the payload reference should be used directly by 
953 the application  in  the  interest  of  speed  and  ease  of 
954 programming.  The same care to prevent writing more bytes to 
955 the payload buffer than it can hold must  be  taken  by  the 
956 application.  By the nature of the allocation of the payload 
957 in transport space, RMR is unable to add guard bytes  and/or 
958 test for data overrun. 
959
960
961 Actual Transmission
962 -------------------
963
964 When RMR sends the application's message, the message buffer 
965 is **not** transmitted. The transport buffer (tp_buf)  which 
966 contains  the RMR header and application payload is the only 
967 set of bytes which are transmitted. While it may seem to the 
968 caller  like  the function ``rmr_send_msg()`` is returning a 
969 new message buffer, the same struct is reused and only a new 
970 transport  buffer  is  allocated.  The intent is to keep the 
971 alloc/free cycles to a minimum. 
972  
973
974
975 Appendix C -- Glossary
976 ======================
977
978 Many terms in networking can be  interpreted  with  multiple 
979 meanings, and several terms used in various RMR documentation 
980 are RMR specific. The following definitions are the meanings 
981 of  terms  used within RMR documentation and should help the 
982 reader to understand the intent of meaning. 
983  
984     .. list-table:: 
985       :widths: 25,70 
986       :header-rows: 0 
987       :class: borderless 
988        
989       * - **application** 
990         - 
991           A programme which uses RMR to send and/or  receive  messages 
992           to/from another RMR based application. 
993        
994       * - **Critical error** 
995         - 
996           An error that RMR has encountered which will prevent further 
997           successful  processing  by  RMR.  Critical  errors  usually  
998           indicate that the application should abort. 
999        
1000       * - **Endpoint** 
1001         - 
1002           An RMR based application that is defined as being capable of 
1003           receiving one or more types of messages  (as  defined  by  a 
1004           *routing key.*) 
1005        
1006       * - **Environment variable** 
1007         - 
1008           A key/value pair which is set externally to the application, 
1009           but which is available to the  application  (and  referenced 
1010           libraries)  through  the ``getenv`` system call. Environment 
1011           variables are the main method of  communicating  information 
1012           such as port numbers to RMR. 
1013        
1014       * - **Error** 
1015         - 
1016           An abnormal condition that RMR has encountered, but will not 
1017           affect the overall processing by RMR, but may impact certain 
1018           aspects  such  as the ability to communicate with a specific 
1019           endpoint. Errors generally indicate that something,  usually 
1020           external to RMR, must be addressed. 
1021        
1022       * - **Host name** 
1023         - 
1024           The  name  of  the host as returned by the ``gethostbyname`` 
1025           system call. In a containerised environment this might be the 
1026           container  or service name depending on how the container is 
1027           started. From RMR's point of view, a host name can be used to 
1028           resolve an *endpoint* definition in a *route* table.) 
1029        
1030       * - **IP** 
1031         - 
1032           Internet  protocol.  A low level transmission protocol which 
1033           governs   the  transmission  of  datagrams  across  network  
1034           boundaries. 
1035        
1036       * - **Listen socket** 
1037         - 
1038           A  *TCP*  socket used to await incoming connection requests. 
1039           Listen sockets are defined by an interface and  port  number 
1040           combination  where  the  port  number  is  unique  for  the  
1041           interface. 
1042        
1043       * - **Message** 
1044         - 
1045           A series of bytes transmitted from the application to another 
1046           RMR based application. A message is comprised of RMR specific 
1047           data (a header), and application data (a payload). 
1048        
1049       * - **Message buffer** 
1050         - 
1051           A data structure used to describe a message which is  to  be 
1052           sent  or  has been received. The message buffer includes the 
1053           payload length, message  type,  message  source,  and  other 
1054           information. 
1055        
1056       * - **Message type** 
1057         - 
1058           A  signed  integer  (0-32000)  which  identifies the type of 
1059           message being transmitted, and is one of the two  components 
1060           of a *routing key.* See *Subscription ID.* 
1061        
1062       * - **Payload** 
1063         - 
1064           The  portion  of  a  message which holds the user data to be 
1065           transmitted to the remote *endpoint.* The  payload  contents 
1066           are completely application defined. 
1067        
1068       * - **RMR context** 
1069         - 
1070           A  set of information which defines the current state of the 
1071           underlying transport connections that RMR is  managing.  The 
1072           application  will be give a context reference (pointer) that 
1073           is supplied to most RMR functions as the first parameter. 
1074        
1075       * - **Round robin** 
1076         - 
1077           The method of selecting an *endpoint* from a list such  that 
1078           all  *endpoints* are selected before starting at the head of 
1079           the list. 
1080        
1081       * - **Route table** 
1082         - 
1083           A series of "rules" which define the possible *endpoints* for 
1084           each *routing key.* 
1085        
1086       * - **Route table manager** 
1087         - 
1088           An  application responsible for building a *route table* and 
1089           then   distributing   it   to   all  applicable  RMR  based  
1090           applications. 
1091        
1092       * - **Routing** 
1093         - 
1094           The  process  of  selecting  an *endpoint* which will be the 
1095           recipient of a message. 
1096        
1097       * - **Routing key** 
1098         - 
1099           A combination of *message type* and *subscription ID*  which 
1100           RMR uses to select the destination *endpoint* when sending a 
1101           message. 
1102        
1103       * - **Source** 
1104         - 
1105           The sender of a message. 
1106        
1107       * - **Subscription ID** 
1108         - 
1109           A  signed  integer  value  (0-32000)  which  identifies  the 
1110           subscription  characteristic  of  a  message.  It is used in 
1111           conjunction with the *message type* to determine the *routing 
1112           key.* 
1113        
1114       * - **Target** 
1115         - 
1116           The *endpoint* selected to receive a message. 
1117        
1118       * - **TCP** 
1119         - 
1120           Transmission  Control  Protocol. A connection based internet 
1121           protocol which provides for lossless packet  transportation, 
1122           usually over IP. 
1123        
1124       * - **Thread** 
1125         - 
1126           Also  called  a  *process  thread,  or  pthread.*  This is a 
1127           lightweight process which executes in concurrently with  the 
1128           application  and  shares  the  same  address space. RMR uses 
1129           threads to manage asynchronous functions such as route table 
1130           updates. 
1131        
1132       * - **Trace information** 
1133         - 
1134           An   optional  portion  of  the  message  buffer  that  the  
1135           application may populate with data that allows  for  tracing 
1136           the  progress  of  the  transaction  or application activity 
1137           across components. RMR makes no use of this data. 
1138        
1139       * - **Transaction ID** 
1140         - 
1141           A fixed number of bytes in the *message* buffer)  which  the 
1142           application  may  populate  with  information related to the 
1143           transaction. RMR makes use of the transaction ID for matching 
1144           response  messages  with  the  &c function is used to send a 
1145           message. 
1146        
1147       * - **Transient failure** 
1148         - 
1149           An error state that is believed to be short lived  and  that 
1150           the  operation,  if  retried  by  the  application, might be 
1151           successful.   C   programmers   will   recognise   this  as  
1152           ``EAGAIN.`` 
1153        
1154       * - **Warning** 
1155         - 
1156           A  warning occurs when RMR has encountered something that it 
1157           believes isn't correct, but has a defined work round. 
1158        
1159       * - **Wormhole** 
1160         - 
1161           A  direct  connection  managed  by  RMR  between  the  user  
1162           application and a remote, RMR based, application. 
1163            
1164  
1165  
1166
1167
1168 Appendix D -- Code Examples
1169 ===========================
1170
1171 The  following  snippet of code illustrate some of the basic 
1172 operation of the RMR library. Please refer to  the  examples 
1173 and  test directories in the RMR repository for complete RMR 
1174 based programmes. 
1175
1176
1177 Sender Sample
1178 -------------
1179
1180 The following code segment shows how a message buffer can be 
1181 allocated, populated, and sent. The snippet also illustrates 
1182 how the result from the ``rmr_send_msg()`` function is  used 
1183 to send the next message. It does not illustrate error and/or 
1184 retry handling. 
1185  
1186  
1187 :: 
1188  
1189    
1190   #include <unistd.h>
1191   #include <errno.h>
1192   #include <string.h>
1193   #include <stdio.h>
1194   #include <stdlib.h>
1195   #include <sys/epoll.h>
1196   #include <time.h>
1197    
1198   #include <rmr/rmr.h>
1199    
1200   int main( int argc, char** argv ) {
1201       void* mrc;                            // msg router context
1202       struct epoll_event events[1];        // list of events to give to epoll
1203       struct epoll_event epe;                // event definition for event to listen to
1204       int     ep_fd = -1;                    // epoll's file des (given to epoll_wait)
1205       int rcv_fd;                            // file des for epoll checks
1206       int nready;                            // number of events ready for receive
1207       rmr_mbuf_t*        sbuf;                // send buffer
1208       rmr_mbuf_t*        rbuf;                // received buffer
1209       int    count = 0;
1210       int    rcvd_count = 0;
1211       char*    listen_port = "43086";
1212       int        delay = 1000000;            // mu-sec delay between messages
1213       int        mtype = 0;
1214       int        stats_freq = 100;
1215    
1216       if( argc > 1 ) {                    // simplistic arg picking
1217           listen_port = argv[1];
1218       }
1219       if( argc > 2 ) {
1220           delay = atoi( argv[2] );
1221       }
1222       if( argc > 3 ) {
1223           mtype = atoi( argv[3] );
1224       }
1225    
1226       fprintf( stderr, "<DEMO> listen port: %s; mtype: %d; delay: %d\\n",
1227           listen_port, mtype, delay );
1228    
1229       if( (mrc = rmr_init( listen_port, 1400, RMRFL_NONE )) == NULL ) {
1230           fprintf( stderr, "<DEMO> unable to initialise RMR\\n" );
1231           exit( 1 );
1232       }
1233    
1234       rcv_fd = rmr_get_rcvfd( mrc );  // set up epoll things, start by getting the FD from RMR
1235       if( rcv_fd < 0 ) {
1236           fprintf( stderr, "<DEMO> unable to set up polling fd\\n" );
1237           exit( 1 );
1238       }
1239       if( (ep_fd = epoll_create1( 0 )) < 0 ) {
1240           fprintf( stderr, "[FAIL] unable to create epoll fd: %d\\n", errno );
1241           exit( 1 );
1242       }
1243       epe.events = EPOLLIN;
1244       epe.data.fd = rcv_fd;
1245    
1246       if( epoll_ctl( ep_fd, EPOLL_CTL_ADD, rcv_fd, &epe ) != 0 )  {
1247           fprintf( stderr, "[FAIL] epoll_ctl status not 0 : %s\\n", strerror( errno ) );
1248           exit( 1 );
1249       }
1250    
1251       sbuf = rmr_alloc_msg( mrc, 256 );    // alloc 1st send buf; subsequent bufs alloc on send
1252       rbuf = NULL;                        // don't need to alloc receive buffer
1253    
1254       while( ! rmr_ready( mrc ) ) {        // must have route table
1255           sleep( 1 );                        // wait til we get one
1256       }
1257       fprintf( stderr, "<DEMO> rmr is ready\\n" );
1258    
1259    
1260       while( 1 ) {            // send messages until the cows come home
1261           snprintf( sbuf->payload, 200,
1262               "count=%d received= %d ts=%lld %d stand up and cheer!",    // create the payload
1263               count, rcvd_count, (long long) time( NULL ), rand() );
1264    
1265           sbuf->mtype = mtype;                            // fill in the message bits
1266           sbuf->len =  strlen( sbuf->payload ) + 1;        // send full ascii-z string
1267           sbuf->state = 0;
1268           sbuf = rmr_send_msg( mrc, sbuf );                // send & get next buf to fill in
1269           while( sbuf->state == RMR_ERR_RETRY ) {            // soft failure (device busy?) retry
1270               sbuf = rmr_send_msg( mrc, sbuf );            // w/ simple spin that doesn't give up
1271           }
1272           count++;
1273    
1274           // check to see if anything was received and pull all messages in
1275           while( (nready = epoll_wait( ep_fd, events, 1, 0 )) > 0 ) { // 0 is non-blocking
1276               if( events[0].data.fd == rcv_fd ) {     // waiting on 1 thing, so [0] is ok
1277                   errno = 0;
1278                   rbuf = rmr_rcv_msg( mrc, rbuf );    // receive and ignore; just count
1279                   if( rbuf ) {
1280                       rcvd_count++;
1281                   }
1282               }
1283           }
1284    
1285           if( (count % stats_freq) == 0 ) {            // occasional stats out to tty
1286               fprintf( stderr, "<DEMO> sent %d   received %d\\n", count, rcvd_count );
1287           }
1288    
1289           usleep( delay );
1290       }
1291   }
1292    
1293  
1294
1295
1296 Receiver Sample
1297 ---------------
1298
1299 The receiver code is even simpler than the sender code as it 
1300 does  not  need  to  wait  for a route table to arrive (only 
1301 senders need to do that), nor does it need  to  allocate  an 
1302 initial  buffer.  The  example  assumes  that  the sender is 
1303 transmitting a zero terminated string as the payload. 
1304  
1305  
1306 :: 
1307  
1308    
1309   #include <unistd.h>
1310   #include <errno.h>
1311   #include <stdio.h>
1312   #include <stdlib.h>
1313   #include <time.h>
1314    
1315   #include <rmr/rmr.h>
1316    
1317    
1318   int main( int argc, char** argv ) {
1319       void* mrc;                     // msg router context
1320       long long total = 0;
1321       rmr_mbuf_t* msg = NULL;        // message received
1322       int stat_freq = 10;            // write stats after reciving this many messages
1323       int i;
1324       char*    listen_port = "4560"; // default to what has become the standard RMR port
1325       long long count = 0;
1326       long long bad = 0;
1327       long long empty = 0;
1328    
1329       if( argc > 1 ) {
1330           listen_port = argv[1];
1331       }
1332       if( argc > 2 ) {
1333           stat_freq = atoi( argv[2] );
1334       }
1335       fprintf( stderr, "<DEMO> listening on port: %s\\n", listen_port );
1336       fprintf( stderr, "<DEMO> stats will be reported every %d messages\\n", stat_freq );
1337    
1338       mrc = rmr_init( listen_port, RMR_MAX_RCV_BYTES, RMRFL_NONE );
1339       if( mrc == NULL ) {
1340           fprintf( stderr, "<DEMO> ABORT:  unable to initialise RMr\\n" );
1341           exit( 1 );
1342       }
1343    
1344       while( ! rmr_ready( mrc ) ) {    // wait for RMR to get a route table
1345           fprintf( stderr, "<DEMO> waiting for ready\\n" );
1346           sleep( 3 );
1347       }
1348       fprintf( stderr, "<DEMO> rmr now shows ready\\n" );
1349    
1350       while( 1 ) {                              // receive until killed
1351           msg = rmr_rcv_msg( mrc, msg );        // block until one arrives
1352    
1353           if( msg ) {
1354               if( msg->state == RMR_OK ) {
1355                   count++;                      // nothing fancy, just count
1356               } else {
1357                   bad++;
1358               }
1359           } else {
1360               empty++;
1361           }
1362    
1363           if( (count % stat_freq) == 0  ) {
1364               fprintf( stderr, "<DEMO> total received: %lld; errors: %lld; empty: %lld\\n",
1365                   count, bad, empty );
1366           }
1367       }
1368   }
1369    
1370  
1371
1372
1373 Receive and Send Sample
1374 -----------------------
1375
1376 The following code snippet receives messages and responds to 
1377 the  sender if the message type is odd. The code illustrates 
1378 how the received message may be used to return a message  to 
1379 the source. Variable type definitions are omitted for clarity 
1380 and should be obvious. 
1381  
1382 It should also be noted that things like  the  message  type 
1383 which  id returned to the sender (99) is a random value that 
1384 these applications would have agreed on in  advance  and  is 
1385 **not** an RMR definition. 
1386  
1387  
1388 :: 
1389  
1390   mrc = rmr_init( listen_port, MAX_BUF_SZ, RMRFL_NOFLAGS );
1391   rmr_set_stimeout( mrc, 1 );        // allow RMR to retry failed sends for ~1ms
1392    
1393   while( ! rmr_ready( mrc ) ) {        // we send, therefore we need a route table
1394       sleep( 1 );
1395   }
1396    
1397   mbuf = NULL;                        // ensure our buffer pointer is nil for 1st call
1398    
1399   while( TRUE ) {
1400       mbuf = rmr_rcv_msg( mrc, mbuf );        // wait for message
1401    
1402       if( mbuf == NULL || mbuf->state != RMR_OK ) {
1403           break;
1404       }
1405    
1406       if( mbuf->mtype % 2 ) {                // respond to odd message types
1407           plen = rmr_payload_size( mbuf );        // max size
1408    
1409                                                   // reset necessary fields in msg
1410           mbuf->mtype = 99;                       // response type
1411           mbuf->sub_id = RMR_VOID_SUBID;          // we turn subid off
1412           mbuf->len = snprintf( mbuf->payload, plen, "pong: %s", get_info() );
1413    
1414           mbuf = rmr_rts_msg( mrc, mbuf );        // return to sender
1415           if( mbuf == NULL || mbuf->state != RMR_OK ) {
1416               fprintf( stderr, "return to sender failed\\n" );
1417           }
1418       }
1419   }
1420    
1421   fprintf( stderr, "abort: receive failure\\n" );
1422   rmr_close( mrc );
1423    
1424  
1425