1aec3c8f4Simarom"""0MQ Socket class."""
2aec3c8f4Simarom
3aec3c8f4Simarom#
4aec3c8f4Simarom#    Copyright (c) 2010-2011 Brian E. Granger & Min Ragan-Kelley
5aec3c8f4Simarom#
6aec3c8f4Simarom#    This file is part of pyzmq.
7aec3c8f4Simarom#
8aec3c8f4Simarom#    pyzmq is free software; you can redistribute it and/or modify it under
9aec3c8f4Simarom#    the terms of the Lesser GNU General Public License as published by
10aec3c8f4Simarom#    the Free Software Foundation; either version 3 of the License, or
11aec3c8f4Simarom#    (at your option) any later version.
12aec3c8f4Simarom#
13aec3c8f4Simarom#    pyzmq is distributed in the hope that it will be useful,
14aec3c8f4Simarom#    but WITHOUT ANY WARRANTY; without even the implied warranty of
15aec3c8f4Simarom#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16aec3c8f4Simarom#    Lesser GNU General Public License for more details.
17aec3c8f4Simarom#
18aec3c8f4Simarom#    You should have received a copy of the Lesser GNU General Public License
19aec3c8f4Simarom#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20aec3c8f4Simarom#
21aec3c8f4Simarom
22aec3c8f4Simarom#-----------------------------------------------------------------------------
23aec3c8f4Simarom# Cython Imports
24aec3c8f4Simarom#-----------------------------------------------------------------------------
25aec3c8f4Simarom
26aec3c8f4Simarom# get version-independent aliases:
27aec3c8f4Simaromcdef extern from "pyversion_compat.h":
28aec3c8f4Simarom    pass
29aec3c8f4Simarom
30aec3c8f4Simaromfrom libc.errno cimport ENAMETOOLONG
31aec3c8f4Simaromfrom libc.string cimport memcpy
32aec3c8f4Simarom
33aec3c8f4Simaromfrom cpython cimport PyBytes_FromStringAndSize
34aec3c8f4Simaromfrom cpython cimport PyBytes_AsString, PyBytes_Size
35aec3c8f4Simaromfrom cpython cimport Py_DECREF, Py_INCREF
36aec3c8f4Simarom
37aec3c8f4Simaromfrom buffers cimport asbuffer_r, viewfromobject_r
38aec3c8f4Simarom
39aec3c8f4Simaromfrom libzmq cimport *
40aec3c8f4Simaromfrom message cimport Frame, copy_zmq_msg_bytes
41aec3c8f4Simarom
42aec3c8f4Simaromfrom context cimport Context
43aec3c8f4Simarom
44aec3c8f4Simaromcdef extern from "Python.h":
45aec3c8f4Simarom    ctypedef int Py_ssize_t
46aec3c8f4Simarom
47aec3c8f4Simaromcdef extern from "ipcmaxlen.h":
48aec3c8f4Simarom    int get_ipc_path_max_len()
49aec3c8f4Simarom
50aec3c8f4Simaromcdef extern from "getpid_compat.h":
51aec3c8f4Simarom    int getpid()
52aec3c8f4Simarom
53aec3c8f4Simarom
54aec3c8f4Simarom#-----------------------------------------------------------------------------
55aec3c8f4Simarom# Python Imports
56aec3c8f4Simarom#-----------------------------------------------------------------------------
57aec3c8f4Simarom
58aec3c8f4Simaromimport copy as copy_mod
59aec3c8f4Simaromimport time
60aec3c8f4Simaromimport sys
61aec3c8f4Simaromimport random
62aec3c8f4Simaromimport struct
63aec3c8f4Simaromimport codecs
64aec3c8f4Simarom
65aec3c8f4Simaromfrom zmq.utils import jsonapi
66aec3c8f4Simarom
67aec3c8f4Simaromtry:
68aec3c8f4Simarom    import cPickle
69aec3c8f4Simarom    pickle = cPickle
70aec3c8f4Simaromexcept:
71aec3c8f4Simarom    cPickle = None
72aec3c8f4Simarom    import pickle
73aec3c8f4Simarom
74aec3c8f4Simaromimport zmq
75aec3c8f4Simaromfrom zmq.backend.cython import constants
76aec3c8f4Simaromfrom zmq.backend.cython.constants import *
77aec3c8f4Simaromfrom zmq.backend.cython.checkrc cimport _check_rc
78aec3c8f4Simaromfrom zmq.error import ZMQError, ZMQBindError, _check_version
79aec3c8f4Simaromfrom zmq.utils.strtypes import bytes,unicode,basestring
80aec3c8f4Simarom
81aec3c8f4Simarom#-----------------------------------------------------------------------------
82aec3c8f4Simarom# Code
83aec3c8f4Simarom#-----------------------------------------------------------------------------
84aec3c8f4Simarom
85aec3c8f4SimaromIPC_PATH_MAX_LEN = get_ipc_path_max_len()
86aec3c8f4Simarom
87aec3c8f4Simarom# inline some small socket submethods:
88aec3c8f4Simarom# true methods frequently cannot be inlined, acc. Cython docs
89aec3c8f4Simarom
90aec3c8f4Simaromcdef inline _check_closed(Socket s):
91aec3c8f4Simarom    """raise ENOTSUP if socket is closed
92aec3c8f4Simarom    
93aec3c8f4Simarom    Does not do a deep check
94aec3c8f4Simarom    """
95aec3c8f4Simarom    if s._closed:
96aec3c8f4Simarom        raise ZMQError(ENOTSOCK)
97aec3c8f4Simarom
98aec3c8f4Simaromcdef inline _check_closed_deep(Socket s):
99aec3c8f4Simarom    """thorough check of whether the socket has been closed,
100aec3c8f4Simarom    even if by another entity (e.g. ctx.destroy).
101aec3c8f4Simarom    
102aec3c8f4Simarom    Only used by the `closed` property.
103aec3c8f4Simarom    
104aec3c8f4Simarom    returns True if closed, False otherwise
105aec3c8f4Simarom    """
106aec3c8f4Simarom    cdef int rc
107aec3c8f4Simarom    cdef int errno
108aec3c8f4Simarom    cdef int stype
109aec3c8f4Simarom    cdef size_t sz=sizeof(int)
110aec3c8f4Simarom    if s._closed:
111aec3c8f4Simarom        return True
112aec3c8f4Simarom    else:
113aec3c8f4Simarom        rc = zmq_getsockopt(s.handle, ZMQ_TYPE, <void *>&stype, &sz)
114aec3c8f4Simarom        if rc < 0 and zmq_errno() == ENOTSOCK:
115aec3c8f4Simarom            s._closed = True
116aec3c8f4Simarom            return True
117aec3c8f4Simarom        else:
118aec3c8f4Simarom            _check_rc(rc)
119aec3c8f4Simarom    return False
120aec3c8f4Simarom
121aec3c8f4Simaromcdef inline Frame _recv_frame(void *handle, int flags=0, track=False):
122aec3c8f4Simarom    """Receive a message in a non-copying manner and return a Frame."""
123aec3c8f4Simarom    cdef int rc
124aec3c8f4Simarom    msg = zmq.Frame(track=track)
125aec3c8f4Simarom    cdef Frame cmsg = msg
126aec3c8f4Simarom
127aec3c8f4Simarom    with nogil:
128aec3c8f4Simarom        rc = zmq_msg_recv(&cmsg.zmq_msg, handle, flags)
129aec3c8f4Simarom    
130aec3c8f4Simarom    _check_rc(rc)
131aec3c8f4Simarom    return msg
132aec3c8f4Simarom
133aec3c8f4Simaromcdef inline object _recv_copy(void *handle, int flags=0):
134aec3c8f4Simarom    """Receive a message and return a copy"""
135aec3c8f4Simarom    cdef zmq_msg_t zmq_msg
136aec3c8f4Simarom    with nogil:
137aec3c8f4Simarom        zmq_msg_init (&zmq_msg)
138aec3c8f4Simarom        rc = zmq_msg_recv(&zmq_msg, handle, flags)
139aec3c8f4Simarom    _check_rc(rc)
140aec3c8f4Simarom    msg_bytes = copy_zmq_msg_bytes(&zmq_msg)
141aec3c8f4Simarom    zmq_msg_close(&zmq_msg)
142aec3c8f4Simarom    return msg_bytes
143aec3c8f4Simarom
144aec3c8f4Simaromcdef inline object _send_frame(void *handle, Frame msg, int flags=0):
145aec3c8f4Simarom    """Send a Frame on this socket in a non-copy manner."""
146aec3c8f4Simarom    cdef int rc
147aec3c8f4Simarom    cdef Frame msg_copy
148aec3c8f4Simarom
149aec3c8f4Simarom    # Always copy so the original message isn't garbage collected.
150aec3c8f4Simarom    # This doesn't do a real copy, just a reference.
151aec3c8f4Simarom    msg_copy = msg.fast_copy()
152aec3c8f4Simarom
153aec3c8f4Simarom    with nogil:
154aec3c8f4Simarom        rc = zmq_msg_send(&msg_copy.zmq_msg, handle, flags)
155aec3c8f4Simarom
156aec3c8f4Simarom    _check_rc(rc)
157aec3c8f4Simarom    return msg.tracker
158aec3c8f4Simarom
159aec3c8f4Simarom
160aec3c8f4Simaromcdef inline object _send_copy(void *handle, object msg, int flags=0):
161aec3c8f4Simarom    """Send a message on this socket by copying its content."""
162aec3c8f4Simarom    cdef int rc, rc2
163aec3c8f4Simarom    cdef zmq_msg_t data
164aec3c8f4Simarom    cdef char *msg_c
165aec3c8f4Simarom    cdef Py_ssize_t msg_c_len=0
166aec3c8f4Simarom
167aec3c8f4Simarom    # copy to c array:
168aec3c8f4Simarom    asbuffer_r(msg, <void **>&msg_c, &msg_c_len)
169aec3c8f4Simarom
170aec3c8f4Simarom    # Copy the msg before sending. This avoids any complications with
171aec3c8f4Simarom    # the GIL, etc.
172aec3c8f4Simarom    # If zmq_msg_init_* fails we must not call zmq_msg_close (Bus Error)
173aec3c8f4Simarom    rc = zmq_msg_init_size(&data, msg_c_len)
174aec3c8f4Simarom
175aec3c8f4Simarom    _check_rc(rc)
176aec3c8f4Simarom
177aec3c8f4Simarom    with nogil:
178aec3c8f4Simarom        memcpy(zmq_msg_data(&data), msg_c, zmq_msg_size(&data))
179aec3c8f4Simarom        rc = zmq_msg_send(&data, handle, flags)
180aec3c8f4Simarom        rc2 = zmq_msg_close(&data)
181aec3c8f4Simarom    _check_rc(rc)
182aec3c8f4Simarom    _check_rc(rc2)
183aec3c8f4Simarom
184aec3c8f4Simarom
185aec3c8f4Simaromcdef class Socket:
186aec3c8f4Simarom    """Socket(context, socket_type)
187aec3c8f4Simarom
188aec3c8f4Simarom    A 0MQ socket.
189aec3c8f4Simarom
190aec3c8f4Simarom    These objects will generally be constructed via the socket() method of a Context object.
191aec3c8f4Simarom    
192aec3c8f4Simarom    Note: 0MQ Sockets are *not* threadsafe. **DO NOT** share them across threads.
193aec3c8f4Simarom    
194aec3c8f4Simarom    Parameters
195aec3c8f4Simarom    ----------
196aec3c8f4Simarom    context : Context
197aec3c8f4Simarom        The 0MQ Context this Socket belongs to.
198aec3c8f4Simarom    socket_type : int
199aec3c8f4Simarom        The socket type, which can be any of the 0MQ socket types: 
200aec3c8f4Simarom        REQ, REP, PUB, SUB, PAIR, DEALER, ROUTER, PULL, PUSH, XPUB, XSUB.
201aec3c8f4Simarom    
202aec3c8f4Simarom    See Also
203aec3c8f4Simarom    --------
204aec3c8f4Simarom    .Context.socket : method for creating a socket bound to a Context.
205aec3c8f4Simarom    """
206aec3c8f4Simarom    
207aec3c8f4Simarom    # no-op for the signature
208aec3c8f4Simarom    def __init__(self, context=None, socket_type=-1, shadow=0):
209aec3c8f4Simarom        pass
210aec3c8f4Simarom    
211aec3c8f4Simarom    def __cinit__(self, Context context=None, int socket_type=-1, size_t shadow=0, *args, **kwargs):
212aec3c8f4Simarom        cdef Py_ssize_t c_handle
213aec3c8f4Simarom
214aec3c8f4Simarom        self.handle = NULL
215aec3c8f4Simarom        self.context = context
216aec3c8f4Simarom        if shadow:
217aec3c8f4Simarom            self._shadow = True
218aec3c8f4Simarom            self.handle = <void *>shadow
219aec3c8f4Simarom        else:
220aec3c8f4Simarom            if context is None:
221aec3c8f4Simarom                raise TypeError("context must be specified")
222aec3c8f4Simarom            if socket_type < 0:
223aec3c8f4Simarom                raise TypeError("socket_type must be specified")
224aec3c8f4Simarom            self._shadow = False
225aec3c8f4Simarom            self.handle = zmq_socket(context.handle, socket_type)
226aec3c8f4Simarom        if self.handle == NULL:
227aec3c8f4Simarom            raise ZMQError()
228aec3c8f4Simarom        self._closed = False
229aec3c8f4Simarom        self._pid = getpid()
230aec3c8f4Simarom        if context:
231aec3c8f4Simarom            context._add_socket(self.handle)
232aec3c8f4Simarom
233aec3c8f4Simarom    def __dealloc__(self):
234aec3c8f4Simarom        """remove from context's list
235aec3c8f4Simarom        
236aec3c8f4Simarom        But be careful that context might not exist if called during gc
237aec3c8f4Simarom        """
238aec3c8f4Simarom        if self.handle != NULL and not self._shadow and getpid() == self._pid:
239aec3c8f4Simarom            # during gc, self.context might be NULL
240aec3c8f4Simarom            if self.context and not self.context.closed:
241aec3c8f4Simarom                self.context._remove_socket(self.handle)
242aec3c8f4Simarom    
243aec3c8f4Simarom    @property
244aec3c8f4Simarom    def underlying(self):
245aec3c8f4Simarom        """The address of the underlying libzmq socket"""
246aec3c8f4Simarom        return <size_t> self.handle
247aec3c8f4Simarom    
248aec3c8f4Simarom    @property
249aec3c8f4Simarom    def closed(self):
250aec3c8f4Simarom        return _check_closed_deep(self)
251aec3c8f4Simarom    
252aec3c8f4Simarom    def close(self, linger=None):
253aec3c8f4Simarom        """s.close(linger=None)
254aec3c8f4Simarom
255aec3c8f4Simarom        Close the socket.
256aec3c8f4Simarom        
257aec3c8f4Simarom        If linger is specified, LINGER sockopt will be set prior to closing.
258aec3c8f4Simarom
259aec3c8f4Simarom        This can be called to close the socket by hand. If this is not
260aec3c8f4Simarom        called, the socket will automatically be closed when it is
261aec3c8f4Simarom        garbage collected.
262aec3c8f4Simarom        """
263aec3c8f4Simarom        cdef int rc=0
264aec3c8f4Simarom        cdef int linger_c
265aec3c8f4Simarom        cdef bint setlinger=False
266aec3c8f4Simarom        
267aec3c8f4Simarom        if linger is not None:
268aec3c8f4Simarom            linger_c = linger
269aec3c8f4Simarom            setlinger=True
270aec3c8f4Simarom        
271aec3c8f4Simarom        if self.handle != NULL and not self._closed and getpid() == self._pid:
272aec3c8f4Simarom            if setlinger:
273aec3c8f4Simarom                zmq_setsockopt(self.handle, ZMQ_LINGER, &linger_c, sizeof(int))
274aec3c8f4Simarom            rc = zmq_close(self.handle)
275aec3c8f4Simarom            if rc != 0 and zmq_errno() != ENOTSOCK:
276aec3c8f4Simarom                # ignore ENOTSOCK (closed by Context)
277aec3c8f4Simarom                _check_rc(rc)
278aec3c8f4Simarom            self._closed = True
279aec3c8f4Simarom            # during gc, self.context might be NULL
280aec3c8f4Simarom            if self.context:
281aec3c8f4Simarom                self.context._remove_socket(self.handle)
282aec3c8f4Simarom            self.handle = NULL
283aec3c8f4Simarom
284aec3c8f4Simarom    def set(self, int option, optval):
285aec3c8f4Simarom        """s.set(option, optval)
286aec3c8f4Simarom
287aec3c8f4Simarom        Set socket options.
288aec3c8f4Simarom
289aec3c8f4Simarom        See the 0MQ API documentation for details on specific options.
290aec3c8f4Simarom
291aec3c8f4Simarom        Parameters
292aec3c8f4Simarom        ----------
293aec3c8f4Simarom        option : int
294aec3c8f4Simarom            The option to set.  Available values will depend on your
295aec3c8f4Simarom            version of libzmq.  Examples include::
296aec3c8f4Simarom            
297aec3c8f4Simarom                zmq.SUBSCRIBE, UNSUBSCRIBE, IDENTITY, HWM, LINGER, FD
298aec3c8f4Simarom        
299aec3c8f4Simarom        optval : int or bytes
300aec3c8f4Simarom            The value of the option to set.
301aec3c8f4Simarom        """
302aec3c8f4Simarom        cdef int64_t optval_int64_c
303aec3c8f4Simarom        cdef int optval_int_c
304aec3c8f4Simarom        cdef int rc
305aec3c8f4Simarom        cdef char* optval_c
306aec3c8f4Simarom        cdef Py_ssize_t sz
307aec3c8f4Simarom
308aec3c8f4Simarom        _check_closed(self)
309aec3c8f4Simarom        if isinstance(optval, unicode):
310aec3c8f4Simarom            raise TypeError("unicode not allowed, use setsockopt_string")
311aec3c8f4Simarom
312aec3c8f4Simarom        if option in zmq.constants.bytes_sockopts:
313aec3c8f4Simarom            if not isinstance(optval, bytes):
314aec3c8f4Simarom                raise TypeError('expected bytes, got: %r' % optval)
315aec3c8f4Simarom            optval_c = PyBytes_AsString(optval)
316aec3c8f4Simarom            sz = PyBytes_Size(optval)
317aec3c8f4Simarom            rc = zmq_setsockopt(
318aec3c8f4Simarom                    self.handle, option,
319aec3c8f4Simarom                    optval_c, sz
320aec3c8f4Simarom                )
321aec3c8f4Simarom        elif option in zmq.constants.int64_sockopts:
322aec3c8f4Simarom            if not isinstance(optval, int):
323aec3c8f4Simarom                raise TypeError('expected int, got: %r' % optval)
324aec3c8f4Simarom            optval_int64_c = optval
325aec3c8f4Simarom            rc = zmq_setsockopt(
326aec3c8f4Simarom                    self.handle, option,
327aec3c8f4Simarom                    &optval_int64_c, sizeof(int64_t)
328aec3c8f4Simarom                )
329aec3c8f4Simarom        else:
330aec3c8f4Simarom            # default is to assume int, which is what most new sockopts will be
331aec3c8f4Simarom            # this lets pyzmq work with newer libzmq which may add constants
332aec3c8f4Simarom            # pyzmq has not yet added, rather than artificially raising. Invalid
333aec3c8f4Simarom            # sockopts will still raise just the same, but it will be libzmq doing
334aec3c8f4Simarom            # the raising.
335aec3c8f4Simarom            if not isinstance(optval, int):
336aec3c8f4Simarom                raise TypeError('expected int, got: %r' % optval)
337aec3c8f4Simarom            optval_int_c = optval
338aec3c8f4Simarom            rc = zmq_setsockopt(
339aec3c8f4Simarom                    self.handle, option,
340aec3c8f4Simarom                    &optval_int_c, sizeof(int)
341aec3c8f4Simarom                )
342aec3c8f4Simarom
343aec3c8f4Simarom        _check_rc(rc)
344aec3c8f4Simarom
345aec3c8f4Simarom    def get(self, int option):
346aec3c8f4Simarom        """s.get(option)
347aec3c8f4Simarom
348aec3c8f4Simarom        Get the value of a socket option.
349aec3c8f4Simarom
350aec3c8f4Simarom        See the 0MQ API documentation for details on specific options.
351aec3c8f4Simarom
352aec3c8f4Simarom        Parameters
353aec3c8f4Simarom        ----------
354aec3c8f4Simarom        option : int
355aec3c8f4Simarom            The option to get.  Available values will depend on your
356aec3c8f4Simarom            version of libzmq.  Examples include::
357aec3c8f4Simarom            
358aec3c8f4Simarom                zmq.IDENTITY, HWM, LINGER, FD, EVENTS
359aec3c8f4Simarom
360aec3c8f4Simarom        Returns
361aec3c8f4Simarom        -------
362aec3c8f4Simarom        optval : int or bytes
363aec3c8f4Simarom            The value of the option as a bytestring or int.
364aec3c8f4Simarom        """
365aec3c8f4Simarom        cdef int64_t optval_int64_c
366aec3c8f4Simarom        cdef int optval_int_c
367aec3c8f4Simarom        cdef fd_t optval_fd_c
368aec3c8f4Simarom        cdef char identity_str_c [255]
369aec3c8f4Simarom        cdef size_t sz
370aec3c8f4Simarom        cdef int rc
371aec3c8f4Simarom
372aec3c8f4Simarom        _check_closed(self)
373aec3c8f4Simarom
374aec3c8f4Simarom        if option in zmq.constants.bytes_sockopts:
375aec3c8f4Simarom            sz = 255
376aec3c8f4Simarom            rc = zmq_getsockopt(self.handle, option, <void *>identity_str_c, &sz)
377aec3c8f4Simarom            _check_rc(rc)
378aec3c8f4Simarom            # strip null-terminated strings *except* identity
379aec3c8f4Simarom            if option != ZMQ_IDENTITY and sz > 0 and (<char *>identity_str_c)[sz-1] == b'\0':
380aec3c8f4Simarom                sz -= 1
381aec3c8f4Simarom            result = PyBytes_FromStringAndSize(<char *>identity_str_c, sz)
382aec3c8f4Simarom        elif option in zmq.constants.int64_sockopts:
383aec3c8f4Simarom            sz = sizeof(int64_t)
384aec3c8f4Simarom            rc = zmq_getsockopt(self.handle, option, <void *>&optval_int64_c, &sz)
385aec3c8f4Simarom            _check_rc(rc)
386aec3c8f4Simarom            result = optval_int64_c
387aec3c8f4Simarom        elif option in zmq.constants.fd_sockopts:
388aec3c8f4Simarom            sz = sizeof(fd_t)
389aec3c8f4Simarom            rc = zmq_getsockopt(self.handle, option, <void *>&optval_fd_c, &sz)
390aec3c8f4Simarom            _check_rc(rc)
391aec3c8f4Simarom            result = optval_fd_c
392aec3c8f4Simarom        else:
393aec3c8f4Simarom            # default is to assume int, which is what most new sockopts will be
394aec3c8f4Simarom            # this lets pyzmq work with newer libzmq which may add constants
395aec3c8f4Simarom            # pyzmq has not yet added, rather than artificially raising. Invalid
396aec3c8f4Simarom            # sockopts will still raise just the same, but it will be libzmq doing
397aec3c8f4Simarom            # the raising.
398aec3c8f4Simarom            sz = sizeof(int)
399aec3c8f4Simarom            rc = zmq_getsockopt(self.handle, option, <void *>&optval_int_c, &sz)
400aec3c8f4Simarom            _check_rc(rc)
401aec3c8f4Simarom            result = optval_int_c
402aec3c8f4Simarom
403aec3c8f4Simarom        return result
404aec3c8f4Simarom    
405aec3c8f4Simarom    def bind(self, addr):
406aec3c8f4Simarom        """s.bind(addr)
407aec3c8f4Simarom
408aec3c8f4Simarom        Bind the socket to an address.
409aec3c8f4Simarom
410aec3c8f4Simarom        This causes the socket to listen on a network port. Sockets on the
411aec3c8f4Simarom        other side of this connection will use ``Socket.connect(addr)`` to
412aec3c8f4Simarom        connect to this socket.
413aec3c8f4Simarom
414aec3c8f4Simarom        Parameters
415aec3c8f4Simarom        ----------
416aec3c8f4Simarom        addr : str
417aec3c8f4Simarom            The address string. This has the form 'protocol://interface:port',
418aec3c8f4Simarom            for example 'tcp://127.0.0.1:5555'. Protocols supported include
419aec3c8f4Simarom            tcp, udp, pgm, epgm, inproc and ipc. If the address is unicode, it is
420aec3c8f4Simarom            encoded to utf-8 first.
421aec3c8f4Simarom        """
422aec3c8f4Simarom        cdef int rc
423aec3c8f4Simarom        cdef char* c_addr
424aec3c8f4Simarom
425aec3c8f4Simarom        _check_closed(self)
426aec3c8f4Simarom        if isinstance(addr, unicode):
427aec3c8f4Simarom            addr = addr.encode('utf-8')
428aec3c8f4Simarom        if not isinstance(addr, bytes):
429aec3c8f4Simarom            raise TypeError('expected str, got: %r' % addr)
430aec3c8f4Simarom        c_addr = addr
431aec3c8f4Simarom        rc = zmq_bind(self.handle, c_addr)
432aec3c8f4Simarom        if rc != 0:
433aec3c8f4Simarom            if IPC_PATH_MAX_LEN and zmq_errno() == ENAMETOOLONG:
434aec3c8f4Simarom                # py3compat: addr is bytes, but msg wants str
435aec3c8f4Simarom                if str is unicode:
436aec3c8f4Simarom                    addr = addr.decode('utf-8', 'replace')
437aec3c8f4Simarom                path = addr.split('://', 1)[-1]
438aec3c8f4Simarom                msg = ('ipc path "{0}" is longer than {1} '
439aec3c8f4Simarom                                'characters (sizeof(sockaddr_un.sun_path)). '
440aec3c8f4Simarom                                'zmq.IPC_PATH_MAX_LEN constant can be used '
441aec3c8f4Simarom                                'to check addr length (if it is defined).'
442aec3c8f4Simarom                                .format(path, IPC_PATH_MAX_LEN))
443aec3c8f4Simarom                raise ZMQError(msg=msg)
444aec3c8f4Simarom        _check_rc(rc)
445aec3c8f4Simarom
446aec3c8f4Simarom    def connect(self, addr):
447aec3c8f4Simarom        """s.connect(addr)
448aec3c8f4Simarom
449aec3c8f4Simarom        Connect to a remote 0MQ socket.
450aec3c8f4Simarom
451aec3c8f4Simarom        Parameters
452aec3c8f4Simarom        ----------
453aec3c8f4Simarom        addr : str
454aec3c8f4Simarom            The address string. This has the form 'protocol://interface:port',
455aec3c8f4Simarom            for example 'tcp://127.0.0.1:5555'. Protocols supported are
456aec3c8f4Simarom            tcp, upd, pgm, inproc and ipc. If the address is unicode, it is
457aec3c8f4Simarom            encoded to utf-8 first.
458aec3c8f4Simarom        """
459aec3c8f4Simarom        cdef int rc
460aec3c8f4Simarom        cdef char* c_addr
461aec3c8f4Simarom
462aec3c8f4Simarom        _check_closed(self)
463aec3c8f4Simarom        if isinstance(addr, unicode):
464aec3c8f4Simarom            addr = addr.encode('utf-8')
465aec3c8f4Simarom        if not isinstance(addr, bytes):
466aec3c8f4Simarom            raise TypeError('expected str, got: %r' % addr)
467aec3c8f4Simarom        c_addr = addr
468aec3c8f4Simarom        
469aec3c8f4Simarom        rc = zmq_connect(self.handle, c_addr)
470aec3c8f4Simarom        if rc != 0:
471aec3c8f4Simarom            raise ZMQError()
472aec3c8f4Simarom
473aec3c8f4Simarom    def unbind(self, addr):
474aec3c8f4Simarom        """s.unbind(addr)
475aec3c8f4Simarom        
476aec3c8f4Simarom        Unbind from an address (undoes a call to bind).
477aec3c8f4Simarom        
478aec3c8f4Simarom        .. versionadded:: libzmq-3.2
479aec3c8f4Simarom        .. versionadded:: 13.0
480aec3c8f4Simarom
481aec3c8f4Simarom        Parameters
482aec3c8f4Simarom        ----------
483aec3c8f4Simarom        addr : str
484aec3c8f4Simarom            The address string. This has the form 'protocol://interface:port',
485aec3c8f4Simarom            for example 'tcp://127.0.0.1:5555'. Protocols supported are
486aec3c8f4Simarom            tcp, upd, pgm, inproc and ipc. If the address is unicode, it is
487aec3c8f4Simarom            encoded to utf-8 first.
488aec3c8f4Simarom        """
489aec3c8f4Simarom        cdef int rc
490aec3c8f4Simarom        cdef char* c_addr
491aec3c8f4Simarom
492aec3c8f4Simarom        _check_version((3,2), "unbind")
493aec3c8f4Simarom        _check_closed(self)
494aec3c8f4Simarom        if isinstance(addr, unicode):
495aec3c8f4Simarom            addr = addr.encode('utf-8')
496aec3c8f4Simarom        if not isinstance(addr, bytes):
497aec3c8f4Simarom            raise TypeError('expected str, got: %r' % addr)
498aec3c8f4Simarom        c_addr = addr
499aec3c8f4Simarom        
500aec3c8f4Simarom        rc = zmq_unbind(self.handle, c_addr)
501aec3c8f4Simarom        if rc != 0:
502aec3c8f4Simarom            raise ZMQError()
503aec3c8f4Simarom
504aec3c8f4Simarom    def disconnect(self, addr):
505aec3c8f4Simarom        """s.disconnect(addr)
506aec3c8f4Simarom
507aec3c8f4Simarom        Disconnect from a remote 0MQ socket (undoes a call to connect).
508aec3c8f4Simarom        
509aec3c8f4Simarom        .. versionadded:: libzmq-3.2
510aec3c8f4Simarom        .. versionadded:: 13.0
511aec3c8f4Simarom
512aec3c8f4Simarom        Parameters
513aec3c8f4Simarom        ----------
514aec3c8f4Simarom        addr : str
515aec3c8f4Simarom            The address string. This has the form 'protocol://interface:port',
516aec3c8f4Simarom            for example 'tcp://127.0.0.1:5555'. Protocols supported are
517aec3c8f4Simarom            tcp, upd, pgm, inproc and ipc. If the address is unicode, it is
518aec3c8f4Simarom            encoded to utf-8 first.
519aec3c8f4Simarom        """
520aec3c8f4Simarom        cdef int rc
521aec3c8f4Simarom        cdef char* c_addr
522aec3c8f4Simarom        
523aec3c8f4Simarom        _check_version((3,2), "disconnect")
524aec3c8f4Simarom        _check_closed(self)
525aec3c8f4Simarom        if isinstance(addr, unicode):
526aec3c8f4Simarom            addr = addr.encode('utf-8')
527aec3c8f4Simarom        if not isinstance(addr, bytes):
528aec3c8f4Simarom            raise TypeError('expected str, got: %r' % addr)
529aec3c8f4Simarom        c_addr = addr
530aec3c8f4Simarom        
531aec3c8f4Simarom        rc = zmq_disconnect(self.handle, c_addr)
532aec3c8f4Simarom        if rc != 0:
533aec3c8f4Simarom            raise ZMQError()
534aec3c8f4Simarom
535aec3c8f4Simarom    def monitor(self, addr, int events=ZMQ_EVENT_ALL):
536aec3c8f4Simarom        """s.monitor(addr, flags)
537aec3c8f4Simarom
538aec3c8f4Simarom        Start publishing socket events on inproc.
539aec3c8f4Simarom        See libzmq docs for zmq_monitor for details.
540aec3c8f4Simarom        
541aec3c8f4Simarom        While this function is available from libzmq 3.2,
542aec3c8f4Simarom        pyzmq cannot parse monitor messages from libzmq prior to 4.0.
543aec3c8f4Simarom        
544aec3c8f4Simarom        .. versionadded: libzmq-3.2
545aec3c8f4Simarom        .. versionadded: 14.0
546aec3c8f4Simarom        
547aec3c8f4Simarom        Parameters
548aec3c8f4Simarom        ----------
549aec3c8f4Simarom        addr : str
550aec3c8f4Simarom            The inproc url used for monitoring. Passing None as
551aec3c8f4Simarom            the addr will cause an existing socket monitor to be
552aec3c8f4Simarom            deregistered.
553aec3c8f4Simarom        events : int [default: zmq.EVENT_ALL]
554aec3c8f4Simarom            The zmq event bitmask for which events will be sent to the monitor.
555aec3c8f4Simarom        """
556aec3c8f4Simarom        cdef int rc, c_flags
557aec3c8f4Simarom        cdef char* c_addr = NULL
558aec3c8f4Simarom        
559aec3c8f4Simarom        _check_version((3,2), "monitor")
560aec3c8f4Simarom        if addr is not None:
561aec3c8f4Simarom            if isinstance(addr, unicode):
562aec3c8f4Simarom                addr = addr.encode('utf-8')
563aec3c8f4Simarom            if not isinstance(addr, bytes):
564aec3c8f4Simarom                raise TypeError('expected str, got: %r' % addr)
565aec3c8f4Simarom            c_addr = addr
566aec3c8f4Simarom        c_flags = events
567aec3c8f4Simarom        rc = zmq_socket_monitor(self.handle, c_addr, c_flags)
568aec3c8f4Simarom        _check_rc(rc)
569aec3c8f4Simarom
570aec3c8f4Simarom    #-------------------------------------------------------------------------
571aec3c8f4Simarom    # Sending and receiving messages
572aec3c8f4Simarom    #-------------------------------------------------------------------------
573aec3c8f4Simarom
574aec3c8f4Simarom    cpdef object send(self, object data, int flags=0, copy=True, track=False):
575aec3c8f4Simarom        """s.send(data, flags=0, copy=True, track=False)
576aec3c8f4Simarom
577aec3c8f4Simarom        Send a message on this socket.
578aec3c8f4Simarom
579aec3c8f4Simarom        This queues the message to be sent by the IO thread at a later time.
580aec3c8f4Simarom
581aec3c8f4Simarom        Parameters
582aec3c8f4Simarom        ----------
583aec3c8f4Simarom        data : object, str, Frame
584aec3c8f4Simarom            The content of the message.
585aec3c8f4Simarom        flags : int
586aec3c8f4Simarom            Any supported flag: NOBLOCK, SNDMORE.
587aec3c8f4Simarom        copy : bool
588aec3c8f4Simarom            Should the message be sent in a copying or non-copying manner.
589aec3c8f4Simarom        track : bool
590aec3c8f4Simarom            Should the message be tracked for notification that ZMQ has
591aec3c8f4Simarom            finished with it? (ignored if copy=True)
592aec3c8f4Simarom
593aec3c8f4Simarom        Returns
594aec3c8f4Simarom        -------
595aec3c8f4Simarom        None : if `copy` or not track
596aec3c8f4Simarom            None if message was sent, raises an exception otherwise.
597aec3c8f4Simarom        MessageTracker : if track and not copy
598aec3c8f4Simarom            a MessageTracker object, whose `pending` property will
599aec3c8f4Simarom            be True until the send is completed.
600aec3c8f4Simarom        
601aec3c8f4Simarom        Raises
602aec3c8f4Simarom        ------
603aec3c8f4Simarom        TypeError
604aec3c8f4Simarom            If a unicode object is passed
605aec3c8f4Simarom        ValueError
606aec3c8f4Simarom            If `track=True`, but an untracked Frame is passed.
607aec3c8f4Simarom        ZMQError
608aec3c8f4Simarom            If the send does not succeed for any reason.
609aec3c8f4Simarom        
610aec3c8f4Simarom        """
611aec3c8f4Simarom        _check_closed(self)
612aec3c8f4Simarom        
613aec3c8f4Simarom        if isinstance(data, unicode):
614aec3c8f4Simarom            raise TypeError("unicode not allowed, use send_string")
615aec3c8f4Simarom        
616aec3c8f4Simarom        if copy:
617aec3c8f4Simarom            # msg.bytes never returns the input data object
618aec3c8f4Simarom            # it is always a copy, but always the same copy
619aec3c8f4Simarom            if isinstance(data, Frame):
620aec3c8f4Simarom                data = data.buffer
621aec3c8f4Simarom            return _send_copy(self.handle, data, flags)
622aec3c8f4Simarom        else:
623aec3c8f4Simarom            if isinstance(data, Frame):
624aec3c8f4Simarom                if track and not data.tracker:
625aec3c8f4Simarom                    raise ValueError('Not a tracked message')
626aec3c8f4Simarom                msg = data
627aec3c8f4Simarom            else:
628aec3c8f4Simarom                msg = Frame(data, track=track)
629aec3c8f4Simarom            return _send_frame(self.handle, msg, flags)
630aec3c8f4Simarom
631aec3c8f4Simarom    cpdef object recv(self, int flags=0, copy=True, track=False):
632aec3c8f4Simarom        """s.recv(flags=0, copy=True, track=False)
633aec3c8f4Simarom
634aec3c8f4Simarom        Receive a message.
635aec3c8f4Simarom
636aec3c8f4Simarom        Parameters
637aec3c8f4Simarom        ----------
638aec3c8f4Simarom        flags : int
639aec3c8f4Simarom            Any supported flag: NOBLOCK. If NOBLOCK is set, this method
640aec3c8f4Simarom            will raise a ZMQError with EAGAIN if a message is not ready.
641aec3c8f4Simarom            If NOBLOCK is not set, then this method will block until a
642aec3c8f4Simarom            message arrives.
643aec3c8f4Simarom        copy : bool
644aec3c8f4Simarom            Should the message be received in a copying or non-copying manner?
645aec3c8f4Simarom            If False a Frame object is returned, if True a string copy of
646aec3c8f4Simarom            message is returned.
647aec3c8f4Simarom        track : bool
648aec3c8f4Simarom            Should the message be tracked for notification that ZMQ has
649aec3c8f4Simarom            finished with it? (ignored if copy=True)
650aec3c8f4Simarom
651aec3c8f4Simarom        Returns
652aec3c8f4Simarom        -------
653aec3c8f4Simarom        msg : bytes, Frame
654aec3c8f4Simarom            The received message frame.  If `copy` is False, then it will be a Frame,
655aec3c8f4Simarom            otherwise it will be bytes.
656aec3c8f4Simarom            
657aec3c8f4Simarom        Raises
658aec3c8f4Simarom        ------
659aec3c8f4Simarom        ZMQError
660aec3c8f4Simarom            for any of the reasons zmq_msg_recv might fail.
661aec3c8f4Simarom        """
662aec3c8f4Simarom        _check_closed(self)
663aec3c8f4Simarom        
664aec3c8f4Simarom        if copy:
665aec3c8f4Simarom            return _recv_copy(self.handle, flags)
666aec3c8f4Simarom        else:
667aec3c8f4Simarom            frame = _recv_frame(self.handle, flags, track)
668aec3c8f4Simarom            frame.more = self.getsockopt(zmq.RCVMORE)
669aec3c8f4Simarom            return frame
670aec3c8f4Simarom    
671aec3c8f4Simarom
672aec3c8f4Simarom__all__ = ['Socket', 'IPC_PATH_MAX_LEN']
673