blob: e29a5ded7542503b9f5cded309df92b3fc8e5491 [file] [log] [blame]
Tommy Carpenter3a6ac012020-04-06 14:42:57 -04001# ==================================================================================
2# Copyright (c) 2019-2020 Nokia
3# Copyright (c) 2018-2020 AT&T Intellectual Property.
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16# ==================================================================================
17import uuid
Lott, Christopher (cl778h)db26ba22020-04-09 18:25:19 -040018from ctypes import POINTER, Structure
19from ctypes import c_int, c_char, c_char_p, c_void_p, memmove, cast, create_string_buffer
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -040020
Tommy Carpenter3a6ac012020-04-06 14:42:57 -040021from ricxappframe.rmr.exceptions import BadBufferAllocation, MeidSizeOutOfRange, InitFailed
Lott, Christopher (cl778h)db26ba22020-04-09 18:25:19 -040022from ricxappframe.rmr.rmrclib.rmrclib import rmr_c_lib, get_constants, state_to_status
Tommy Carpenter3a6ac012020-04-06 14:42:57 -040023
Lott, Christopher (cl778h)db26ba22020-04-09 18:25:19 -040024##############
25# PRIVATE API
26##############
Tommy Carpenter3a6ac012020-04-06 14:42:57 -040027
28
Lott, Christopher (cl778h)db26ba22020-04-09 18:25:19 -040029def _get_rmr_constant(key: str, default=None):
Tommy Carpenter3a6ac012020-04-06 14:42:57 -040030 """
Lott, Christopher (cl778h)db26ba22020-04-09 18:25:19 -040031 Gets the constant with the named key from the RMR C library.
32 Returns None if the value is not a simple type. This happens
33 during sphinx autodoc document generation, which mocks the
34 rmrclib package to work without the RMR shared object file,
35 and the response is something like this:
36 <class 'ricxappframe.rmr.rmrclib.rmrclib.get_constants.get'>
Tommy Carpenter3a6ac012020-04-06 14:42:57 -040037 """
Lott, Christopher (cl778h)db26ba22020-04-09 18:25:19 -040038 val = get_constants().get(key, default)
39 return val if isinstance(val, (type(None), bool, bytes, float, int, str)) else None
Tommy Carpenter3a6ac012020-04-06 14:42:57 -040040
41
42##############
43# PUBLIC API
44##############
45
Lott, Christopher (cl778h)db26ba22020-04-09 18:25:19 -040046# Publish constants from RMR C-language header files for use by importers of this library.
Tommy Carpenter3a6ac012020-04-06 14:42:57 -040047# TODO: Are there others that will be useful?
Lott, Christopher (cl778h)db26ba22020-04-09 18:25:19 -040048#: Typical size message to receive; size is not limited
49RMR_MAX_RCV_BYTES = _get_rmr_constant('RMR_MAX_RCV_BYTES')
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -040050#: Multi-threaded initialization flag
Lott, Christopher (cl778h)db26ba22020-04-09 18:25:19 -040051RMRFL_MTCALL = _get_rmr_constant('RMRFL_MTCALL', 0x02) # initialization flags
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -040052#: Empty flag
Lott, Christopher (cl778h)db26ba22020-04-09 18:25:19 -040053RMRFL_NONE = _get_rmr_constant('RMRFL_NONE', 0x0)
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -040054#: State constant for OK
Lott, Christopher (cl778h)db26ba22020-04-09 18:25:19 -040055RMR_OK = _get_rmr_constant('RMR_OK', 0x00)
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -040056#: State constant for timeout
Lott, Christopher (cl778h)db26ba22020-04-09 18:25:19 -040057RMR_ERR_TIMEOUT = _get_rmr_constant('RMR_ERR_TIMEOUT')
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -040058#: State constant for retry
Lott, Christopher (cl778h)db26ba22020-04-09 18:25:19 -040059RMR_ERR_RETRY = _get_rmr_constant('RMR_ERR_RETRY')
Tommy Carpenter3a6ac012020-04-06 14:42:57 -040060
61
62class rmr_mbuf_t(Structure):
63 """
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -040064 Mirrors public members of type rmr_mbuf_t from RMR header file src/common/include/rmr.h
Tommy Carpenter3a6ac012020-04-06 14:42:57 -040065
66 | typedef struct {
67 | int state; // state of processing
68 | int mtype; // message type
69 | int len; // length of data in the payload (send or received)
70 | unsigned char* payload; // transported data
71 | unsigned char* xaction; // pointer to fixed length transaction id bytes
72 | int sub_id; // subscription id
73 | int tp_state; // transport state (a.k.a errno)
74 |
75 | these things are off limits to the user application
76 |
77 | void* tp_buf; // underlying transport allocated pointer (e.g. nng message)
78 | void* header; // internal message header (whole buffer: header+payload)
79 | unsigned char* id; // if we need an ID in the message separate from the xaction id
80 | int flags; // various MFL (private) flags as needed
81 | int alloc_len; // the length of the allocated space (hdr+payload)
82 | } rmr_mbuf_t;
83
Tommy Carpenter3a6ac012020-04-06 14:42:57 -040084 RE PAYLOADs type below, see the documentation for c_char_p:
85 class ctypes.c_char_p
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -040086 Represents the C char * datatype when it points to a zero-terminated string.
87 For a general character pointer that may also point to binary data, POINTER(c_char)
88 must be used. The constructor accepts an integer address, or a bytes object.
Tommy Carpenter3a6ac012020-04-06 14:42:57 -040089 """
90
91 _fields_ = [
92 ("state", c_int),
93 ("mtype", c_int),
94 ("len", c_int),
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -040095 ("payload", POINTER(c_char)), # according to the following the python bytes are already unsigned
96 # https://bytes.com/topic/python/answers/695078-ctypes-unsigned-char
Tommy Carpenter3a6ac012020-04-06 14:42:57 -040097 ("xaction", POINTER(c_char)),
98 ("sub_id", c_int),
99 ("tp_state", c_int),
100 ]
101
102
103# argtypes and restype are important: https://stackoverflow.com/questions/24377845/ctype-why-specify-argtypes
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400104_rmr_init = rmr_c_lib.rmr_init
105_rmr_init.argtypes = [c_char_p, c_int, c_int]
106_rmr_init.restype = c_void_p
107
108
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400109def rmr_init(uproto_port: c_char_p, max_msg_size: int, flags: int) -> c_void_p:
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400110 """
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400111 Prepares the environment for sending and receiving messages.
112 Refer to RMR C documentation for method::
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400113
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400114 extern void* rmr_init(char* uproto_port, int max_msg_size, int flags)
115
116 This function raises an exception if the returned context is None.
117
118 Parameters
119 ----------
120 uproto_port: c_char_p
121 Pointer to bytes built from the port number as a string; e.g., b'4550'
122 max_msg_size: integer
123 Maximum message size to receive
124 flags: integer
125 RMR option flags
126
127 Returns
128 -------
129 c_void_p:
130 Pointer to RMR context
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400131 """
132 mrc = _rmr_init(uproto_port, max_msg_size, flags)
133 if mrc is None:
134 raise InitFailed()
135 return mrc
136
137
138_rmr_ready = rmr_c_lib.rmr_ready
139_rmr_ready.argtypes = [c_void_p]
140_rmr_ready.restype = c_int
141
142
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400143def rmr_ready(vctx: c_void_p) -> int:
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400144 """
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400145 Checks if a routing table has been received and installed.
146 Refer to RMR C documentation for method::
147
148 extern int rmr_ready(void* vctx)
149
150 Parameters
151 ----------
152 vctx: ctypes c_void_p
153 Pointer to RMR context
154
155 Returns
156 -------
157 1 for yes, 0 for no
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400158 """
159 return _rmr_ready(vctx)
160
161
162_rmr_close = rmr_c_lib.rmr_close
163_rmr_close.argtypes = [c_void_p]
164
165
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400166def rmr_close(vctx: c_void_p):
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400167 """
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400168 Closes the listen socket.
169 Refer to RMR C documentation for method::
170
171 extern void rmr_close(void* vctx)
172
173 Parameters
174 ----------
175 vctx: ctypes c_void_p
176 Pointer to RMR context
177
178 Returns
179 -------
180 None
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400181 """
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400182 _rmr_close(vctx)
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400183
184
185_rmr_set_stimeout = rmr_c_lib.rmr_set_stimeout
186_rmr_set_stimeout.argtypes = [c_void_p, c_int]
187_rmr_set_stimeout.restype = c_int
188
189
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400190def rmr_set_stimeout(vctx: c_void_p, rloops: int) -> int:
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400191 """
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400192 Sets the configuration for how RMR will retry message send operations.
193 Refer to RMR C documentation for method::
194
195 extern int rmr_set_stimeout(void* vctx, int rloops)
196
197 Parameters
198 ----------
199 vctx: ctypes c_void_p
200 Pointer to RMR context
201 rloops: int
202 Number of retry loops
203
204 Returns
205 -------
206 0 on success, -1 on failure
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400207 """
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400208 return _rmr_set_stimeout(vctx, rloops)
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400209
210
211_rmr_alloc_msg = rmr_c_lib.rmr_alloc_msg
212_rmr_alloc_msg.argtypes = [c_void_p, c_int]
213_rmr_alloc_msg.restype = POINTER(rmr_mbuf_t)
214
215
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400216def rmr_alloc_msg(vctx: c_void_p, size: int,
217 payload=None, gen_transaction_id=False, mtype=None,
218 meid=None, sub_id=None, fixed_transaction_id=None):
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400219 """
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400220 Allocates and returns a buffer to write and send through the RMR library.
221 Refer to RMR C documentation for method::
222
223 extern rmr_mbuf_t* rmr_alloc_msg(void* vctx, int size)
224
225 Optionally populates the message from the remaining arguments.
226
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400227 TODO: on next API break, clean up transaction_id ugliness. Kept for now to preserve API.
228
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400229 Parameters
230 ----------
231 vctx: ctypes c_void_p
232 Pointer to RMR context
233 size: int
234 How much space to allocate
235 payload: bytes
236 if not None, attempts to set the payload
237 gen_transaction_id: bool
238 if True, generates and sets a transaction ID.
239 Note, option fixed_transaction_id overrides this option
240 mtype: bytes
241 if not None, sets the sbuf's message type
242 meid: bytes
243 if not None, sets the sbuf's meid
244 sub_id: bytes
245 if not None, sets the sbuf's subscription id
246 fixed_transaction_id: bytes
247 if not None, used as the transaction ID.
248 Note, this overrides the option gen_transaction_id
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400249
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400250 Returns
251 -------
252 c_void_p:
253 Pointer to rmr_mbuf structure
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400254 """
255 sbuf = _rmr_alloc_msg(vctx, size)
256 try:
257 # make sure the alloc worked
258 sbuf.contents
259
260 # set specified fields
261 if payload:
262 set_payload_and_length(payload, sbuf)
263
264 if fixed_transaction_id:
265 set_transaction_id(sbuf, fixed_transaction_id)
266 elif gen_transaction_id:
267 generate_and_set_transaction_id(sbuf)
268
269 if mtype:
270 sbuf.contents.mtype = mtype
271
272 if meid:
273 rmr_set_meid(sbuf, meid)
274
275 if sub_id:
276 sbuf.contents.sub_id = sub_id
277
278 return sbuf
279
280 except ValueError:
281 raise BadBufferAllocation
282
283
284_rmr_realloc_payload = rmr_c_lib.rmr_realloc_payload
285_rmr_realloc_payload.argtypes = [POINTER(rmr_mbuf_t), c_int, c_int, c_int] # new_len, copy, clone
286_rmr_realloc_payload.restype = POINTER(rmr_mbuf_t)
287
288
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400289def rmr_realloc_payload(ptr_mbuf: c_void_p, new_len: int, copy=False, clone=False):
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400290 """
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400291 Allocates and returns a message buffer large enough for the new length.
292 Refer to RMR C documentation for method::
293
294 extern rmr_mbuf_t* rmr_realloc_payload(rmr_mbuf_t*, int, int, int)
295
296 Parameters
297 ----------
298 ptr_mbuf: c_void_p
299 Pointer to rmr_mbuf structure
300 new_len: int
301 Length
302 copy: bool
303 Whether to copy the original paylod
304 clone: bool
305 Whether to clone the original buffer
306
307 Returns
308 -------
309 c_void_p:
310 Pointer to rmr_mbuf structure
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400311 """
312 return _rmr_realloc_payload(ptr_mbuf, new_len, copy, clone)
313
314
315_rmr_free_msg = rmr_c_lib.rmr_free_msg
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400316_rmr_free_msg.argtypes = [POINTER(rmr_mbuf_t)]
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400317_rmr_free_msg.restype = None
318
319
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400320def rmr_free_msg(ptr_mbuf: c_void_p):
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400321 """
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400322 Releases the message buffer.
323 Refer to RMR C documentation for method::
324
325 extern void rmr_free_msg(rmr_mbuf_t* mbuf )
326
327 Parameters
328 ----------
329 ptr_mbuf: c_void_p
330 Pointer to rmr_mbuf structure
331
332 Returns
333 -------
334 None
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400335 """
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400336 if ptr_mbuf is not None:
337 _rmr_free_msg(ptr_mbuf)
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400338
339
340_rmr_payload_size = rmr_c_lib.rmr_payload_size
341_rmr_payload_size.argtypes = [POINTER(rmr_mbuf_t)]
342_rmr_payload_size.restype = c_int
343
344
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400345def rmr_payload_size(ptr_mbuf: c_void_p) -> int:
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400346 """
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400347 Gets the number of bytes available in the payload.
348 Refer to RMR C documentation for method::
349
350 extern int rmr_payload_size(rmr_mbuf_t* msg)
351
352 Parameters
353 ----------
354 ptr_mbuf: c_void_p
355 Pointer to rmr_mbuf structure
356
357 Returns
358 -------
359 int:
360 Number of bytes available
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400361 """
362 return _rmr_payload_size(ptr_mbuf)
363
364
365"""
366The following functions all seem to have the same interface
367"""
368
369_rmr_send_msg = rmr_c_lib.rmr_send_msg
370_rmr_send_msg.argtypes = [c_void_p, POINTER(rmr_mbuf_t)]
371_rmr_send_msg.restype = POINTER(rmr_mbuf_t)
372
373
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400374def rmr_send_msg(vctx: c_void_p, ptr_mbuf: POINTER(rmr_mbuf_t)) -> POINTER(rmr_mbuf_t):
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400375 """
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400376 Sends the message according to the routing table and returns an empty buffer.
377 Refer to RMR C documentation for method::
378
379 extern rmr_mbuf_t* rmr_send_msg(void* vctx, rmr_mbuf_t* msg)
380
381 Parameters
382 ----------
383 vctx: ctypes c_void_p
384 Pointer to RMR context
385 ptr_mbuf: c_void_p
386 Pointer to rmr_mbuf structure
387
388 Returns
389 -------
390 c_void_p:
391 Pointer to rmr_mbuf structure
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400392 """
393 return _rmr_send_msg(vctx, ptr_mbuf)
394
395
396# TODO: the old message (Send param) is actually optional, but I don't know how to specify that in Ctypes.
397_rmr_rcv_msg = rmr_c_lib.rmr_rcv_msg
398_rmr_rcv_msg.argtypes = [c_void_p, POINTER(rmr_mbuf_t)]
399_rmr_rcv_msg.restype = POINTER(rmr_mbuf_t)
400
401
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400402def rmr_rcv_msg(vctx: c_void_p, ptr_mbuf: POINTER(rmr_mbuf_t)) -> POINTER(rmr_mbuf_t):
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400403 """
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400404 Waits for a message to arrive, and returns it.
405 Refer to RMR C documentation for method::
406
407 extern rmr_mbuf_t* rmr_rcv_msg(void* vctx, rmr_mbuf_t* old_msg)
408
409 Parameters
410 ----------
411 vctx: ctypes c_void_p
412 Pointer to RMR context
413 ptr_mbuf: c_void_p
414 Pointer to rmr_mbuf structure
415
416 Returns
417 -------
418 c_void_p:
419 Pointer to rmr_mbuf structure
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400420 """
421 return _rmr_rcv_msg(vctx, ptr_mbuf)
422
423
424_rmr_torcv_msg = rmr_c_lib.rmr_torcv_msg
425_rmr_torcv_msg.argtypes = [c_void_p, POINTER(rmr_mbuf_t), c_int]
426_rmr_torcv_msg.restype = POINTER(rmr_mbuf_t)
427
428
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400429def rmr_torcv_msg(vctx: c_void_p, ptr_mbuf: POINTER(rmr_mbuf_t), ms_to: int) -> POINTER(rmr_mbuf_t):
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400430 """
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400431 Waits up to the timeout value for a message to arrive, and returns it.
432 Refer to RMR C documentation for method::
433
434 extern rmr_mbuf_t* rmr_torcv_msg(void* vctx, rmr_mbuf_t* old_msg, int ms_to)
435
436 Parameters
437 ----------
438 vctx: ctypes c_void_p
439 Pointer to RMR context
440 ptr_mbuf: c_void_p
441 Pointer to rmr_mbuf structure
442 ms_to: int
443 Time out value in milliseconds
444
445 Returns
446 -------
447 c_void_p:
448 Pointer to rmr_mbuf structure
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400449 """
450 return _rmr_torcv_msg(vctx, ptr_mbuf, ms_to)
451
452
453_rmr_rts_msg = rmr_c_lib.rmr_rts_msg
454_rmr_rts_msg.argtypes = [c_void_p, POINTER(rmr_mbuf_t)]
455_rmr_rts_msg.restype = POINTER(rmr_mbuf_t)
456
457
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400458def rmr_rts_msg(vctx: c_void_p, ptr_mbuf: POINTER(rmr_mbuf_t), payload=None, mtype=None) -> POINTER(rmr_mbuf_t):
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400459 """
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400460 Sends a message to the originating endpoint and returns an empty buffer.
461 Refer to RMR C documentation for method::
462
463 extern rmr_mbuf_t* rmr_rts_msg(void* vctx, rmr_mbuf_t* msg)
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400464
465 additional features beyond c-rmr:
466 if payload is not None, attempts to set the payload
467 if mtype is not None, sets the sbuf's message type
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400468
469 Parameters
470 ----------
471 vctx: ctypes c_void_p
472 Pointer to an RMR context
473 ptr_mbuf: ctypes c_void_p
474 Pointer to an RMR message buffer
475 payload: bytes
476 Payload
477 mtype: bytes
478 Message type
479
480 Returns
481 -------
482 c_void_p:
483 Pointer to rmr_mbuf structure
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400484 """
485
486 if payload:
487 set_payload_and_length(payload, ptr_mbuf)
488
489 if mtype:
490 ptr_mbuf.contents.mtype = mtype
491
492 return _rmr_rts_msg(vctx, ptr_mbuf)
493
494
495_rmr_call = rmr_c_lib.rmr_call
496_rmr_call.argtypes = [c_void_p, POINTER(rmr_mbuf_t)]
497_rmr_call.restype = POINTER(rmr_mbuf_t)
498
499
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400500def rmr_call(vctx: c_void_p, ptr_mbuf: POINTER(rmr_mbuf_t)) -> POINTER(rmr_mbuf_t):
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400501 """
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400502 Sends a message, waits for a response and returns it.
503 Refer to RMR C documentation for method::
504
505 extern rmr_mbuf_t* rmr_call(void* vctx, rmr_mbuf_t* msg)
506
507 Parameters
508 ----------
509 ptr_mbuf: ctypes c_void_p
510 Pointer to an RMR message buffer
511
512 Returns
513 -------
514 c_void_p:
515 Pointer to rmr_mbuf structure
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400516 """
517 return _rmr_call(vctx, ptr_mbuf)
518
519
520_rmr_bytes2meid = rmr_c_lib.rmr_bytes2meid
521_rmr_bytes2meid.argtypes = [POINTER(rmr_mbuf_t), c_char_p, c_int]
522_rmr_bytes2meid.restype = c_int
523
524
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400525def rmr_set_meid(ptr_mbuf: POINTER(rmr_mbuf_t), byte_str: bytes) -> int:
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400526 """
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400527 Sets the managed entity field in the message and returns the number of bytes copied.
528 Refer to RMR C documentation for method::
529
530 extern int rmr_bytes2meid(rmr_mbuf_t* mbuf, unsigned char const* src, int len);
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400531
532 Caution: the meid length supported in an RMR message is 32 bytes, but C applications
533 expect this to be a nil terminated string and thus only 31 bytes are actually available.
534
535 Raises: exceptions.MeidSizeOutOfRang
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400536
537 Parameters
538 ----------
539 ptr_mbuf: ctypes c_void_p
540 Pointer to an RMR message buffer
541 byte_tr: bytes
542 Managed entity ID value
543
544 Returns
545 -------
546 int:
547 number of bytes copied
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400548 """
Lott, Christopher (cl778h)db26ba22020-04-09 18:25:19 -0400549 max = _get_rmr_constant("RMR_MAX_MEID", 32)
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400550 if len(byte_str) >= max:
551 raise MeidSizeOutOfRange
552
553 return _rmr_bytes2meid(ptr_mbuf, byte_str, len(byte_str))
554
555
556# CAUTION: Some of the C functions expect a mutable buffer to copy the bytes into;
557# if there is a get_* function below, use it to set up and return the
558# buffer properly.
559
560# extern unsigned char* rmr_get_meid(rmr_mbuf_t* mbuf, unsigned char* dest);
561# we don't provide direct access to this function (unless it is asked for) because it is not really useful to provide your own buffer.
562# Rather, rmr_get_meid does this for you, and just returns the string.
563_rmr_get_meid = rmr_c_lib.rmr_get_meid
564_rmr_get_meid.argtypes = [POINTER(rmr_mbuf_t), c_char_p]
565_rmr_get_meid.restype = c_char_p
566
567
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400568def rmr_get_meid(ptr_mbuf: POINTER(rmr_mbuf_t)) -> bytes:
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400569 """
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400570 Gets the managed entity ID (meid) from the message header.
571 This is a python-friendly version of RMR C method::
572
573 extern unsigned char* rmr_get_meid(rmr_mbuf_t* mbuf, unsigned char* dest);
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400574
575 Parameters
576 ----------
577 ptr_mbuf: ctypes c_void_p
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400578 Pointer to an RMR message buffer
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400579
580 Returns
581 -------
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400582 bytes:
583 Managed entity ID
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400584 """
Lott, Christopher (cl778h)db26ba22020-04-09 18:25:19 -0400585 sz = _get_rmr_constant("RMR_MAX_MEID", 32) # size for buffer to fill
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400586 buf = create_string_buffer(sz)
587 _rmr_get_meid(ptr_mbuf, buf)
588 return buf.value
589
590
591_rmr_get_src = rmr_c_lib.rmr_get_src
592_rmr_get_src.argtypes = [POINTER(rmr_mbuf_t), c_char_p]
593_rmr_get_src.restype = c_char_p
594
595
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400596def rmr_get_src(ptr_mbuf: POINTER(rmr_mbuf_t), dest: c_char_p) -> c_char_p:
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400597 """
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400598 Copies the message-source information to the buffer.
599 Refer to RMR C documentation for method::
600
601 extern unsigned char* rmr_get_src(rmr_mbuf_t* mbuf, unsigned char* dest);
602
603 Parameters
604 ----------
605 ptr_mbuf: ctypes POINTER(rmr_mbuf_t)
606 Pointer to an RMR message buffer
607 dest: ctypes c_char_p
608 Pointer to a buffer to receive the message source
609
610 Returns
611 -------
612 string:
613 message-source information
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400614 """
615 return _rmr_get_src(ptr_mbuf, dest)
616
617
618# Methods that exist ONLY in rmr-python, and are not wrapped methods
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400619# In hindsight, I wish i put these in a separate module, but leaving this here to prevent api breakage.
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400620
621
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400622def get_payload(ptr_mbuf: c_void_p) -> bytes:
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400623 """
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400624 Gets the binary payload from the rmr_buf_t*.
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400625
626 Parameters
627 ----------
628 ptr_mbuf: ctypes c_void_p
629 Pointer to an rmr message buffer
630
631 Returns
632 -------
633 bytes:
634 the message payload
635 """
636 # Logic came from the answer here: https://stackoverflow.com/questions/55103298/python-ctypes-read-pointerc-char-in-python
637 sz = ptr_mbuf.contents.len
638 CharArr = c_char * sz
639 return CharArr(*ptr_mbuf.contents.payload[:sz]).raw
640
641
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400642def get_xaction(ptr_mbuf: c_void_p) -> bytes:
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400643 """
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400644 Gets the transaction ID from the rmr_buf_t*.
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400645
646 Parameters
647 ----------
648 ptr_mbuf: ctypes c_void_p
649 Pointer to an rmr message buffer
650
651 Returns
652 -------
653 bytes:
654 the transaction id
655 """
656 val = cast(ptr_mbuf.contents.xaction, c_char_p).value
Lott, Christopher (cl778h)db26ba22020-04-09 18:25:19 -0400657 sz = _get_rmr_constant("RMR_MAX_XID", 0)
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400658 return val[:sz]
659
660
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400661def message_summary(ptr_mbuf: c_void_p) -> dict:
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400662 """
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400663 Returns a dict with the fields of an RMR message.
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400664
665 Parameters
666 ----------
667 ptr_mbuf: ctypes c_void_p
668 Pointer to an rmr message buffer
669
670 Returns
671 -------
672 dict:
673 dict message summary
674 """
675 return {
676 "payload": get_payload(ptr_mbuf) if ptr_mbuf.contents.state == RMR_OK else None,
677 "payload length": ptr_mbuf.contents.len,
678 "message type": ptr_mbuf.contents.mtype,
679 "subscription id": ptr_mbuf.contents.sub_id,
680 "transaction id": get_xaction(ptr_mbuf),
681 "message state": ptr_mbuf.contents.state,
Lott, Christopher (cl778h)db26ba22020-04-09 18:25:19 -0400682 "message status": state_to_status(ptr_mbuf.contents.state),
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400683 "payload max size": rmr_payload_size(ptr_mbuf),
684 "meid": rmr_get_meid(ptr_mbuf),
685 "message source": get_src(ptr_mbuf),
686 "errno": ptr_mbuf.contents.tp_state,
687 }
688
689
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400690def set_payload_and_length(byte_str: bytes, ptr_mbuf: c_void_p):
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400691 """
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400692 Sets an rmr payload and content length.
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400693
694 Parameters
695 ----------
696 byte_str: bytes
697 the bytes to set the payload to
698 ptr_mbuf: ctypes c_void_p
699 Pointer to an rmr message buffer
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400700
701 Returns
702 -------
703 None
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400704 """
705 if rmr_payload_size(ptr_mbuf) < len(byte_str): # existing message payload too small
706 ptr_mbuf = rmr_realloc_payload(ptr_mbuf, len(byte_str), True)
707
708 memmove(ptr_mbuf.contents.payload, byte_str, len(byte_str))
709 ptr_mbuf.contents.len = len(byte_str)
710
711
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400712def generate_and_set_transaction_id(ptr_mbuf: c_void_p):
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400713 """
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400714 Generates a UUID and sets the RMR transaction id to it
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400715
716 Parameters
717 ----------
718 ptr_mbuf: ctypes c_void_p
719 Pointer to an rmr message buffer
720 """
721 set_transaction_id(ptr_mbuf, uuid.uuid1().hex.encode("utf-8"))
722
723
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400724def set_transaction_id(ptr_mbuf: c_void_p, tid_bytes: bytes):
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400725 """
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400726 Sets an RMR transaction id
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400727 TODO: on next API break, merge these two functions. Not done now to preserve API.
728
729 Parameters
730 ----------
731 ptr_mbuf: ctypes c_void_p
732 Pointer to an rmr message buffer
733 tid_bytes: bytes
734 bytes of the desired transaction id
735 """
Lott, Christopher (cl778h)db26ba22020-04-09 18:25:19 -0400736 sz = _get_rmr_constant("RMR_MAX_XID", 0)
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400737 memmove(ptr_mbuf.contents.xaction, tid_bytes, sz)
738
739
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400740def get_src(ptr_mbuf: c_void_p) -> str:
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400741 """
Lott, Christopher (cl778h)4b9552c2020-04-09 14:49:02 -0400742 Gets the message source (likely host:port)
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400743
744 Parameters
745 ----------
746 ptr_mbuf: ctypes c_void_p
747 Pointer to an rmr message buffer
748
749 Returns
750 -------
751 string:
752 message source
753 """
Lott, Christopher (cl778h)db26ba22020-04-09 18:25:19 -0400754 sz = _get_rmr_constant("RMR_MAX_SRC", 64) # size to fill
Tommy Carpenter3a6ac012020-04-06 14:42:57 -0400755 buf = create_string_buffer(sz)
756 rmr_get_src(ptr_mbuf, buf)
757 return buf.value.decode()