Raise an exception on bad buffer allocations
[ric-plt/lib/rmr.git] / src / bindings / rmr-python / rmr / rmr.py
index b666299..85c9ee8 100644 (file)
@@ -19,6 +19,7 @@ import json
 from ctypes import RTLD_GLOBAL, Structure, c_int, POINTER, c_char, c_char_p, c_void_p, memmove, cast
 from ctypes import CDLL
 from ctypes import create_string_buffer
+from rmr.exceptions import BadBufferAllocation
 
 # https://docs.python.org/3.7/library/ctypes.html
 # https://stackoverflow.com/questions/2327344/ctypes-loading-a-c-shared-library-that-has-dependencies/30845750#30845750
@@ -69,7 +70,7 @@ def _get_mapping_dict(cache={}):
     RMR_ERR_TIMEOUT     12  message processing call timed out
     RMR_ERR_UNSET       13  the message hasn't been populated with a transport buffer
     RMR_ERR_TRUNC       14  received message likely truncated
-    RMR_ERR_INITFAILED  15  initialisation of something (probably message) failed
+    RMR_ERR_INITFAILED  15  initialization of something (probably message) failed
 
     """
     if cache:
@@ -93,6 +94,9 @@ def _state_to_status(stateno):
     return sdict.get(stateno, "UNKNOWN STATE")
 
 
+_RCONST = _get_constants()
+
+
 ##############
 # PUBLIC API
 ##############
@@ -100,7 +104,13 @@ def _state_to_status(stateno):
 
 # These constants are directly usable by importers of this library
 # TODO: Are there others that will be useful?
-RMR_MAX_RCV_BYTES = _get_constants()["RMR_MAX_RCV_BYTES"]
+
+RMR_MAX_RCV_BYTES = _RCONST["RMR_MAX_RCV_BYTES"]
+RMRFL_MTCALL = _RCONST.get("RMRFL_MTCALL", 0x02)  # initialization flags
+RMRFL_NONE = _RCONST.get("RMRFL_NONE", 0x0)
+RMR_OK = _RCONST["RMR_OK"]  # useful state constants
+RMR_ERR_TIMEOUT = _RCONST["RMR_ERR_TIMEOUT"]
+RMR_ERR_RETRY = _RCONST["RMR_ERR_RETRY"]
 
 
 class rmr_mbuf_t(Structure):
@@ -210,7 +220,26 @@ def rmr_alloc_msg(vctx, size):
     Refer to the rmr C documentation for rmr_alloc_msg
     extern rmr_mbuf_t* rmr_alloc_msg(void* vctx, int size)
     """
-    return _rmr_alloc_msg(vctx, size)
+    sbuf = _rmr_alloc_msg(vctx, size)
+    try:
+        sbuf.contents
+    except ValueError:
+        raise BadBufferAllocation
+    return sbuf
+
+
+_rmr_free_msg = rmr_c_lib.rmr_free_msg
+_rmr_free_msg.argtypes = [c_void_p]
+_rmr_free_msg.restype = None
+
+
+def rmr_free_msg(mbuf):
+    """
+    Refer to the rmr C documentation for rmr_free_msg
+    extern void rmr_free_msg( rmr_mbuf_t* mbuf )
+    """
+    if mbuf is not None:
+        _rmr_free_msg(mbuf)
 
 
 _rmr_payload_size = rmr_c_lib.rmr_payload_size
@@ -414,11 +443,8 @@ def message_summary(ptr_mbuf):
     dict:
         dict message summary
     """
-    if ptr_mbuf.contents.len > RMR_MAX_RCV_BYTES:
-        return "Malformed message: message length is greater than the maximum possible"
-
     return {
-        "payload": get_payload(ptr_mbuf),
+        "payload": get_payload(ptr_mbuf) if ptr_mbuf.contents.state == RMR_OK else None,
         "payload length": ptr_mbuf.contents.len,
         "message type": ptr_mbuf.contents.mtype,
         "subscription id": ptr_mbuf.contents.sub_id,