PageRenderTime 93ms CodeModel.GetById 2ms app.highlight 79ms RepoModel.GetById 1ms app.codeStats 1ms

/src/lib.rs

http://github.com/erickt/rust-zmq
Rust | 1317 lines | 875 code | 138 blank | 304 comment | 42 complexity | 7008ff52ad3ed40805e07893698a564c MD5 | raw file
   1//! Module: zmq
   2
   3#![allow(trivial_numeric_casts)]
   4
   5use bitflags::bitflags;
   6use libc::{c_int, c_long, c_short};
   7
   8use std::ffi;
   9use std::fmt;
  10use std::marker::PhantomData;
  11use std::os::raw::c_void;
  12use std::result;
  13use std::string::FromUtf8Error;
  14use std::sync::Arc;
  15use std::{mem, ptr, str};
  16
  17use zmq_sys::{errno, RawFd};
  18
  19macro_rules! zmq_try {
  20    ($($tt:tt)*) => {{
  21        let rc = $($tt)*;
  22        if rc == -1 {
  23            return Err(crate::errno_to_error());
  24        }
  25        rc
  26    }}
  27}
  28
  29mod message;
  30mod sockopt;
  31
  32use crate::message::msg_ptr;
  33pub use crate::message::Message;
  34pub use crate::SocketType::*;
  35
  36/// `zmq`-specific Result type.
  37pub type Result<T> = result::Result<T, Error>;
  38
  39/// Socket types
  40#[allow(non_camel_case_types)]
  41#[derive(Clone, Copy, Debug, PartialEq)]
  42pub enum SocketType {
  43    PAIR,
  44    PUB,
  45    SUB,
  46    REQ,
  47    REP,
  48    DEALER,
  49    ROUTER,
  50    PULL,
  51    PUSH,
  52    XPUB,
  53    XSUB,
  54    STREAM,
  55}
  56
  57impl SocketType {
  58    fn to_raw(self) -> c_int {
  59        let raw = match self {
  60            PAIR => zmq_sys::ZMQ_PAIR,
  61            PUB => zmq_sys::ZMQ_PUB,
  62            SUB => zmq_sys::ZMQ_SUB,
  63            REQ => zmq_sys::ZMQ_REQ,
  64            REP => zmq_sys::ZMQ_REP,
  65            DEALER => zmq_sys::ZMQ_DEALER,
  66            ROUTER => zmq_sys::ZMQ_ROUTER,
  67            PULL => zmq_sys::ZMQ_PULL,
  68            PUSH => zmq_sys::ZMQ_PUSH,
  69            XPUB => zmq_sys::ZMQ_XPUB,
  70            XSUB => zmq_sys::ZMQ_XSUB,
  71            STREAM => zmq_sys::ZMQ_STREAM,
  72        };
  73        raw as c_int
  74    }
  75    fn from_raw(raw: c_int) -> SocketType {
  76        match raw as u32 {
  77            zmq_sys::ZMQ_PAIR => PAIR,
  78            zmq_sys::ZMQ_PUB => PUB,
  79            zmq_sys::ZMQ_SUB => SUB,
  80            zmq_sys::ZMQ_REQ => REQ,
  81            zmq_sys::ZMQ_REP => REP,
  82            zmq_sys::ZMQ_DEALER => DEALER,
  83            zmq_sys::ZMQ_ROUTER => ROUTER,
  84            zmq_sys::ZMQ_PULL => PULL,
  85            zmq_sys::ZMQ_PUSH => PUSH,
  86            zmq_sys::ZMQ_XPUB => XPUB,
  87            zmq_sys::ZMQ_XSUB => XSUB,
  88            zmq_sys::ZMQ_STREAM => STREAM,
  89            _ => panic!("socket type is out of range!"),
  90        }
  91    }
  92}
  93
  94/// Socket Events
  95#[allow(non_camel_case_types)]
  96#[derive(Clone, Copy, Debug, PartialEq)]
  97pub enum SocketEvent {
  98    // TODO: This should become a proper enum, including the data.
  99    CONNECTED = zmq_sys::ZMQ_EVENT_CONNECTED as isize,
 100    CONNECT_DELAYED = zmq_sys::ZMQ_EVENT_CONNECT_DELAYED as isize,
 101    CONNECT_RETRIED = zmq_sys::ZMQ_EVENT_CONNECT_RETRIED as isize,
 102    LISTENING = zmq_sys::ZMQ_EVENT_LISTENING as isize,
 103    BIND_FAILED = zmq_sys::ZMQ_EVENT_BIND_FAILED as isize,
 104    ACCEPTED = zmq_sys::ZMQ_EVENT_ACCEPTED as isize,
 105    ACCEPT_FAILED = zmq_sys::ZMQ_EVENT_ACCEPT_FAILED as isize,
 106    CLOSED = zmq_sys::ZMQ_EVENT_CLOSED as isize,
 107    CLOSE_FAILED = zmq_sys::ZMQ_EVENT_CLOSE_FAILED as isize,
 108    DISCONNECTED = zmq_sys::ZMQ_EVENT_DISCONNECTED as isize,
 109    MONITOR_STOPPED = zmq_sys::ZMQ_EVENT_MONITOR_STOPPED as isize,
 110    HANDSHAKE_FAILED_NO_DETAIL = zmq_sys::ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL as isize,
 111    HANDSHAKE_SUCCEEDED = zmq_sys::ZMQ_EVENT_HANDSHAKE_SUCCEEDED as isize,
 112    HANDSHAKE_FAILED_PROTOCOL = zmq_sys::ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL as isize,
 113    HANDSHAKE_FAILED_AUTH = zmq_sys::ZMQ_EVENT_HANDSHAKE_FAILED_AUTH as isize,
 114    ALL = zmq_sys::ZMQ_EVENT_ALL as isize,
 115}
 116
 117impl SocketEvent {
 118    pub fn to_raw(self) -> u16 {
 119        self as u16
 120    }
 121
 122    // TODO: this should not need to be public
 123    pub fn from_raw(raw: u16) -> SocketEvent {
 124        use SocketEvent::*;
 125        match u32::from(raw) {
 126            zmq_sys::ZMQ_EVENT_CONNECTED => CONNECTED,
 127            zmq_sys::ZMQ_EVENT_CONNECT_DELAYED => CONNECT_DELAYED,
 128            zmq_sys::ZMQ_EVENT_CONNECT_RETRIED => CONNECT_RETRIED,
 129            zmq_sys::ZMQ_EVENT_LISTENING => LISTENING,
 130            zmq_sys::ZMQ_EVENT_BIND_FAILED => BIND_FAILED,
 131            zmq_sys::ZMQ_EVENT_ACCEPTED => ACCEPTED,
 132            zmq_sys::ZMQ_EVENT_ACCEPT_FAILED => ACCEPT_FAILED,
 133            zmq_sys::ZMQ_EVENT_CLOSED => CLOSED,
 134            zmq_sys::ZMQ_EVENT_CLOSE_FAILED => CLOSE_FAILED,
 135            zmq_sys::ZMQ_EVENT_DISCONNECTED => DISCONNECTED,
 136            zmq_sys::ZMQ_EVENT_MONITOR_STOPPED => MONITOR_STOPPED,
 137            zmq_sys::ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL => HANDSHAKE_FAILED_NO_DETAIL,
 138            zmq_sys::ZMQ_EVENT_HANDSHAKE_SUCCEEDED => HANDSHAKE_SUCCEEDED,
 139            zmq_sys::ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL => HANDSHAKE_FAILED_PROTOCOL,
 140            zmq_sys::ZMQ_EVENT_HANDSHAKE_FAILED_AUTH => HANDSHAKE_FAILED_AUTH,
 141            zmq_sys::ZMQ_EVENT_ALL => ALL,
 142            x => panic!("unknown event type {}", x),
 143        }
 144    }
 145}
 146
 147/// Flag for socket `send` methods that specifies non-blocking mode.
 148pub static DONTWAIT: i32 = zmq_sys::ZMQ_DONTWAIT as i32;
 149/// Flag for socket `send` methods that specifies that more frames of a
 150/// multipart message will follow.
 151pub static SNDMORE: i32 = zmq_sys::ZMQ_SNDMORE as i32;
 152
 153/// Security Mechanism
 154#[allow(non_camel_case_types)]
 155#[derive(Clone, Copy, Debug, PartialEq)]
 156pub enum Mechanism {
 157    // TODO: Fix the naming
 158    ZMQ_NULL,
 159    ZMQ_PLAIN,
 160    ZMQ_CURVE,
 161    ZMQ_GSSAPI,
 162}
 163
 164/// An error returned by a 0MQ API function.
 165#[derive(Clone, Copy, Eq, PartialEq)]
 166pub enum Error {
 167    EACCES,
 168    EADDRINUSE,
 169    EAGAIN,
 170    EBUSY,
 171    ECONNREFUSED,
 172    EFAULT,
 173    EINTR,
 174    EHOSTUNREACH,
 175    EINPROGRESS,
 176    EINVAL,
 177    EMFILE,
 178    EMSGSIZE,
 179    ENAMETOOLONG,
 180    ENODEV,
 181    ENOENT,
 182    ENOMEM,
 183    ENOTCONN,
 184    ENOTSOCK,
 185    EPROTO,
 186    EPROTONOSUPPORT,
 187    ENOTSUP,
 188    ENOBUFS,
 189    ENETDOWN,
 190    EADDRNOTAVAIL,
 191
 192    // native zmq error codes
 193    EFSM,
 194    ENOCOMPATPROTO,
 195    ETERM,
 196    EMTHREAD,
 197}
 198
 199impl Error {
 200    pub fn to_raw(self) -> i32 {
 201        match self {
 202            Error::EACCES => errno::EACCES,
 203            Error::EADDRINUSE => errno::EADDRINUSE,
 204            Error::EAGAIN => errno::EAGAIN,
 205            Error::EBUSY => errno::EBUSY,
 206            Error::ECONNREFUSED => errno::ECONNREFUSED,
 207            Error::EFAULT => errno::EFAULT,
 208            Error::EINTR => errno::EINTR,
 209            Error::EHOSTUNREACH => errno::EHOSTUNREACH,
 210            Error::EINPROGRESS => errno::EINPROGRESS,
 211            Error::EINVAL => errno::EINVAL,
 212            Error::EMFILE => errno::EMFILE,
 213            Error::EMSGSIZE => errno::EMSGSIZE,
 214            Error::ENAMETOOLONG => errno::ENAMETOOLONG,
 215            Error::ENODEV => errno::ENODEV,
 216            Error::ENOENT => errno::ENOENT,
 217            Error::ENOMEM => errno::ENOMEM,
 218            Error::ENOTCONN => errno::ENOTCONN,
 219            Error::ENOTSOCK => errno::ENOTSOCK,
 220            Error::EPROTO => errno::EPROTO,
 221            Error::EPROTONOSUPPORT => errno::EPROTONOSUPPORT,
 222            Error::ENOTSUP => errno::ENOTSUP,
 223            Error::ENOBUFS => errno::ENOBUFS,
 224            Error::ENETDOWN => errno::ENETDOWN,
 225            Error::EADDRNOTAVAIL => errno::EADDRNOTAVAIL,
 226
 227            Error::EFSM => errno::EFSM,
 228            Error::ENOCOMPATPROTO => errno::ENOCOMPATPROTO,
 229            Error::ETERM => errno::ETERM,
 230            Error::EMTHREAD => errno::EMTHREAD,
 231        }
 232    }
 233
 234    pub fn from_raw(raw: i32) -> Error {
 235        match raw {
 236            errno::EACCES => Error::EACCES,
 237            errno::EADDRINUSE => Error::EADDRINUSE,
 238            errno::EAGAIN => Error::EAGAIN,
 239            errno::EBUSY => Error::EBUSY,
 240            errno::ECONNREFUSED => Error::ECONNREFUSED,
 241            errno::EFAULT => Error::EFAULT,
 242            errno::EHOSTUNREACH => Error::EHOSTUNREACH,
 243            errno::EINPROGRESS => Error::EINPROGRESS,
 244            errno::EINVAL => Error::EINVAL,
 245            errno::EMFILE => Error::EMFILE,
 246            errno::EMSGSIZE => Error::EMSGSIZE,
 247            errno::ENAMETOOLONG => Error::ENAMETOOLONG,
 248            errno::ENODEV => Error::ENODEV,
 249            errno::ENOENT => Error::ENOENT,
 250            errno::ENOMEM => Error::ENOMEM,
 251            errno::ENOTCONN => Error::ENOTCONN,
 252            errno::ENOTSOCK => Error::ENOTSOCK,
 253            errno::EPROTO => Error::EPROTO,
 254            errno::EPROTONOSUPPORT => Error::EPROTONOSUPPORT,
 255            errno::ENOTSUP => Error::ENOTSUP,
 256            errno::ENOBUFS => Error::ENOBUFS,
 257            errno::ENETDOWN => Error::ENETDOWN,
 258            errno::EADDRNOTAVAIL => Error::EADDRNOTAVAIL,
 259            errno::EINTR => Error::EINTR,
 260
 261            // These may turn up on platforms that don't support these
 262            // errno codes natively (Windows)
 263            errno::ENOTSUP_ALT => Error::ENOTSUP,
 264            errno::EPROTONOSUPPORT_ALT => Error::EPROTONOSUPPORT,
 265            errno::ENOBUFS_ALT => Error::ENOBUFS,
 266            errno::ENETDOWN_ALT => Error::ENETDOWN,
 267            errno::EADDRINUSE_ALT => Error::EADDRINUSE,
 268            errno::EADDRNOTAVAIL_ALT => Error::EADDRNOTAVAIL,
 269            errno::ECONNREFUSED_ALT => Error::ECONNREFUSED,
 270            errno::EINPROGRESS_ALT => Error::EINPROGRESS,
 271            errno::ENOTSOCK_ALT => Error::ENOTSOCK,
 272            errno::EMSGSIZE_ALT => Error::EMSGSIZE,
 273
 274            // TODO: these are present in `zmq-sys`, but not handled, as that
 275            // would break backwards-compatibility for the `Error` enum.
 276
 277            // errno::EAFNOSUPPORT_ALT => Error::EAFNOSUPPORT,
 278            // errno::ENETUNREACH_ALT => Error::ENETUNREACH,
 279            // errno::ECONNABORTED_ALT => Error::ECONNABORTED,
 280            // errno::ECONNRESET_ALT => Error::ECONNRESET,
 281            // errno::ENOTCONN_ALT => Error::ENOTCONN,
 282            // errno::ETIMEDOUT_ALT => Error::ETIMEDOUT,
 283            // errno::EHOSTUNREACH_ALT => Error::EHOSTUNREACH,
 284            // errno::ENETRESET_ALT => Error::ENETRESET,
 285
 286            // 0MQ native error codes
 287            errno::EFSM => Error::EFSM,
 288            errno::ENOCOMPATPROTO => Error::ENOCOMPATPROTO,
 289            errno::ETERM => Error::ETERM,
 290            errno::EMTHREAD => Error::EMTHREAD,
 291
 292            x => unsafe {
 293                let s = zmq_sys::zmq_strerror(x);
 294                panic!(
 295                    "unknown error [{}]: {}",
 296                    x,
 297                    str::from_utf8(ffi::CStr::from_ptr(s).to_bytes()).unwrap()
 298                )
 299            },
 300        }
 301    }
 302
 303    /// Returns the error message provided by 0MQ.
 304    pub fn message(self) -> &'static str {
 305        unsafe {
 306            let s = zmq_sys::zmq_strerror(self.to_raw());
 307            let v: &'static [u8] = mem::transmute(ffi::CStr::from_ptr(s).to_bytes());
 308            str::from_utf8(v).unwrap()
 309        }
 310    }
 311}
 312
 313impl std::error::Error for Error {
 314    fn description(&self) -> &str {
 315        self.message()
 316    }
 317}
 318
 319impl std::fmt::Display for Error {
 320    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 321        write!(f, "{}", self.message())
 322    }
 323}
 324
 325impl fmt::Debug for Error {
 326    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 327        // FIXME: An unquoted string is not a good `Debug` output.
 328        write!(f, "{}", self.message())
 329    }
 330}
 331
 332impl From<Error> for std::io::Error {
 333    fn from(error: Error) -> Self {
 334        use std::io::ErrorKind;
 335
 336        let kind = match error {
 337            Error::ENOENT => ErrorKind::NotFound,
 338            Error::EACCES => ErrorKind::PermissionDenied,
 339            Error::ECONNREFUSED => ErrorKind::ConnectionRefused,
 340            Error::ENOTCONN => ErrorKind::NotConnected,
 341            Error::EADDRINUSE => ErrorKind::AddrInUse,
 342            Error::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable,
 343            Error::EAGAIN => ErrorKind::WouldBlock,
 344            Error::EINVAL => ErrorKind::InvalidInput,
 345            Error::EINTR => ErrorKind::Interrupted,
 346            _ => ErrorKind::Other,
 347        };
 348        // TODO: With rust 1.14 and up there is an optimization
 349        // opportunity using `std::io::Error: From<ErrorKind>` when
 350        // `kind != Other`. We should do that once 1.14 has been
 351        // stable for a bit.
 352        std::io::Error::new(kind, error)
 353    }
 354}
 355
 356fn errno_to_error() -> Error {
 357    Error::from_raw(unsafe { zmq_sys::zmq_errno() })
 358}
 359
 360/// Return the current zeromq version, as `(major, minor, patch)`.
 361pub fn version() -> (i32, i32, i32) {
 362    let mut major = 0;
 363    let mut minor = 0;
 364    let mut patch = 0;
 365
 366    unsafe {
 367        zmq_sys::zmq_version(&mut major, &mut minor, &mut patch);
 368    }
 369
 370    (major as i32, minor as i32, patch as i32)
 371}
 372
 373struct RawContext {
 374    ctx: *mut c_void,
 375}
 376
 377impl RawContext {
 378    fn term(&self) -> Result<()> {
 379        zmq_try!(unsafe { zmq_sys::zmq_ctx_term(self.ctx) });
 380        Ok(())
 381    }
 382}
 383
 384unsafe impl Send for RawContext {}
 385unsafe impl Sync for RawContext {}
 386
 387impl Drop for RawContext {
 388    fn drop(&mut self) {
 389        let mut e = self.term();
 390        while e == Err(Error::EINTR) {
 391            e = self.term();
 392        }
 393    }
 394}
 395
 396/// Handle for a 0MQ context, used to create sockets.
 397///
 398/// It is thread safe, and can be safely cloned and shared. Each clone
 399/// references the same underlying C context. Internally, an `Arc` is
 400/// used to implement this in a threadsafe way.
 401///
 402/// Also note that this binding deviates from the C API in that each
 403/// socket created from a context initially owns a clone of that
 404/// context. This reference is kept to avoid a potential deadlock
 405/// situation that would otherwise occur:
 406///
 407/// Destroying the underlying C context is an operation which
 408/// blocks waiting for all sockets created from it to be closed
 409/// first. If one of the sockets belongs to thread issuing the
 410/// destroy operation, you have established a deadlock.
 411///
 412/// You can still deadlock yourself (or intentionally close sockets in
 413/// other threads, see `zmq_ctx_destroy`(3)) by explicitly calling
 414/// `Context::destroy`.
 415///
 416#[derive(Clone)]
 417pub struct Context {
 418    raw: Arc<RawContext>,
 419}
 420
 421impl Context {
 422    /// Create a new reference-counted context handle.
 423    pub fn new() -> Context {
 424        Context {
 425            raw: Arc::new(RawContext {
 426                ctx: unsafe { zmq_sys::zmq_ctx_new() },
 427            }),
 428        }
 429    }
 430
 431    /// Create a new socket.
 432    ///
 433    /// Note that the returned socket keeps a an `Arc` reference to
 434    /// the context it was created from, and will keep that context
 435    /// from being dropped while being live.
 436    pub fn socket(&self, socket_type: SocketType) -> Result<Socket> {
 437        let sock = unsafe { zmq_sys::zmq_socket(self.raw.ctx, socket_type.to_raw()) };
 438
 439        if sock.is_null() {
 440            return Err(errno_to_error());
 441        }
 442
 443        Ok(Socket {
 444            sock,
 445            context: Some(self.clone()),
 446            owned: true,
 447        })
 448    }
 449
 450    /// Try to destroy the context. This is different than the destructor; the
 451    /// destructor will loop when zmq_ctx_term returns EINTR.
 452    pub fn destroy(&mut self) -> Result<()> {
 453        self.raw.term()
 454    }
 455}
 456
 457impl Default for Context {
 458    fn default() -> Self {
 459        Context::new()
 460    }
 461}
 462
 463/// A socket, the central object in 0MQ.
 464pub struct Socket {
 465    sock: *mut c_void,
 466    // The `context` field is never accessed, but implicitly does
 467    // reference counting via the `Drop` trait.
 468    #[allow(dead_code)]
 469    context: Option<Context>,
 470    owned: bool,
 471}
 472
 473unsafe impl Send for Socket {}
 474
 475impl Drop for Socket {
 476    fn drop(&mut self) {
 477        if self.owned && unsafe { zmq_sys::zmq_close(self.sock) } == -1 {
 478            panic!(errno_to_error());
 479        }
 480    }
 481}
 482
 483macro_rules! sockopt_getter {
 484    ( $(#[$meta:meta])*
 485      pub $getter:ident => $constant_name:ident as $ty:ty
 486    ) => {
 487        $(#[$meta])*
 488        pub fn $getter(&self) -> Result<$ty> {
 489            <$ty as sockopt::Getter>::get(self.sock, zmq_sys::$constant_name as c_int)
 490        }
 491    };
 492}
 493
 494macro_rules! sockopt_setter {
 495    ( $(#[$meta:meta])*
 496      pub $setter:ident => $constant_name:ident as $ty:ty
 497    ) => {
 498        $(#[$meta])*
 499        pub fn $setter(&self, value: $ty) -> Result<()> {
 500            <$ty as sockopt::Setter>::set(self.sock, zmq_sys::$constant_name as c_int, value)
 501        }
 502    };
 503}
 504
 505macro_rules! sockopt_seq {
 506    ( META { $($meta:meta)* }, ) => ();
 507    ( META { $($meta:meta)* }, $(#[$item_meta:meta])* (_, $setter:ident) => $constant_name:ident as $ty:ty,
 508      $($rest:tt)*
 509    ) => {
 510        sockopt_setter! {
 511            $(#[$meta])* $(#[$item_meta])*
 512            pub $setter => $constant_name as $ty
 513        }
 514        sockopt_seq!(META { $($meta)* }, $($rest)*);
 515    };
 516    ( META { $($meta:meta)* }, $(#[$item_meta:meta])* ($getter:ident) => $constant_name:ident as $ty:ty,
 517      $($rest:tt)*
 518    ) => {
 519        sockopt_getter! {
 520            $(#[$meta])* $(#[$item_meta])*
 521            pub $getter => $constant_name as $ty
 522        }
 523        sockopt_seq!(META { $($meta)* }, $($rest)*);
 524    };
 525    ( META { $($meta:meta)* }, $(#[$item_meta:meta])* ($getter:ident, $setter:ident) => $constant_name:ident as $ty:ty,
 526      $($rest:tt)*
 527    ) => {
 528        sockopt_getter! {
 529            $(#[$meta])* $(#[$item_meta])*
 530            pub $getter => $constant_name as $ty
 531        }
 532        sockopt_setter! {
 533            $(#[$meta])* $(#[$item_meta])*
 534            pub $setter => $constant_name as $ty
 535        }
 536        sockopt_seq!(META { $($meta)* }, $($rest)*);
 537    };
 538}
 539
 540macro_rules! sockopts {
 541    () => ();
 542    ( $($rest:tt)* ) => {
 543        sockopt_seq!(META {}, $($rest)*);
 544    };
 545}
 546
 547/// Sendable over a `Socket`.
 548///
 549/// A type can implement this trait there is an especially efficient
 550/// implementation for sending it as a message over a zmq socket.
 551///
 552/// If the type needs to be directly passed to `Socket::send()`, but
 553/// the overhead of allocating a `Message` instance is not an issue,
 554/// `Into<Message>` should be implemented instead.
 555///
 556pub trait Sendable {
 557    fn send(self, socket: &Socket, flags: i32) -> Result<()>;
 558}
 559
 560impl<T> Sendable for T
 561where
 562    T: Into<Message>,
 563{
 564    fn send(self, socket: &Socket, flags: i32) -> Result<()> {
 565        let mut msg = self.into();
 566        zmq_try!(unsafe { zmq_sys::zmq_msg_send(msg_ptr(&mut msg), socket.sock, flags as c_int) });
 567        Ok(())
 568    }
 569}
 570
 571impl Socket {
 572    /// Consume the Socket and return the raw socket pointer.
 573    ///
 574    /// Failure to close the raw socket manually or call `from_raw`
 575    /// will lead to a memory leak. Also note that is function
 576    /// relinquishes the reference on the context is was created from.
 577    pub fn into_raw(mut self) -> *mut c_void {
 578        self.owned = false;
 579        self.sock
 580    }
 581
 582    /// Create a Socket from a raw socket pointer.
 583    ///
 584    /// The Socket assumes ownership of the pointer and will close the socket
 585    /// when it is dropped. The returned socket will not reference any context.
 586    ///
 587    /// # Safety
 588    ///
 589    /// The socket pointer must be a socket created via the `into_raw`
 590    /// method. The ownership of the socket is transferred the returned Socket,
 591    /// so any other pointers to the same socket may only be used until it is
 592    /// dropped.
 593    pub unsafe fn from_raw(sock: *mut c_void) -> Socket {
 594        Socket {
 595            sock,
 596            context: None,
 597            owned: true,
 598        }
 599    }
 600
 601    /// Return the inner pointer to this Socket.
 602    ///
 603    /// **WARNING**:
 604    /// It is your responsibility to make sure that the underlying
 605    /// memory is not freed too early.
 606    pub fn as_mut_ptr(&mut self) -> *mut c_void {
 607        self.sock
 608    }
 609
 610    /// Accept connections on a socket.
 611    pub fn bind(&self, endpoint: &str) -> Result<()> {
 612        let c_str = ffi::CString::new(endpoint.as_bytes()).unwrap();
 613        zmq_try!(unsafe { zmq_sys::zmq_bind(self.sock, c_str.as_ptr()) });
 614        Ok(())
 615    }
 616
 617    /// Stop accepting connections on a socket
 618    pub fn unbind(&self, endpoint: &str) -> Result<()> {
 619        let c_str = ffi::CString::new(endpoint.as_bytes()).unwrap();
 620        zmq_try!(unsafe { zmq_sys::zmq_unbind(self.sock, c_str.as_ptr()) });
 621        Ok(())
 622    }
 623
 624    /// Connect a socket.
 625    pub fn connect(&self, endpoint: &str) -> Result<()> {
 626        let c_str = ffi::CString::new(endpoint.as_bytes()).unwrap();
 627        zmq_try!(unsafe { zmq_sys::zmq_connect(self.sock, c_str.as_ptr()) });
 628        Ok(())
 629    }
 630
 631    /// Disconnect a previously connected socket
 632    pub fn disconnect(&self, endpoint: &str) -> Result<()> {
 633        let c_str = ffi::CString::new(endpoint.as_bytes()).unwrap();
 634        zmq_try!(unsafe { zmq_sys::zmq_disconnect(self.sock, c_str.as_ptr()) });
 635        Ok(())
 636    }
 637
 638    /// Configure the socket for monitoring
 639    pub fn monitor(&self, monitor_endpoint: &str, events: i32) -> Result<()> {
 640        let c_str = ffi::CString::new(monitor_endpoint.as_bytes()).unwrap();
 641        zmq_try!(unsafe {
 642            zmq_sys::zmq_socket_monitor(self.sock, c_str.as_ptr(), events as c_int)
 643        });
 644        Ok(())
 645    }
 646
 647    /// Send a message.
 648    ///
 649    /// Due to the provided `From` implementations, this works for
 650    /// `&[u8]`, `Vec<u8>` and `&str` `Message` itself.
 651    pub fn send<T>(&self, data: T, flags: i32) -> Result<()>
 652    where
 653        T: Sendable,
 654    {
 655        data.send(self, flags)
 656    }
 657
 658    /// Send a `Message` message.
 659    #[deprecated(since = "0.9.0", note = "Use `send` instead")]
 660    pub fn send_msg(&self, msg: Message, flags: i32) -> Result<()> {
 661        self.send(msg, flags)
 662    }
 663
 664    #[deprecated(since = "0.9.0", note = "Use `send` instead")]
 665    pub fn send_str(&self, data: &str, flags: i32) -> Result<()> {
 666        self.send(data, flags)
 667    }
 668
 669    pub fn send_multipart<I, T>(&self, iter: I, flags: i32) -> Result<()>
 670    where
 671        I: IntoIterator<Item = T>,
 672        T: Into<Message>,
 673    {
 674        let mut last_part: Option<T> = None;
 675        for part in iter {
 676            let maybe_last = last_part.take();
 677            if let Some(last) = maybe_last {
 678                self.send(last.into(), flags | SNDMORE)?;
 679            }
 680            last_part = Some(part);
 681        }
 682        if let Some(last) = last_part {
 683            self.send(last.into(), flags)
 684        } else {
 685            Ok(())
 686        }
 687    }
 688
 689    /// Receive a message into a `Message`. The length passed to zmq_msg_recv
 690    /// is the length of the buffer.
 691    pub fn recv(&self, msg: &mut Message, flags: i32) -> Result<()> {
 692        zmq_try!(unsafe { zmq_sys::zmq_msg_recv(msg_ptr(msg), self.sock, flags as c_int) });
 693        Ok(())
 694    }
 695
 696    /// Receive bytes into a slice. The length passed to `zmq_recv` is the length of the slice. The
 697    /// return value is the number of bytes in the message, which may be larger than the length of
 698    /// the slice, indicating truncation.
 699    pub fn recv_into(&self, bytes: &mut [u8], flags: i32) -> Result<usize> {
 700        let bytes_ptr = bytes.as_mut_ptr() as *mut c_void;
 701        let rc = zmq_try!(unsafe {
 702            zmq_sys::zmq_recv(self.sock, bytes_ptr, bytes.len(), flags as c_int)
 703        });
 704        Ok(rc as usize)
 705    }
 706
 707    /// Receive a message into a fresh `Message`.
 708    pub fn recv_msg(&self, flags: i32) -> Result<Message> {
 709        let mut msg = Message::new();
 710        self.recv(&mut msg, flags).map(|_| msg)
 711    }
 712
 713    /// Receive a message as a byte vector.
 714    pub fn recv_bytes(&self, flags: i32) -> Result<Vec<u8>> {
 715        self.recv_msg(flags).map(|msg| msg.to_vec())
 716    }
 717
 718    /// Receive a `String` from the socket.
 719    ///
 720    /// If the received message is not valid UTF-8, it is returned as the original
 721    /// Vec in the `Err` part of the inner result.
 722    pub fn recv_string(&self, flags: i32) -> Result<result::Result<String, Vec<u8>>> {
 723        self.recv_bytes(flags)
 724            .map(|bytes| String::from_utf8(bytes).map_err(FromUtf8Error::into_bytes))
 725    }
 726
 727    /// Receive a multipart message from the socket.
 728    ///
 729    /// Note that this will allocate a new vector for each message part; for
 730    /// many applications it will be possible to process the different parts
 731    /// sequentially and reuse allocations that way.
 732    pub fn recv_multipart(&self, flags: i32) -> Result<Vec<Vec<u8>>> {
 733        let mut parts: Vec<Vec<u8>> = vec![];
 734        loop {
 735            let part = self.recv_bytes(flags)?;
 736            parts.push(part);
 737
 738            let more_parts = self.get_rcvmore()?;
 739            if !more_parts {
 740                break;
 741            }
 742        }
 743        Ok(parts)
 744    }
 745
 746    sockopts! {
 747        /// Accessor for the `ZMQ_IPV6` option.
 748        (is_ipv6, set_ipv6) => ZMQ_IPV6 as bool,
 749        /// Accessor for the `ZMQ_IMMEDIATE` option.
 750        (is_immediate, set_immediate) => ZMQ_IMMEDIATE as bool,
 751        /// Accessor for the `ZMQ_PLAIN_SERVER` option.
 752        (is_plain_server, set_plain_server) => ZMQ_PLAIN_SERVER as bool,
 753        /// Accessor for the `ZMQ_CONFLATE` option.
 754        (is_conflate, set_conflate) => ZMQ_CONFLATE as bool,
 755        (is_probe_router, set_probe_router) => ZMQ_PROBE_ROUTER as bool,
 756        (is_router_mandatory, set_router_mandatory) => ZMQ_ROUTER_MANDATORY as bool,
 757        (is_router_handover, set_router_handover) => ZMQ_ROUTER_HANDOVER as bool,
 758        (is_curve_server, set_curve_server) => ZMQ_CURVE_SERVER as bool,
 759        (is_gssapi_server, set_gssapi_server) => ZMQ_GSSAPI_SERVER as bool,
 760        (is_gssapi_plaintext, set_gssapi_plaintext) => ZMQ_GSSAPI_PLAINTEXT as bool,
 761        (_, set_req_relaxed) => ZMQ_REQ_RELAXED as bool,
 762        (_, set_req_correlate) => ZMQ_REQ_CORRELATE as bool,
 763    }
 764
 765    /// Return the type of this socket.
 766    pub fn get_socket_type(&self) -> Result<SocketType> {
 767        sockopt::get(self.sock, zmq_sys::ZMQ_TYPE as c_int).map(SocketType::from_raw)
 768    }
 769
 770    /// Return true if there are more frames of a multipart message to receive.
 771    pub fn get_rcvmore(&self) -> Result<bool> {
 772        sockopt::get(self.sock, zmq_sys::ZMQ_RCVMORE as c_int).map(|o: i64| o == 1i64)
 773    }
 774
 775    sockopts! {
 776        (get_maxmsgsize, set_maxmsgsize) => ZMQ_MAXMSGSIZE as i64,
 777        (get_sndhwm, set_sndhwm) => ZMQ_SNDHWM as i32,
 778        (get_rcvhwm, set_rcvhwm) => ZMQ_RCVHWM as i32,
 779        (get_affinity, set_affinity) => ZMQ_AFFINITY as u64,
 780        (get_rate, set_rate) => ZMQ_RATE as i32,
 781        (get_recovery_ivl, set_recovery_ivl) => ZMQ_RECOVERY_IVL as i32,
 782        (get_sndbuf, set_sndbuf) => ZMQ_SNDBUF as i32,
 783        (get_rcvbuf, set_rcvbuf) => ZMQ_RCVBUF as i32,
 784        (get_tos, set_tos) => ZMQ_TOS as i32,
 785        (get_linger, set_linger) => ZMQ_LINGER as i32,
 786        (get_reconnect_ivl, set_reconnect_ivl) => ZMQ_RECONNECT_IVL as i32,
 787        (get_reconnect_ivl_max, set_reconnect_ivl_max) => ZMQ_RECONNECT_IVL_MAX as i32,
 788        (get_backlog, set_backlog) => ZMQ_BACKLOG as i32,
 789
 790        /// Get the event notification file descriptor.
 791        ///
 792        /// Getter for the `ZMQ_FD` option. Note that the returned
 793        /// type is platform-specific; it aliases either
 794        /// `std::os::unix::io::RawFd` and or
 795        /// `std::os::windows::io::RawSocket`.
 796        ///
 797        /// Note that the returned file desciptor has special
 798        /// semantics: it should only used with an operating system
 799        /// facility like Unix `poll()` to check its readability.
 800        (get_fd) => ZMQ_FD as RawFd,
 801
 802        /// Get the currently pending events.
 803        ///
 804        /// Note that the result of this function can also change due
 805        /// to receiving or sending a message on the socket, without
 806        /// the signalling FD (see `Socket::get_fd()`).
 807        ///
 808        /// # Examples
 809        ///
 810        /// ```
 811        /// use zmq;
 812        /// let ctx = zmq::Context::new();
 813        /// let socket = ctx.socket(zmq::REQ).unwrap();
 814        /// let events = socket.get_events().unwrap();
 815        /// if events.contains(zmq::POLLIN) {
 816        ///   println!("socket readable")
 817        /// }
 818        /// drop(socket);
 819        /// ```
 820        ///
 821        /// # Compatibility
 822        ///
 823        /// This function currently returns the bitmask as an `i32`
 824        /// for backwards compatibility; in effect it should have been
 825        /// using the same type as `PollItem::get_revents()` all
 826        /// along.
 827        ///
 828        /// In the `0.9` series, this will be rectified.
 829        (get_events) => ZMQ_EVENTS as PollEvents,
 830
 831        (get_multicast_hops, set_multicast_hops) => ZMQ_MULTICAST_HOPS as i32,
 832        (get_rcvtimeo, set_rcvtimeo) => ZMQ_RCVTIMEO as i32,
 833        (get_sndtimeo, set_sndtimeo) => ZMQ_SNDTIMEO as i32,
 834        (get_tcp_keepalive, set_tcp_keepalive) => ZMQ_TCP_KEEPALIVE as i32,
 835        (get_tcp_keepalive_cnt, set_tcp_keepalive_cnt) => ZMQ_TCP_KEEPALIVE_CNT as i32,
 836        (get_tcp_keepalive_idle, set_tcp_keepalive_idle) => ZMQ_TCP_KEEPALIVE_IDLE as i32,
 837        (get_tcp_keepalive_intvl, set_tcp_keepalive_intvl) => ZMQ_TCP_KEEPALIVE_INTVL as i32,
 838        (get_handshake_ivl, set_handshake_ivl) => ZMQ_HANDSHAKE_IVL as i32,
 839        // TODO: deprecate to align with ZMQ's preferred naming
 840        (_, set_identity) => ZMQ_ROUTING_ID as &[u8],
 841        (_, set_subscribe) => ZMQ_SUBSCRIBE as &[u8],
 842        (_, set_unsubscribe) => ZMQ_UNSUBSCRIBE as &[u8],
 843        (get_heartbeat_ivl, set_heartbeat_ivl) => ZMQ_HEARTBEAT_IVL as i32,
 844        (get_heartbeat_ttl, set_heartbeat_ttl) => ZMQ_HEARTBEAT_TTL as i32,
 845        (get_heartbeat_timeout, set_heartbeat_timeout) => ZMQ_HEARTBEAT_TIMEOUT as i32,
 846        (get_connect_timeout, set_connect_timeout) => ZMQ_CONNECT_TIMEOUT as i32,
 847    }
 848
 849    // TODO: deprecate to align with ZMQ's preferred naming
 850    pub fn get_identity(&self) -> Result<Vec<u8>> {
 851        // 255 = identity max length
 852        sockopt::get_bytes(self.sock, zmq_sys::ZMQ_ROUTING_ID as c_int, 255)
 853    }
 854
 855    pub fn get_socks_proxy(&self) -> Result<result::Result<String, Vec<u8>>> {
 856        // 255 = longest allowable domain name is 253 so this should
 857        // be a reasonable size.
 858        sockopt::get_string(self.sock, zmq_sys::ZMQ_SOCKS_PROXY as c_int, 255, true)
 859    }
 860
 861    pub fn get_mechanism(&self) -> Result<Mechanism> {
 862        sockopt::get(self.sock, zmq_sys::ZMQ_MECHANISM as c_int).map(|mech| match mech {
 863            zmq_sys::ZMQ_NULL => Mechanism::ZMQ_NULL,
 864            zmq_sys::ZMQ_PLAIN => Mechanism::ZMQ_PLAIN,
 865            zmq_sys::ZMQ_CURVE => Mechanism::ZMQ_CURVE,
 866            zmq_sys::ZMQ_GSSAPI => Mechanism::ZMQ_GSSAPI,
 867            _ => panic!("Mechanism is out of range!"),
 868        })
 869    }
 870
 871    pub fn get_plain_username(&self) -> Result<result::Result<String, Vec<u8>>> {
 872        // 255 = arbitrary size
 873        sockopt::get_string(self.sock, zmq_sys::ZMQ_PLAIN_USERNAME as c_int, 255, true)
 874    }
 875
 876    pub fn get_plain_password(&self) -> Result<result::Result<String, Vec<u8>>> {
 877        // 256 = arbitrary size based on std crypto key size
 878        sockopt::get_string(self.sock, zmq_sys::ZMQ_PLAIN_PASSWORD as c_int, 256, true)
 879    }
 880
 881    pub fn get_zap_domain(&self) -> Result<result::Result<String, Vec<u8>>> {
 882        // 255 = arbitrary size
 883        sockopt::get_string(self.sock, zmq_sys::ZMQ_ZAP_DOMAIN as c_int, 255, true)
 884    }
 885
 886    /// Return the address of the last endpoint this socket was bound to.
 887    ///
 888    /// Note that the returned address is not guaranteed to be the
 889    /// same as the one used with `bind`, and might also not be
 890    /// directly usable with `connect`. In particular, when `bind` is
 891    /// used with the wildcard address (`"*"`), in the address
 892    /// returned, the wildcard will be expanded into the any address
 893    /// (i.e. `0.0.0.0` with IPv4).
 894    pub fn get_last_endpoint(&self) -> Result<result::Result<String, Vec<u8>>> {
 895        // 256 + 9 + 1 = maximum inproc name size (= 256) + "inproc://".len() (= 9), plus null byte
 896        sockopt::get_string(
 897            self.sock,
 898            zmq_sys::ZMQ_LAST_ENDPOINT as c_int,
 899            256 + 9 + 1,
 900            true,
 901        )
 902    }
 903
 904    /// Set the `ZMQ_CURVE_PUBLICKEY` option value.
 905    ///
 906    /// The key is returned as raw bytes. Use `z85_encode` on the
 907    /// resulting data to get the Z85-encoded string representation of
 908    /// the key.
 909    pub fn get_curve_publickey(&self) -> Result<Vec<u8>> {
 910        sockopt::get_bytes(self.sock, zmq_sys::ZMQ_CURVE_PUBLICKEY as c_int, 32)
 911    }
 912
 913    /// Get the `ZMQ_CURVE_SECRETKEY` option value.
 914    ///
 915    /// The key is returned as raw bytes. Use `z85_encode` on the
 916    /// resulting data to get the Z85-encoded string representation of
 917    /// the key.
 918    pub fn get_curve_secretkey(&self) -> Result<Vec<u8>> {
 919        sockopt::get_bytes(self.sock, zmq_sys::ZMQ_CURVE_SECRETKEY as c_int, 32)
 920    }
 921
 922    /// Get `ZMQ_CURVE_SERVERKEY` option value.
 923    ///
 924    /// Note that the key is returned as raw bytes, as a 32-byte
 925    /// vector. Use `z85_encode()` explicitly to obtain the
 926    /// Z85-encoded string variant.
 927    pub fn get_curve_serverkey(&self) -> Result<Vec<u8>> {
 928        // 41 = Z85 encoded keysize + 1 for null byte
 929        sockopt::get_bytes(self.sock, zmq_sys::ZMQ_CURVE_SERVERKEY as c_int, 32)
 930    }
 931
 932    pub fn get_gssapi_principal(&self) -> Result<result::Result<String, Vec<u8>>> {
 933        // 260 = best guess of max length based on docs.
 934        sockopt::get_string(self.sock, zmq_sys::ZMQ_GSSAPI_PRINCIPAL as c_int, 260, true)
 935    }
 936
 937    pub fn get_gssapi_service_principal(&self) -> Result<result::Result<String, Vec<u8>>> {
 938        // 260 = best guess of max length based on docs.
 939        sockopt::get_string(
 940            self.sock,
 941            zmq_sys::ZMQ_GSSAPI_SERVICE_PRINCIPAL as c_int,
 942            260,
 943            true,
 944        )
 945    }
 946
 947    sockopts! {
 948        (_, set_socks_proxy) => ZMQ_SOCKS_PROXY as Option<&str>,
 949        (_, set_plain_username) => ZMQ_PLAIN_USERNAME as Option<&str>,
 950        (_, set_plain_password) => ZMQ_PLAIN_PASSWORD as Option<&str>,
 951        (_, set_zap_domain) => ZMQ_ZAP_DOMAIN as &str,
 952        (_, set_xpub_welcome_msg) => ZMQ_XPUB_WELCOME_MSG as Option<&str>,
 953        (_, set_xpub_verbose) => ZMQ_XPUB_VERBOSE as bool,
 954
 955        (_, set_curve_publickey) => ZMQ_CURVE_PUBLICKEY as &[u8],
 956        (_, set_curve_secretkey) => ZMQ_CURVE_SECRETKEY as &[u8],
 957        (_, set_curve_serverkey) => ZMQ_CURVE_SERVERKEY as &[u8],
 958        (_, set_gssapi_principal) => ZMQ_GSSAPI_PRINCIPAL as &str,
 959        (_, set_gssapi_service_principal) => ZMQ_GSSAPI_SERVICE_PRINCIPAL as &str,
 960    }
 961
 962    /// Create a `PollItem` from the socket.
 963    pub fn as_poll_item(&self, events: PollEvents) -> PollItem {
 964        PollItem {
 965            socket: self.sock,
 966            fd: 0,
 967            events: events.bits(),
 968            revents: 0,
 969            marker: PhantomData,
 970        }
 971    }
 972
 973    /// Do a call to `zmq_poll` with only this socket.
 974    ///
 975    /// The return value on success will be either zero (no event) or one (some
 976    /// event was signaled).
 977    pub fn poll(&self, events: PollEvents, timeout_ms: i64) -> Result<i32> {
 978        poll(&mut [self.as_poll_item(events)], timeout_ms)
 979    }
 980}
 981
 982// TODO: Duplicating the values inside the bitflags struct and on the top level
 983// is unfortunate.
 984bitflags! {
 985    /// Type representing pending socket events.
 986    pub struct PollEvents: i16 {
 987        /// For `poll()`, specifies to signal when a message/some data
 988        /// can be read from a socket.
 989        const POLLIN = zmq_sys::ZMQ_POLLIN as i16;
 990        /// For `poll()`, specifies to signal when a message/some data
 991        /// can be written to a socket.
 992        const POLLOUT = zmq_sys::ZMQ_POLLOUT as i16;
 993        /// For `poll()`, specifies to signal when an error condition
 994        /// is present on a socket.  This only applies to non-0MQ
 995        /// sockets.
 996        const POLLERR = zmq_sys::ZMQ_POLLERR as i16;
 997    }
 998}
 999
1000/// For `poll()`, specifies to signal when a message/some data can be
1001/// read from a socket.
1002pub const POLLIN: PollEvents = PollEvents::POLLIN;
1003
1004/// For `poll()`, specifies to signal when a message/some data can be
1005/// written to a socket.
1006pub const POLLOUT: PollEvents = PollEvents::POLLOUT;
1007
1008/// For `poll()`, specifies to signal when an error condition is
1009/// present on a socket.  This only applies to non-0MQ sockets.
1010pub const POLLERR: PollEvents = PollEvents::POLLERR;
1011
1012/// Represents a handle that can be `poll()`ed.
1013///
1014/// This is either a reference to a 0MQ socket, or a standard socket.
1015/// Apart from that it contains the requested event mask, and is updated
1016/// with the occurred events after `poll()` finishes.
1017#[repr(C)]
1018pub struct PollItem<'a> {
1019    socket: *mut c_void,
1020    fd: RawFd,
1021    events: c_short,
1022    revents: c_short,
1023    marker: PhantomData<&'a Socket>,
1024}
1025
1026impl<'a> PollItem<'a> {
1027    /// Construct a PollItem from a non-0MQ socket, given by its file
1028    /// descriptor and the events that should be polled.
1029    pub fn from_fd(fd: RawFd, events: PollEvents) -> PollItem<'a> {
1030        PollItem {
1031            socket: ptr::null_mut(),
1032            fd,
1033            events: events.bits(),
1034            revents: 0,
1035            marker: PhantomData,
1036        }
1037    }
1038
1039    /// Change the events to wait for.
1040    pub fn set_events(&mut self, events: PollEvents) {
1041        self.events = events.bits();
1042    }
1043
1044    /// Retrieve the events that occurred for this handle.
1045    pub fn get_revents(&self) -> PollEvents {
1046        PollEvents::from_bits_truncate(self.revents)
1047    }
1048
1049    /// Returns true if the polled socket has messages ready to receive.
1050    pub fn is_readable(&self) -> bool {
1051        (self.revents & POLLIN.bits()) != 0
1052    }
1053
1054    /// Returns true if the polled socket can accept messages to be sent
1055    /// without blocking.
1056    pub fn is_writable(&self) -> bool {
1057        (self.revents & POLLOUT.bits()) != 0
1058    }
1059
1060    /// Returns true if the polled socket encountered an error condition.
1061    pub fn is_error(&self) -> bool {
1062        (self.revents & POLLERR.bits()) != 0
1063    }
1064
1065    /// Returns true if the polled socket is the given 0MQ socket.
1066    pub fn has_socket(&self, socket: &Socket) -> bool {
1067        self.socket == socket.sock
1068    }
1069
1070    /// Returns true if the polled socket is the given file descriptor.
1071    pub fn has_fd(&self, fd: RawFd) -> bool {
1072        self.socket.is_null() && self.fd == fd
1073    }
1074}
1075
1076/// Poll for events on multiple sockets.
1077///
1078/// For every poll item given, the events given in the `events` bitmask are
1079/// monitored, and signaled in `revents` when they occur. Any number of poll
1080/// items can have events signaled when the function returns.
1081///
1082/// The given timeout is in milliseconds and can be zero. A timeout of `-1`
1083/// indicates to block indefinitely until an event has occurred.
1084///
1085/// The result, if not `Err`, indicates the number of poll items that have
1086/// events signaled.
1087pub fn poll(items: &mut [PollItem], timeout: i64) -> Result<i32> {
1088    let rc = zmq_try!(unsafe {
1089        zmq_sys::zmq_poll(
1090            items.as_mut_ptr() as *mut zmq_sys::zmq_pollitem_t,
1091            items.len() as c_int,
1092            timeout as c_long,
1093        )
1094    });
1095    Ok(rc as i32)
1096}
1097
1098/// Start a 0MQ proxy in the current thread.
1099///
1100/// A proxy connects a frontend socket with a backend socket, where the exact
1101/// behavior depends on the type of both sockets.
1102///
1103/// This function only returns (always with an `Err`) when the sockets' context
1104/// has been closed.
1105pub fn proxy(frontend: &Socket, backend: &Socket) -> Result<()> {
1106    zmq_try!(unsafe { zmq_sys::zmq_proxy(frontend.sock, backend.sock, ptr::null_mut()) });
1107    Ok(())
1108}
1109
1110/// Start a 0MQ proxy in the current thread, with a capture socket.
1111///
1112/// The capture socket is sent all messages received on the frontend and backend
1113/// sockets.
1114pub fn proxy_with_capture(
1115    frontend: &mut Socket,
1116    backend: &mut Socket,
1117    capture: &mut Socket,
1118) -> Result<()> {
1119    zmq_try!(unsafe { zmq_sys::zmq_proxy(frontend.sock, backend.sock, capture.sock) });
1120    Ok(())
1121}
1122
1123/// Start a 0MQ proxy in the current thread, with a control socket.
1124///
1125/// If PAUSE is received on the control socket, the proxy suspends its activities. If RESUME is received,
1126/// it goes on. If TERMINATE is received, it terminates smoothly. At start, the proxy runs normally
1127/// as if `proxy` was used.
1128pub fn proxy_steerable(
1129    frontend: &mut Socket,
1130    backend: &mut Socket,
1131    control: &mut Socket,
1132) -> Result<()> {
1133    zmq_try!(unsafe {
1134        zmq_sys::zmq_proxy_steerable(frontend.sock, backend.sock, ptr::null_mut(), control.sock)
1135    });
1136    Ok(())
1137}
1138
1139/// Start a 0MQ proxy in the current thread, with capture and control sockets.
1140///
1141/// Provides a steerable proxy with a capture socket. See `proxy_with_capture`
1142pub fn proxy_steerable_with_capture(
1143    frontend: &mut Socket,
1144    backend: &mut Socket,
1145    capture: &mut Socket,
1146    control: &mut Socket,
1147) -> Result<()> {
1148    zmq_try!(unsafe {
1149        zmq_sys::zmq_proxy_steerable(frontend.sock, backend.sock, capture.sock, control.sock)
1150    });
1151    Ok(())
1152}
1153
1154/// Return true if the used 0MQ library has the given capability.
1155///
1156/// The return value is always the `Some` variant; it used to return
1157/// `None` for older, now unsupported versions of 0MQ that didn't have
1158/// the wrapped `zmq_has` function. Thus, for code that requires `zmq`
1159/// version 0.9.0 or newer, you can safely call `unwrap` on the return
1160/// value.
1161///
1162/// For a list of capabilities, please consult the `zmq_has` manual
1163/// page.
1164///
1165/// # Compatibility
1166///
1167/// In the `zmq` 0.10.0, this function will simply return `bool`.
1168///
1169pub fn has(capability: &str) -> Option<bool> {
1170    let c_str = ffi::CString::new(capability).unwrap();
1171    unsafe { Some(zmq_sys::zmq_has(c_str.as_ptr()) == 1) }
1172}
1173
1174/// A CURVE key pair generated by 0MQ.
1175///
1176/// Note that for API consistency reasons, since version 0.9, the key
1177/// pair is represented in the binary form. This is in contrast to
1178/// libzmq, which returns the z85-encoded representation.
1179#[derive(Debug)]
1180pub struct CurveKeyPair {
1181    pub public_key: [u8; 32],
1182    pub secret_key: [u8; 32],
1183}
1184
1185impl CurveKeyPair {
1186    /// Create a new key pair.
1187    pub fn new() -> Result<CurveKeyPair> {
1188        // Curve keypairs are currently 40 bytes long, plus terminating NULL.
1189        let mut ffi_public_key = [0u8; 41];
1190        let mut ffi_secret_key = [0u8; 41];
1191
1192        zmq_try!(unsafe {
1193            zmq_sys::zmq_curve_keypair(
1194                ffi_public_key.as_mut_ptr() as *mut libc::c_char,
1195                ffi_secret_key.as_mut_ptr() as *mut libc::c_char,
1196            )
1197        });
1198
1199        let mut pair = CurveKeyPair {
1200            public_key: [0; 32],
1201            secret_key: [0; 32],
1202        };
1203        unsafe {
1204            // No need to check return code here, as zmq_curve_keypair
1205            // is supposed to generate valid z85-encoded keys
1206            zmq_sys::zmq_z85_decode(
1207                pair.public_key.as_mut_ptr(),
1208                ffi_public_key.as_ptr() as *mut libc::c_char,
1209            );
1210            zmq_sys::zmq_z85_decode(
1211                pair.secret_key.as_mut_ptr(),
1212                ffi_secret_key.as_ptr() as *mut libc::c_char,
1213            );
1214        }
1215
1216        Ok(pair)
1217    }
1218}
1219
1220/// Errors that can occur while encoding Z85.
1221#[derive(Debug)]
1222pub enum EncodeError {
1223    BadLength,
1224    FromUtf8Error(FromUtf8Error),
1225}
1226
1227impl From<FromUtf8Error> for EncodeError {
1228    fn from(err: FromUtf8Error) -> Self {
1229        EncodeError::FromUtf8Error(err)
1230    }
1231}
1232
1233impl fmt::Display for EncodeError {
1234    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1235        match *self {
1236            EncodeError::BadLength => write!(f, "Invalid data length. Should be multiple of 4."),
1237            EncodeError::FromUtf8Error(ref e) => write!(f, "UTF8 conversion error: {}", e),
1238        }
1239    }
1240}
1241
1242impl std::error::Error for EncodeError {}
1243
1244/// Encode a binary key as Z85 printable text.
1245///
1246/// Z85 is an encoding similar to Base64, but operates on 4-byte chunks,
1247/// which are encoded into 5-byte sequences.
1248///
1249/// The input slice *must* have a length divisible by 4.
1250pub fn z85_encode(data: &[u8]) -> result::Result<String, EncodeError> {
1251    if data.len() % 4 != 0 {
1252        return Err(EncodeError::BadLength);
1253    }
1254
1255    let len = data.len() * 5 / 4 + 1;
1256    let mut dest = vec![0u8; len];
1257
1258    unsafe {
1259        zmq_sys::zmq_z85_encode(
1260            dest.as_mut_ptr() as *mut libc::c_char,
1261            data.as_ptr(),
1262            data.len(),
1263        );
1264    }
1265
1266    dest.truncate(len - 1);
1267    String::from_utf8(dest).map_err(EncodeError::FromUtf8Error)
1268}
1269
1270/// Errors that can occur while decoding Z85.
1271#[derive(Debug)]
1272pub enum DecodeError {
1273    /// The input string slice's length was not a multiple of 5.
1274    BadLength,
1275    /// The input string slice had embedded NUL bytes.
1276    NulError(ffi::NulError),
1277}
1278
1279impl From<ffi::NulError> for DecodeError {
1280    fn from(err: ffi::NulError) -> Self {
1281        DecodeError::NulError(err)
1282    }
1283}
1284
1285impl fmt::Display for DecodeError {
1286    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1287        match *self {
1288            DecodeError::BadLength => write!(f, "Invalid data length. Should be multiple of 5."),
1289            DecodeError::NulError(ref e) => write!(f, "Nul byte error: {}", e),
1290        }
1291    }
1292}
1293
1294impl std::error::Error for DecodeError {}
1295
1296/// Decode a binary key from Z85-encoded text.
1297///
1298/// The input string must have a length divisible by 5.
1299///
1300/// Note that 0MQ silently accepts characters outside the range defined for
1301/// the Z85 encoding.
1302pub fn z85_decode(data: &str) -> result::Result<Vec<u8>, DecodeError> {
1303    if data.len() % 5 != 0 {
1304        return Err(DecodeError::BadLength);
1305    }
1306
1307    let len = data.len() * 4 / 5;
1308    let mut dest = vec![0u8; len];
1309
1310    let c_str = ffi::CString::new(data)?;
1311
1312    unsafe {
1313        zmq_sys::zmq_z85_decode(dest.as_mut_ptr(), c_str.into_raw());
1314    }
1315
1316    Ok(dest)
1317}