339526af3de9980eceba4c5ba9e5485f2b4e7e70
[ric-plt/xapp-frame-py.git] / ricxappframe / rmr / helpers.py
1 # vim: ts=4 sw=4 expandtab:
2 # ==================================================================================
3 #       Copyright (c) 2019 Nokia
4 #       Copyright (c) 2018-2019 AT&T Intellectual Property.
5 #
6 #   Licensed under the Apache License, Version 2.0 (the "License");
7 #   you may not use this file except in compliance with the License.
8 #   You may obtain a copy of the License at
9 #
10 #          http://www.apache.org/licenses/LICENSE-2.0
11 #
12 #   Unless required by applicable law or agreed to in writing, software
13 #   distributed under the License is distributed on an "AS IS" BASIS,
14 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 #   See the License for the specific language governing permissions and
16 #   limitations under the License.
17 # ==================================================================================
18
19 #   Mnemonic:   helpers.py
20 #   Abstract:   This is a collection of extensions to the RMR base package
21 #               which are likely to be convenient for Python programs.
22 #   Date:       26 September 2019
23 # ---------------------------------------------------------------------------
24
25 from ricxappframe.rmr import rmr
26
27
28 def rmr_rcvall_msgs(mrc, pass_filter=[], timeout=0):
29     """
30     Assembles an array of all messages which can be received without blocking
31     (but see the timeout parameter).  Effectively drains the message queue if
32     RMR is started in mt-call mode, or draining any waiting TCP buffers.  If
33     the pass_filter parameter is supplied, it is treated as one or more
34     message types to accept (pass through). Using the default, an empty list,
35     results in capturing all messages. if the timeout parameter is supplied,
36     this call may block up to that number of milliseconds waiting for a
37     message to arrive. Using the default, zero, results in non-blocking
38     no-wait behavior.
39
40     Parameters
41     ----------
42         mrc: ctypes c_void_p
43             Pointer to the RMR context
44
45         pass_filter: list (optional)
46             The message type(s) to capture.
47
48         timeout: int (optional)
49             The number of milliseconds to wait for a message to arrive.
50
51     Returns
52     -------
53         List of message summaries (dict), one for each message received; may be empty.
54     """
55
56     new_messages = []
57     mbuf = rmr.rmr_alloc_msg(mrc, 4096)  # allocate and reuse a single buffer for RMR
58
59     while True:
60         mbuf = rmr.rmr_torcv_msg(mrc, mbuf, timeout)  # first call may have non-zero timeout
61         timeout = 0  # reset so subsequent calls do not wait
62         summary = rmr.message_summary(mbuf)
63         if summary["message status"] != "RMR_OK":  # ok indicates msg received, stop on all other states; e.g., RMR_ERR_TIMEOUT
64             break
65
66         if len(pass_filter) == 0 or summary["message type"] in pass_filter:  # no filter, or passes; capture it
67             new_messages.append(summary)
68
69     rmr.rmr_free_msg(mbuf)  # free the single buffer to avoid leak
70     return new_messages
71
72
73 def rmr_rcvall_msgs_raw(mrc, pass_filter=[], timeout=0):
74     """
75     Same as rmr_rcvall_msgs, but answers tuples with the raw sbuf.
76     Useful if return-to-sender (rts) functions are required.
77
78     Parameters
79     ----------
80         mrc: ctypes c_void_p
81             Pointer to the RMR context
82
83         pass_filter: list (optional)
84             The message type(s) to capture.
85
86         timeout: int (optional)
87             The number of milliseconds to wait for a message to arrive.
88
89     Returns
90     -------
91     list of tuple:
92         List of tuples [(S, sbuf),...] where S is a message summary (dict), and sbuf is the raw message; may be empty.
93         The caller MUST call rmr.rmr_free_msg(sbuf) when finished with each sbuf to prevent memory leaks!
94     """
95
96     new_messages = []
97
98     while True:
99         mbuf = rmr.rmr_alloc_msg(mrc, 4096)  # allocate a new buffer for every message
100         mbuf = rmr.rmr_torcv_msg(mrc, mbuf, timeout)  # first call may have non-zero timeout
101         timeout = 0  # reset so subsequent calls do not wait
102         summary = rmr.message_summary(mbuf)
103         if summary["message status"] != "RMR_OK":  # e.g., RMR_ERR_TIMEOUT
104             rmr.rmr_free_msg(mbuf)  # free the failed-to-receive buffer
105             break
106
107         if len(pass_filter) == 0 or mbuf.contents.mtype in pass_filter:  # no filter, or passes; capture it
108             new_messages.append((summary, mbuf))  # caller is responsible for freeing the buffer
109         else:
110             rmr.rmr_free_msg(mbuf)  # free the filtered-out message buffer
111
112     return new_messages