1# coding: utf-8
2"""miscellaneous zmq_utils wrapping"""
3
4# Copyright (C) PyZMQ Developers
5# Distributed under the terms of the Modified BSD License.
6
7from ._cffi import ffi, C
8
9from zmq.error import ZMQError, _check_rc, _check_version
10from zmq.utils.strtypes import unicode
11
12def has(capability):
13    """Check for zmq capability by name (e.g. 'ipc', 'curve')
14
15    .. versionadded:: libzmq-4.1
16    .. versionadded:: 14.1
17    """
18    _check_version((4,1), 'zmq.has')
19    if isinstance(capability, unicode):
20        capability = capability.encode('utf8')
21    return bool(C.zmq_has(capability))
22
23def curve_keypair():
24    """generate a Z85 keypair for use with zmq.CURVE security
25
26    Requires libzmq (≥ 4.0) to have been linked with libsodium.
27
28    Returns
29    -------
30    (public, secret) : two bytestrings
31        The public and private keypair as 40 byte z85-encoded bytestrings.
32    """
33    _check_version((3,2), "monitor")
34    public = ffi.new('char[64]')
35    private = ffi.new('char[64]')
36    rc = C.zmq_curve_keypair(public, private)
37    _check_rc(rc)
38    return ffi.buffer(public)[:40], ffi.buffer(private)[:40]
39
40
41class Stopwatch(object):
42    def __init__(self):
43        self.watch = ffi.NULL
44
45    def start(self):
46        if self.watch == ffi.NULL:
47            self.watch = C.zmq_stopwatch_start()
48        else:
49            raise ZMQError('Stopwatch is already runing.')
50
51    def stop(self):
52        if self.watch == ffi.NULL:
53            raise ZMQError('Must start the Stopwatch before calling stop.')
54        else:
55            time = C.zmq_stopwatch_stop(self.watch)
56            self.watch = ffi.NULL
57            return time
58
59    def sleep(self, seconds):
60        C.zmq_sleep(seconds)
61
62__all__ = ['has', 'curve_keypair', 'Stopwatch']
63