From fc6dda50b55af1ba9f2bb2f0f78f187102893a09 Mon Sep 17 00:00:00 2001 From: Leonard Pollak Date: Thu, 14 Oct 2021 10:33:08 +0200 Subject: [PATCH] Update NNG version and remove deprecated API A new option class is added: ArbitraryOption --- .gitignore | 2 +- build_pynng.py | 2 +- nng_api.h | 115 +++++++++++------------------------------------ pynng/_aio.py | 4 +- pynng/nng.py | 64 ++++++++++++++++++++++++-- pynng/options.py | 46 +++++++++++++------ pytest.ini | 6 +++ setup.cfg | 7 ++- setup.py | 7 +-- 9 files changed, 137 insertions(+), 116 deletions(-) create mode 100644 pytest.ini diff --git a/.gitignore b/.gitignore index f0e90f0..1177957 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,7 @@ _nng_py.c Release _nng.c *.pyd -__pycache__ +**/__pycache__/ *.swp .pytest_cache dist diff --git a/build_pynng.py b/build_pynng.py index 4772596..6c94692 100644 --- a/build_pynng.py +++ b/build_pynng.py @@ -26,7 +26,7 @@ # e.g.: python setup.py build_ext -I -L -l #elif True: # incdirs = None -# libraries = ['pthread' 'mbedtls' 'nng'] +# libraries = ['pthread', 'mbedtls', 'nng'] # objects = None else: incdirs = ['nng/include'] diff --git a/nng_api.h b/nng_api.h index e5cabb8..07844d5 100644 --- a/nng_api.h +++ b/nng_api.h @@ -22,21 +22,16 @@ struct nng_sockaddr_inproc { uint16_t sa_family; char sa_name[(128)]; }; -typedef struct nng_sockaddr_inproc nng_sockaddr_inproc; struct nng_sockaddr_path { uint16_t sa_family; char sa_path[(128)]; }; -typedef struct nng_sockaddr_path nng_sockaddr_path; -typedef struct nng_sockaddr_path nng_sockaddr_ipc; struct nng_sockaddr_in6 { uint16_t sa_family; uint16_t sa_port; uint8_t sa_addr[16]; + uint32_t sa_scope; }; -typedef struct nng_sockaddr_in6 nng_sockaddr_in6; -typedef struct nng_sockaddr_in6 nng_sockaddr_udp6; -typedef struct nng_sockaddr_in6 nng_sockaddr_tcp6; struct nng_sockaddr_in { uint16_t sa_family; uint16_t sa_port; @@ -48,10 +43,23 @@ struct nng_sockaddr_zt { uint64_t sa_nodeid; uint32_t sa_port; }; +struct nng_sockaddr_abstract { + uint16_t sa_family; + uint16_t sa_len; + uint8_t sa_name[107]; +}; +struct nng_sockaddr_storage { + uint16_t sa_family; + uint64_t sa_pad[16]; +}; +typedef struct nng_sockaddr_inproc nng_sockaddr_inproc; +typedef struct nng_sockaddr_path nng_sockaddr_path; +typedef struct nng_sockaddr_path nng_sockaddr_ipc; typedef struct nng_sockaddr_in nng_sockaddr_in; -typedef struct nng_sockaddr_in nng_sockaddr_udp; -typedef struct nng_sockaddr_in nng_sockaddr_tcp; +typedef struct nng_sockaddr_in6 nng_sockaddr_in6; typedef struct nng_sockaddr_zt nng_sockaddr_zt; +typedef struct nng_sockaddr_abstract nng_sockaddr_abstract; +typedef struct nng_sockaddr_storage nng_sockaddr_storage; typedef union nng_sockaddr { uint16_t s_family; nng_sockaddr_ipc s_ipc; @@ -59,6 +67,8 @@ typedef union nng_sockaddr { nng_sockaddr_in6 s_in6; nng_sockaddr_in s_in; nng_sockaddr_zt s_zt; + nng_sockaddr_abstract s_abstract; + nng_sockaddr_storage s_storage; } nng_sockaddr; enum nng_sockaddr_family { NNG_AF_UNSPEC = 0, @@ -66,7 +76,8 @@ enum nng_sockaddr_family { NNG_AF_IPC = 2, NNG_AF_INET = 3, NNG_AF_INET6 = 4, - NNG_AF_ZT = 5 + NNG_AF_ZT = 5, + NNG_AF_ABSTRACT = 6 }; typedef struct nng_iov { void * iov_buf; @@ -75,23 +86,6 @@ typedef struct nng_iov { extern void nng_fini(void); extern int nng_close(nng_socket); extern int nng_socket_id(nng_socket); -extern void nng_closeall(void); -extern int nng_setopt(nng_socket, const char *, const void *, size_t); -extern int nng_setopt_bool(nng_socket, const char *, bool); -extern int nng_setopt_int(nng_socket, const char *, int); -extern int nng_setopt_ms(nng_socket, const char *, nng_duration); -extern int nng_setopt_size(nng_socket, const char *, size_t); -extern int nng_setopt_uint64(nng_socket, const char *, uint64_t); -extern int nng_setopt_string(nng_socket, const char *, const char *); -extern int nng_setopt_ptr(nng_socket, const char *, void *); -extern int nng_getopt(nng_socket, const char *, void *, size_t *); -extern int nng_getopt_bool(nng_socket, const char *, bool *); -extern int nng_getopt_int(nng_socket, const char *, int *); -extern int nng_getopt_ms(nng_socket, const char *, nng_duration *); -extern int nng_getopt_size(nng_socket, const char *, size_t *); -extern int nng_getopt_uint64(nng_socket, const char *, uint64_t *); -extern int nng_getopt_ptr(nng_socket, const char *, void **); -extern int nng_getopt_string(nng_socket, const char *, char **); extern int nng_socket_set(nng_socket, const char *, const void *, size_t); extern int nng_socket_set_bool(nng_socket, const char *, bool); extern int nng_socket_set_int(nng_socket, const char *, int); @@ -129,24 +123,6 @@ extern int nng_dialer_close(nng_dialer); extern int nng_listener_close(nng_listener); extern int nng_dialer_id(nng_dialer); extern int nng_listener_id(nng_listener); -extern int nng_dialer_setopt(nng_dialer, const char *, const void *, size_t); -extern int nng_dialer_setopt_bool(nng_dialer, const char *, bool); -extern int nng_dialer_setopt_int(nng_dialer, const char *, int); -extern int nng_dialer_setopt_ms(nng_dialer, const char *, nng_duration); -extern int nng_dialer_setopt_size(nng_dialer, const char *, size_t); -extern int nng_dialer_setopt_uint64(nng_dialer, const char *, uint64_t); -extern int nng_dialer_setopt_ptr(nng_dialer, const char *, void *); -extern int nng_dialer_setopt_string(nng_dialer, const char *, const char *); -extern int nng_dialer_getopt(nng_dialer, const char *, void *, size_t *); -extern int nng_dialer_getopt_bool(nng_dialer, const char *, bool *); -extern int nng_dialer_getopt_int(nng_dialer, const char *, int *); -extern int nng_dialer_getopt_ms(nng_dialer, const char *, nng_duration *); -extern int nng_dialer_getopt_size(nng_dialer, const char *, size_t *); -extern int nng_dialer_getopt_sockaddr( - nng_dialer, const char *, nng_sockaddr *); -extern int nng_dialer_getopt_uint64(nng_dialer, const char *, uint64_t *); -extern int nng_dialer_getopt_ptr(nng_dialer, const char *, void **); -extern int nng_dialer_getopt_string(nng_dialer, const char *, char **); extern int nng_dialer_set(nng_dialer, const char *, const void *, size_t); extern int nng_dialer_set_bool(nng_dialer, const char *, bool); extern int nng_dialer_set_int(nng_dialer, const char *, int); @@ -166,28 +142,6 @@ extern int nng_dialer_get_string(nng_dialer, const char *, char **); extern int nng_dialer_get_ptr(nng_dialer, const char *, void **); extern int nng_dialer_get_ms(nng_dialer, const char *, nng_duration *); extern int nng_dialer_get_addr(nng_dialer, const char *, nng_sockaddr *); -extern int nng_listener_setopt( - nng_listener, const char *, const void *, size_t); -extern int nng_listener_setopt_bool(nng_listener, const char *, bool); -extern int nng_listener_setopt_int(nng_listener, const char *, int); -extern int nng_listener_setopt_ms(nng_listener, const char *, nng_duration); -extern int nng_listener_setopt_size(nng_listener, const char *, size_t); -extern int nng_listener_setopt_uint64(nng_listener, const char *, uint64_t); -extern int nng_listener_setopt_ptr(nng_listener, const char *, void *); -extern int nng_listener_setopt_string( - nng_listener, const char *, const char *); -extern int nng_listener_getopt(nng_listener, const char *, void *, size_t *); -extern int nng_listener_getopt_bool(nng_listener, const char *, bool *); -extern int nng_listener_getopt_int(nng_listener, const char *, int *); -extern int nng_listener_getopt_ms( - nng_listener, const char *, nng_duration *); -extern int nng_listener_getopt_size(nng_listener, const char *, size_t *); -extern int nng_listener_getopt_sockaddr( - nng_listener, const char *, nng_sockaddr *); -extern int nng_listener_getopt_uint64( - nng_listener, const char *, uint64_t *); -extern int nng_listener_getopt_ptr(nng_listener, const char *, void **); -extern int nng_listener_getopt_string(nng_listener, const char *, char **); extern int nng_listener_set( nng_listener, const char *, const void *, size_t); extern int nng_listener_set_bool(nng_listener, const char *, bool); @@ -220,16 +174,6 @@ extern int nng_ctx_close(nng_ctx); extern int nng_ctx_id(nng_ctx); extern void nng_ctx_recv(nng_ctx, nng_aio *); extern void nng_ctx_send(nng_ctx, nng_aio *); -extern int nng_ctx_getopt(nng_ctx, const char *, void *, size_t *); -extern int nng_ctx_getopt_bool(nng_ctx, const char *, bool *); -extern int nng_ctx_getopt_int(nng_ctx, const char *, int *); -extern int nng_ctx_getopt_ms(nng_ctx, const char *, nng_duration *); -extern int nng_ctx_getopt_size(nng_ctx, const char *, size_t *); -extern int nng_ctx_setopt(nng_ctx, const char *, const void *, size_t); -extern int nng_ctx_setopt_bool(nng_ctx, const char *, bool); -extern int nng_ctx_setopt_int(nng_ctx, const char *, int); -extern int nng_ctx_setopt_ms(nng_ctx, const char *, nng_duration); -extern int nng_ctx_setopt_size(nng_ctx, const char *, size_t); extern int nng_ctx_get(nng_ctx, const char *, void *, size_t *); extern int nng_ctx_get_bool(nng_ctx, const char *, bool *); extern int nng_ctx_get_int(nng_ctx, const char *, int *); @@ -254,6 +198,7 @@ extern char *nng_strdup(const char *); extern void nng_strfree(char *); extern int nng_aio_alloc(nng_aio **, void (*)(void *), void *); extern void nng_aio_free(nng_aio *); +extern void nng_aio_reap(nng_aio *); extern void nng_aio_stop(nng_aio *); extern int nng_aio_result(nng_aio *); extern size_t nng_aio_count(nng_aio *); @@ -276,6 +221,8 @@ extern void nng_sleep_aio(nng_duration, nng_aio *); extern int nng_msg_alloc(nng_msg **, size_t); extern void nng_msg_free(nng_msg *); extern int nng_msg_realloc(nng_msg *, size_t); +extern int nng_msg_reserve(nng_msg *, size_t); +extern size_t nng_msg_capacity(nng_msg *); extern void * nng_msg_header(nng_msg *); extern size_t nng_msg_header_len(const nng_msg *); extern void * nng_msg_body(nng_msg *); @@ -317,16 +264,6 @@ extern void nng_msg_clear(nng_msg *); extern void nng_msg_header_clear(nng_msg *); extern void nng_msg_set_pipe(nng_msg *, nng_pipe); extern nng_pipe nng_msg_get_pipe(const nng_msg *); -extern int nng_msg_getopt(nng_msg *, int, void *, size_t *); -extern int nng_pipe_getopt(nng_pipe, const char *, void *, size_t *); -extern int nng_pipe_getopt_bool(nng_pipe, const char *, bool *); -extern int nng_pipe_getopt_int(nng_pipe, const char *, int *); -extern int nng_pipe_getopt_ms(nng_pipe, const char *, nng_duration *); -extern int nng_pipe_getopt_size(nng_pipe, const char *, size_t *); -extern int nng_pipe_getopt_sockaddr(nng_pipe, const char *, nng_sockaddr *); -extern int nng_pipe_getopt_uint64(nng_pipe, const char *, uint64_t *); -extern int nng_pipe_getopt_ptr(nng_pipe, const char *, void **); -extern int nng_pipe_getopt_string(nng_pipe, const char *, char **); extern int nng_pipe_get(nng_pipe, const char *, void *, size_t *); extern int nng_pipe_get_bool(nng_pipe, const char *, bool *); extern int nng_pipe_get_int(nng_pipe, const char *, int *); @@ -369,6 +306,7 @@ enum nng_unit_enum { NNG_UNIT_EVENTS = 4 }; extern uint64_t nng_stat_value(nng_stat *); +extern bool nng_stat_bool(nng_stat *); extern const char *nng_stat_string(nng_stat *); extern const char *nng_stat_desc(nng_stat *); extern uint64_t nng_stat_timestamp(nng_stat *); @@ -591,9 +529,8 @@ int nng_tls_config_version( const char *nng_tls_engine_name(void); const char *nng_tls_engine_description(void); bool nng_tls_engine_fips_mode(void); -int nng_tls_register(void); #define NNG_FLAG_ALLOC 1u // Recv to allocate receive buffer #define NNG_FLAG_NONBLOCK 2u // Non-blocking operations #define NNG_MAJOR_VERSION 1 -#define NNG_MINOR_VERSION 4 -#define NNG_PATCH_VERSION 0 +#define NNG_MINOR_VERSION 5 +#define NNG_PATCH_VERSION 2 diff --git a/pynng/_aio.py b/pynng/_aio.py index 82440f4..1222343 100644 --- a/pynng/_aio.py +++ b/pynng/_aio.py @@ -40,12 +40,12 @@ async def wait_for_aio(): except curio.CancelledError: if fut.cancelled(): lib.nng_aio_cancel(aio.aio) - + err = lib.nng_aio_result(aio.aio) if err == lib.NNG_ECANCELED: raise curio.CancelledError() check_err(err) - + def callback(): if not fut.cancelled(): fut.set_result(True) diff --git a/pynng/nng.py b/pynng/nng.py index 1b71a4e..7472e3f 100644 --- a/pynng/nng.py +++ b/pynng/nng.py @@ -92,6 +92,12 @@ def __set__(self, instance, value): self.__class__._setter(instance, self.option, value) +class ArbitraryOption(_NNGOption): + """Descriptor for getting/setting arbitrary options""" + _getter = options._getopt_arbitrary + _setter = options._setopt_arbitrary + + class IntOption(_NNGOption): """Descriptor for getting/setting integer options""" _getter = options._getopt_int @@ -279,7 +285,10 @@ class Socket: tcp_nodelay = BooleanOption('tcp-nodelay') tcp_keepalive = BooleanOption('tcp-keepalive') - tls_config = PointerOption('tls-config') + #tls_config = PointerOption('tls-config') + # Sockets are Transport agnostic. + # The tls-config is transport specific and has to be set on the listener/dialer + tls_config = None def __init__(self, *, dial=None, @@ -386,11 +395,21 @@ def _dial(self, address, flags=0): """ dialer = ffi.new('nng_dialer *') - ret = lib.nng_dial(self.socket, to_char(address), dialer, flags) + if self.tls_config: + ret = lib.nng_dialer_create(dialer, self.socket, to_char(address)) + else: + ret = lib.nng_dial(self.socket, to_char(address), dialer, flags) check_err(ret) # we can only get here if check_err doesn't raise d_id = lib.nng_dialer_id(dialer[0]) py_dialer = Dialer(dialer, self) + if self.tls_config: + py_dialer.tls_config = self.tls_config + lib.nng_dialer_start(dialer[0], flags) + # FIXME: Set the tls_config to None here + # If one wants another dialer with the same tls_config it + # has to be set again which might be confusing + self.tls_config = None self._dialers[d_id] = py_dialer return py_dialer @@ -401,11 +420,21 @@ def listen(self, address, flags=0): """ listener = ffi.new('nng_listener *') - ret = lib.nng_listen(self.socket, to_char(address), listener, flags) + if self.tls_config: + ret = lib.nng_listener_create(listener, self.socket, to_char(address)) + else: + ret = lib.nng_listen(self.socket, to_char(address), listener, flags) check_err(ret) # we can only get here if check_err doesn't raise l_id = lib.nng_listener_id(listener[0]) py_listener = Listener(listener, self) + if self.tls_config: + py_listener.tls_config = self.tls_config + lib.nng_listener_start(listener[0], flags) + # FIXME: Set the tls_config to None here + # If one wants another listener with the same tls_config it + # has to be set again which might be confusing + self.tls_config = None self._listeners[l_id] = py_listener return py_listener @@ -873,11 +902,38 @@ def subscribe(self, topic): desired behavior, just pass :class:`bytes` in as the topic. """ - options._setopt_string(self, b'sub:subscribe', topic) + options._setopt_arbitrary(self, b'sub:subscribe', topic) def unsubscribe(self, topic): """Unsubscribe to the specified topic. + .. Note:: + + If you pass a :class:`str` as the ``topic``, it will be + automatically encoded with :meth:`str.encode`. If this is not the + desired behavior, just pass :class:`bytes` in as the topic. + + """ + options._setopt_arbitrary(self, b'sub:unsubscribe', topic) + + def subscribe_string(self, topic): + """Subscribe to the specified topic. + + Topics are matched by looking at the first bytes of any received + message. + + .. Note:: + + If you pass a :class:`str` as the ``topic``, it will be + automatically encoded with :meth:`str.encode`. If this is not the + desired behavior, just pass :class:`bytes` in as the topic. + + """ + options._setopt_string(self, b'sub:subscribe', topic) + + def unsubscribe_string(self, topic): + """Unsubscribe to the specified topic. + .. Note:: If you pass a :class:`str` as the ``topic``, it will be diff --git a/pynng/options.py b/pynng/options.py index 671335c..1d3669e 100644 --- a/pynng/options.py +++ b/pynng/options.py @@ -21,13 +21,14 @@ def _get_inst_and_func(py_obj, option_type, get_or_set): # map Python wrapper class to nng attribute option_to_func_map = { - 'int': 'nng_getopt_int', - 'size': 'nng_getopt_size', - 'ms': 'nng_getopt_ms', - 'string': 'nng_getopt_string', - 'bool': 'nng_getopt_bool', - 'sockaddr': 'nng_getopt_sockaddr', - 'ptr': 'nng_getopt_ptr', + 'arbitrary': 'nng_get', + 'int': 'nng_get_int', + 'size': 'nng_get_size', + 'ms': 'nng_get_ms', + 'string': 'nng_get_string', + 'bool': 'nng_get_bool', + 'sockaddr': 'nng_get_addr', + 'ptr': 'nng_get_ptr', } if option_type not in option_to_func_map: @@ -35,7 +36,7 @@ def _get_inst_and_func(py_obj, option_type, get_or_set): basic_funcname = option_to_func_map[option_type] if isinstance(py_obj, pynng.Socket): - funcname = basic_funcname + funcname = basic_funcname.replace('nng_', 'nng_socket_') obj = py_obj.socket elif isinstance(py_obj, pynng.Dialer): funcname = basic_funcname.replace('nng_', 'nng_dialer_') @@ -52,16 +53,33 @@ def _get_inst_and_func(py_obj, option_type, get_or_set): raise TypeError(msg) if get_or_set == 'set': - funcname = funcname.replace('getopt', 'setopt') - # special-case for nng_setopt_string, which expects NULL-terminated - # strings; we use the generic setopt in that case. - if option_type == 'string': - funcname = funcname.replace('_string', '') + funcname = funcname.replace('get', 'set') nng_func = getattr(pynng.lib, funcname) return obj, nng_func +def _getopt_arbitrary(py_obj, option): + """Gets the specified option""" + opt = pynng.ffi.new('char *[]', 1) + opt_as_char = pynng.nng.to_char(option) + obj, lib_func = _get_inst_and_func(py_obj, 'arbitrary', 'get') + ret = lib_func(obj, opt_as_char, opt) + pynng.check_err(ret) + py_string = pynng.ffi.string(opt[0]).decode() + pynng.lib.nng_strfree(opt[0]) + return py_string + + +def _setopt_arbitrary(py_obj, option, value): + """Sets an arbitrary option to the specified value""" + opt_as_char = pynng.nng.to_char(option) + val_as_char = pynng.nng.to_char(value) + obj, lib_func = _get_inst_and_func(py_obj, 'arbitrary', 'set') + ret = lib_func(obj, opt_as_char, val_as_char, len(value)) + pynng.check_err(ret) + + def _getopt_int(obj, option): """Gets the specified option""" i = pynng.ffi.new('int []', 1) @@ -156,7 +174,7 @@ def _setopt_string(py_obj, option, value): opt_as_char = pynng.nng.to_char(option) val_as_char = pynng.nng.to_char(value) obj, lib_func = _get_inst_and_func(py_obj, 'string', 'set') - ret = lib_func(obj, opt_as_char, val_as_char, len(value)) + ret = lib_func(obj, opt_as_char, val_as_char) pynng.check_err(ret) diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..e43a4d3 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,6 @@ +[pytest] +log_cli = 1 +log_cli_level = INFO +log_cli_format = %(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s) +log_cli_date_format=%Y-%m-%d %H:%M:%S +addopts = --ignore-glob=mbedtls diff --git a/setup.cfg b/setup.cfg index 4baa27d..f498faa 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,10 +1,13 @@ [build_nng] repo = 'https://github.com/nanomsg/nng' -rev = '4f5e11c391c4a8f1b2731aee5ad47bc0c925042a' +rev = '8d7dcb68d90524a316d2df99d4043a83ce72d6ea' [build_mbedtls] repo = 'https://github.com/ARMmbed/mbedtls.git' -rev = '04a049bda1ceca48060b57bc4bcf5203ce591421' +rev = '8df2f8e7b9c7bb9390ac74bb7bace27edca81a2b' [build_ext] inplace = 1 + +[build] +build-deps = True diff --git a/setup.py b/setup.py index 9f6ee17..60203dc 100644 --- a/setup.py +++ b/setup.py @@ -69,6 +69,7 @@ class BuildNng(BuilderBase): '-DNNG_ENABLE_TLS=ON', '-DNNG_TESTS=OFF', '-DNNG_TOOLS=OFF', + '-DNNG_ELIDE_DEPRECATED=ON', '-DCMAKE_BUILD_TYPE=Release', '-DMBEDTLS_ROOT_DIR={}/mbedtls/prefix/'.format(this_dir), ] @@ -114,7 +115,7 @@ def initialize_options(self): Each user option must be listed here with their default value. """ dbuild.initialize_options(self) - self.build_deps = 'yes' + self.build_deps = False def run(self): """ @@ -168,10 +169,10 @@ def run(self): tests_require=[ 'pytest', 'pytest-asyncio', - 'pytest-trio', - 'pytest-curio', 'trio', + 'pytest-trio', 'curio' + 'pytest-curio', ], test_suite='tests', )