PageRenderTime 27ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/src/System/ZMQ4.hs

http://github.com/twittner/zeromq-haskell
Haskell | 1007 lines | 591 code | 170 blank | 246 comment | 6 complexity | 5918bd0b9e1373081c0ed003aa2e2c39 MD5 | raw file
  1. {-# LANGUAGE CPP #-}
  2. {-# LANGUAGE GADTs #-}
  3. {-# LANGUAGE DeriveDataTypeable #-}
  4. {-# LANGUAGE DeriveGeneric #-}
  5. -- |
  6. -- Module : System.ZMQ4
  7. -- Copyright : (c) 2010-2013 Toralf Wittner
  8. -- License : MIT
  9. -- Maintainer : Toralf Wittner <tw@dtex.org>
  10. -- Stability : experimental
  11. -- Portability : non-portable
  12. --
  13. -- 0MQ haskell binding. The API closely follows the C-API of 0MQ with
  14. -- the main difference being that sockets are typed.
  15. --
  16. -- /Notes/
  17. --
  18. -- Many option settings use a 'Restriction' to further constrain the
  19. -- range of possible values of their integral types. For example
  20. -- the maximum message size can be given as -1, which means no limit
  21. -- or by greater values, which denote the message size in bytes. The
  22. -- type of 'setMaxMessageSize' is therefore:
  23. --
  24. -- @setMaxMessageSize :: Integral i
  25. -- => Restricted (Nneg1, Int64) i
  26. -- -> Socket a
  27. -- -> IO ()@
  28. --
  29. -- which means any integral value in the range of @-1@ to
  30. -- (@maxBound :: Int64@) can be given. To create a restricted
  31. -- value from plain value, use 'toRestricted' or 'restrict'.
  32. module System.ZMQ4
  33. ( -- * Type Definitions
  34. -- ** Socket Types
  35. Pair (..)
  36. , Pub (..)
  37. , Sub (..)
  38. , XPub (..)
  39. , XSub (..)
  40. , Req (..)
  41. , Rep (..)
  42. , Dealer (..)
  43. , Router (..)
  44. , XReq
  45. , XRep
  46. , Pull (..)
  47. , Push (..)
  48. , Stream (..)
  49. -- ** Socket type-classes
  50. , SocketType
  51. , Sender
  52. , Receiver
  53. , Subscriber
  54. , SocketLike
  55. , Conflatable
  56. , SendProbe
  57. -- ** Various type definitions
  58. , Size
  59. , Context
  60. , Socket
  61. , Flag (..)
  62. , Switch (..)
  63. , Timeout
  64. , Event (..)
  65. , EventType (..)
  66. , EventMsg (..)
  67. , Poll (..)
  68. , KeyFormat (..)
  69. , SecurityMechanism (..)
  70. -- * General Operations
  71. , withContext
  72. , withSocket
  73. , bind
  74. , unbind
  75. , connect
  76. , disconnect
  77. , send
  78. , send'
  79. , sendMulti
  80. , receive
  81. , receiveMulti
  82. , version
  83. , monitor
  84. , socketMonitor
  85. , poll
  86. , System.ZMQ4.subscribe
  87. , System.ZMQ4.unsubscribe
  88. -- * Context Options (Read)
  89. , ioThreads
  90. , maxSockets
  91. -- * Context Options (Write)
  92. , setIoThreads
  93. , setMaxSockets
  94. -- * Socket Options (Read)
  95. , System.ZMQ4.affinity
  96. , System.ZMQ4.backlog
  97. , System.ZMQ4.conflate
  98. , System.ZMQ4.curvePublicKey
  99. , System.ZMQ4.curveSecretKey
  100. , System.ZMQ4.curveServerKey
  101. , System.ZMQ4.delayAttachOnConnect
  102. , System.ZMQ4.events
  103. , System.ZMQ4.fileDescriptor
  104. , System.ZMQ4.identity
  105. , System.ZMQ4.immediate
  106. , System.ZMQ4.ipv4Only
  107. , System.ZMQ4.ipv6
  108. , System.ZMQ4.lastEndpoint
  109. , System.ZMQ4.linger
  110. , System.ZMQ4.maxMessageSize
  111. , System.ZMQ4.mcastHops
  112. , System.ZMQ4.mechanism
  113. , System.ZMQ4.moreToReceive
  114. , System.ZMQ4.plainServer
  115. , System.ZMQ4.plainPassword
  116. , System.ZMQ4.plainUserName
  117. , System.ZMQ4.rate
  118. , System.ZMQ4.receiveBuffer
  119. , System.ZMQ4.receiveHighWM
  120. , System.ZMQ4.receiveTimeout
  121. , System.ZMQ4.reconnectInterval
  122. , System.ZMQ4.reconnectIntervalMax
  123. , System.ZMQ4.recoveryInterval
  124. , System.ZMQ4.sendBuffer
  125. , System.ZMQ4.sendHighWM
  126. , System.ZMQ4.sendTimeout
  127. , System.ZMQ4.tcpKeepAlive
  128. , System.ZMQ4.tcpKeepAliveCount
  129. , System.ZMQ4.tcpKeepAliveIdle
  130. , System.ZMQ4.tcpKeepAliveInterval
  131. , System.ZMQ4.zapDomain
  132. -- * Socket Options (Write)
  133. , setAffinity
  134. , setBacklog
  135. , setConflate
  136. , setCurveServer
  137. , setCurvePublicKey
  138. , setCurveSecretKey
  139. , setCurveServerKey
  140. , setDelayAttachOnConnect
  141. , setIdentity
  142. , setImmediate
  143. , setIpv4Only
  144. , setIpv6
  145. , setLinger
  146. , setMaxMessageSize
  147. , setMcastHops
  148. , setPlainServer
  149. , setPlainPassword
  150. , setPlainUserName
  151. , setProbeRouter
  152. , setRate
  153. , setReceiveBuffer
  154. , setReceiveHighWM
  155. , setReceiveTimeout
  156. , setReconnectInterval
  157. , setReconnectIntervalMax
  158. , setRecoveryInterval
  159. , setReqCorrelate
  160. , setReqRelaxed
  161. , setRouterMandatory
  162. , setSendBuffer
  163. , setSendHighWM
  164. , setSendTimeout
  165. , setTcpAcceptFilter
  166. , setTcpKeepAlive
  167. , setTcpKeepAliveCount
  168. , setTcpKeepAliveIdle
  169. , setTcpKeepAliveInterval
  170. , setXPubVerbose
  171. -- * Restrictions
  172. , Data.Restricted.restrict
  173. , Data.Restricted.toRestricted
  174. -- * Error Handling
  175. , ZMQError
  176. , errno
  177. , source
  178. , message
  179. -- * Low-level Functions
  180. , init
  181. , term
  182. , shutdown
  183. , context
  184. , socket
  185. , close
  186. , waitRead
  187. , waitWrite
  188. , z85Encode
  189. , z85Decode
  190. -- * Utils
  191. , proxy
  192. , curveKeyPair
  193. ) where
  194. import Control.Applicative
  195. import Control.Exception
  196. import Control.Monad (unless)
  197. import Control.Monad.IO.Class
  198. import Data.List (intersect, foldl')
  199. import Data.List.NonEmpty (NonEmpty)
  200. import Data.Restricted
  201. import Data.Traversable (forM)
  202. import Data.Typeable
  203. import Foreign hiding (throwIf, throwIf_, throwIfNull, void)
  204. import Foreign.C.String
  205. import Foreign.C.Types (CInt, CShort)
  206. import System.Posix.Types (Fd(..))
  207. import System.ZMQ4.Internal
  208. import System.ZMQ4.Internal.Base
  209. import System.ZMQ4.Internal.Error
  210. import Prelude hiding (init)
  211. import qualified Data.ByteString as SB
  212. import qualified Data.ByteString.Lazy as LB
  213. import qualified Data.List.NonEmpty as S
  214. import qualified Prelude as P
  215. import qualified System.ZMQ4.Internal.Base as B
  216. import GHC.Conc (threadWaitRead)
  217. import GHC.Generics(Generic)
  218. -----------------------------------------------------------------------------
  219. -- Socket Types
  220. -- | <http://api.zeromq.org/4-0:zmq-socket ZMQ_PAIR>
  221. data Pair = Pair deriving (Eq, Typeable, Generic)
  222. -- | <http://api.zeromq.org/4-0:zmq-socket ZMQ_PUB>
  223. data Pub = Pub deriving (Eq, Typeable, Generic)
  224. -- | <http://api.zeromq.org/4-0:zmq-socket ZMQ_SUB>
  225. data Sub = Sub deriving (Eq, Typeable, Generic)
  226. -- | <http://api.zeromq.org/4-0:zmq-socket ZMQ_XPUB>
  227. data XPub = XPub deriving (Eq, Typeable, Generic)
  228. -- | <http://api.zeromq.org/4-0:zmq-socket ZMQ_XSUB>
  229. data XSub = XSub deriving (Eq, Typeable, Generic)
  230. -- | <http://api.zeromq.org/4-0:zmq-socket ZMQ_REQ>
  231. data Req = Req deriving (Eq, Typeable, Generic)
  232. -- | <http://api.zeromq.org/4-0:zmq-socket ZMQ_REP>
  233. data Rep = Rep deriving (Eq, Typeable, Generic)
  234. -- | <http://api.zeromq.org/4-0:zmq-socket ZMQ_DEALER>
  235. data Dealer = Dealer deriving (Eq, Typeable, Generic)
  236. -- | <http://api.zeromq.org/4-0:zmq-socket ZMQ_ROUTER>
  237. data Router = Router deriving (Eq, Typeable, Generic)
  238. -- | <http://api.zeromq.org/4-0:zmq-socket ZMQ_PULL>
  239. data Pull = Pull deriving (Eq, Typeable, Generic)
  240. -- | <http://api.zeromq.org/4-0:zmq-socket ZMQ_PUSH>
  241. data Push = Push deriving (Eq, Typeable, Generic)
  242. -- | <http://api.zeromq.org/4-0:zmq-socket ZMQ_STREAM>
  243. data Stream = Stream deriving (Eq, Typeable, Generic)
  244. type XReq = Dealer
  245. {-# DEPRECATED XReq "Use Dealer" #-}
  246. type XRep = Router
  247. {-# DEPRECATED XRep "Use Router" #-}
  248. -----------------------------------------------------------------------------
  249. -- Socket Type Classifications
  250. -- | Sockets which can 'subscribe'.
  251. class Subscriber a
  252. -- | Sockets which can 'send'.
  253. class Sender a
  254. -- | Sockets which can 'receive'.
  255. class Receiver a
  256. -- | Sockets which can be 'conflate'd.
  257. class Conflatable a
  258. -- | Sockets which can send probes (cf. 'setProbeRouter').
  259. class SendProbe a
  260. instance SocketType Pair where zmqSocketType = const pair
  261. instance Sender Pair
  262. instance Receiver Pair
  263. instance SocketType Pub where zmqSocketType = const pub
  264. instance Sender Pub
  265. instance Conflatable Pub
  266. instance SocketType Sub where zmqSocketType = const sub
  267. instance Subscriber Sub
  268. instance Receiver Sub
  269. instance Conflatable Sub
  270. instance SocketType XPub where zmqSocketType = const xpub
  271. instance Sender XPub
  272. instance Receiver XPub
  273. instance SocketType XSub where zmqSocketType = const xsub
  274. instance Sender XSub
  275. instance Receiver XSub
  276. instance SocketType Req where zmqSocketType = const request
  277. instance Sender Req
  278. instance Receiver Req
  279. instance SendProbe Req
  280. instance SocketType Rep where zmqSocketType = const response
  281. instance Sender Rep
  282. instance Receiver Rep
  283. instance SocketType Dealer where zmqSocketType = const dealer
  284. instance Sender Dealer
  285. instance Receiver Dealer
  286. instance Conflatable Dealer
  287. instance SendProbe Dealer
  288. instance SocketType Router where zmqSocketType = const router
  289. instance Sender Router
  290. instance Receiver Router
  291. instance SendProbe Router
  292. instance SocketType Pull where zmqSocketType = const pull
  293. instance Receiver Pull
  294. instance Conflatable Pull
  295. instance SocketType Push where zmqSocketType = const push
  296. instance Sender Push
  297. instance Conflatable Push
  298. instance SocketType Stream where zmqSocketType = const stream
  299. instance Sender Stream
  300. instance Receiver Stream
  301. -----------------------------------------------------------------------------
  302. -- | Socket events.
  303. data Event =
  304. In -- ^ @ZMQ_POLLIN@ (incoming messages)
  305. | Out -- ^ @ZMQ_POLLOUT@ (outgoing messages, i.e. at least 1 byte can be written)
  306. | Err -- ^ @ZMQ_POLLERR@
  307. deriving (Eq, Ord, Read, Show)
  308. -- | A 'Poll' value contains the object to poll (a 0MQ socket or a file
  309. -- descriptor), the set of 'Event's which are of interest and--optionally--
  310. -- a callback-function which is invoked iff the set of interested events
  311. -- overlaps with the actual events.
  312. data Poll s m where
  313. Sock :: s t -> [Event] -> Maybe ([Event] -> m ()) -> Poll s m
  314. File :: Fd -> [Event] -> Maybe ([Event] -> m ()) -> Poll s m
  315. -- | Return the runtime version of the underlying 0MQ library as a
  316. -- (major, minor, patch) triple.
  317. version :: IO (Int, Int, Int)
  318. version =
  319. with 0 $ \major_ptr ->
  320. with 0 $ \minor_ptr ->
  321. with 0 $ \patch_ptr ->
  322. c_zmq_version major_ptr minor_ptr patch_ptr >>
  323. tupleUp <$> peek major_ptr <*> peek minor_ptr <*> peek patch_ptr
  324. where
  325. tupleUp a b c = (fromIntegral a, fromIntegral b, fromIntegral c)
  326. init :: Size -> IO Context
  327. init n = do
  328. c <- context
  329. setIoThreads n c
  330. return c
  331. {-# DEPRECATED init "Use context" #-}
  332. -- | Initialize a 0MQ context.
  333. -- Equivalent to <http://api.zeromq.org/4-0:zmq-ctx-new zmq_ctx_new>.
  334. context :: IO Context
  335. context = Context <$> throwIfNull "init" c_zmq_ctx_new
  336. -- | Terminate a 0MQ context.
  337. -- Equivalent to <http://api.zeromq.org/4-0:zmq-ctx-term zmq_ctx_term>.
  338. term :: Context -> IO ()
  339. term c = throwIfMinus1Retry_ "term" . c_zmq_ctx_term . _ctx $ c
  340. -- | Shutdown a 0MQ context.
  341. -- Equivalent to <http://api.zeromq.org/4-0:zmq-ctx-shutdown zmq_ctx_shutdown>.
  342. shutdown :: Context -> IO ()
  343. shutdown = throwIfMinus1_ "shutdown" . c_zmq_ctx_shutdown . _ctx
  344. -- | Run an action with a 0MQ context. The 'Context' supplied to your
  345. -- action will /not/ be valid after the action either returns or
  346. -- throws an exception.
  347. withContext :: (Context -> IO a) -> IO a
  348. withContext act =
  349. bracket (throwIfNull "withContext (new)" $ c_zmq_ctx_new)
  350. (throwIfMinus1Retry_ "withContext (term)" . c_zmq_ctx_term)
  351. (act . Context)
  352. -- | Run an action with a 0MQ socket. The socket will be closed after running
  353. -- the supplied action even if an error occurs. The socket supplied to your
  354. -- action will /not/ be valid after the action terminates.
  355. withSocket :: SocketType a => Context -> a -> (Socket a -> IO b) -> IO b
  356. withSocket c t = bracket (socket c t) close
  357. -- | Create a new 0MQ socket within the given context. 'withSocket' provides
  358. -- automatic socket closing and may be safer to use.
  359. socket :: SocketType a => Context -> a -> IO (Socket a)
  360. socket c t = Socket <$> mkSocketRepr t c
  361. -- | Close a 0MQ socket. 'withSocket' provides automatic socket closing and may
  362. -- be safer to use.
  363. close :: Socket a -> IO ()
  364. close = closeSock . _socketRepr
  365. -- | Subscribe Socket to given subscription.
  366. subscribe :: Subscriber a => Socket a -> SB.ByteString -> IO ()
  367. subscribe s = setByteStringOpt s B.subscribe
  368. -- | Unsubscribe Socket from given subscription.
  369. unsubscribe :: Subscriber a => Socket a -> SB.ByteString -> IO ()
  370. unsubscribe s = setByteStringOpt s B.unsubscribe
  371. -- Read Only
  372. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_EVENTS>.
  373. events :: Socket a -> IO [Event]
  374. events s = toEvents <$> getIntOpt s B.events 0
  375. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_FD>.
  376. fileDescriptor :: Socket a -> IO Fd
  377. fileDescriptor s = Fd . fromIntegral <$> getInt32Option B.filedesc s
  378. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_RCVMORE>.
  379. moreToReceive :: Socket a -> IO Bool
  380. moreToReceive s = (== 1) <$> getInt32Option B.receiveMore s
  381. -- Read
  382. -- | <http://api.zeromq.org/4-0:zmq-ctx-get zmq_ctx_get ZMQ_IO_THREADS>.
  383. ioThreads :: Context -> IO Word
  384. ioThreads = ctxIntOption "ioThreads" _ioThreads
  385. -- | <http://api.zeromq.org/4-0:zmq-ctx-get zmq_ctx_get ZMQ_MAX_SOCKETS>.
  386. maxSockets :: Context -> IO Word
  387. maxSockets = ctxIntOption "maxSockets" _maxSockets
  388. -- | Restricts the outgoing and incoming socket buffers to a single message.
  389. conflate :: Conflatable a => Socket a -> IO Bool
  390. conflate s = (== 1) <$> getInt32Option B.conflate s
  391. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_IMMEDIATE>.
  392. immediate :: Socket a -> IO Bool
  393. immediate s = (== 1) <$> getInt32Option B.immediate s
  394. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_IDENTITY>.
  395. identity :: Socket a -> IO SB.ByteString
  396. identity s = getByteStringOpt s B.identity
  397. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_AFFINITY>.
  398. affinity :: Socket a -> IO Word64
  399. affinity s = getIntOpt s B.affinity 0
  400. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_MAXMSGSIZE>.
  401. maxMessageSize :: Socket a -> IO Int64
  402. maxMessageSize s = getIntOpt s B.maxMessageSize 0
  403. ipv4Only :: Socket a -> IO Bool
  404. ipv4Only s = (== 1) <$> getInt32Option B.ipv4Only s
  405. {-# DEPRECATED ipv4Only "Use ipv6" #-}
  406. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_IPV6>.
  407. ipv6 :: Socket a -> IO Bool
  408. ipv6 s = (== 1) <$> getInt32Option B.ipv6 s
  409. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_BACKLOG>.
  410. backlog :: Socket a -> IO Int
  411. backlog = getInt32Option B.backlog
  412. delayAttachOnConnect :: Socket a -> IO Bool
  413. delayAttachOnConnect s = (== 1) <$> getInt32Option B.delayAttachOnConnect s
  414. {-# DEPRECATED delayAttachOnConnect "Use immediate" #-}
  415. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_LINGER>.
  416. linger :: Socket a -> IO Int
  417. linger = getInt32Option B.linger
  418. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_LAST_ENDPOINT>.
  419. lastEndpoint :: Socket a -> IO String
  420. lastEndpoint s = getStrOpt s B.lastEndpoint
  421. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_RATE>.
  422. rate :: Socket a -> IO Int
  423. rate = getInt32Option B.rate
  424. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_RCVBUF>.
  425. receiveBuffer :: Socket a -> IO Int
  426. receiveBuffer = getInt32Option B.receiveBuf
  427. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_RECONNECT_IVL>.
  428. reconnectInterval :: Socket a -> IO Int
  429. reconnectInterval = getInt32Option B.reconnectIVL
  430. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_RECONNECT_IVL_MAX>.
  431. reconnectIntervalMax :: Socket a -> IO Int
  432. reconnectIntervalMax = getInt32Option B.reconnectIVLMax
  433. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_RECOVERY_IVL>.
  434. recoveryInterval :: Socket a -> IO Int
  435. recoveryInterval = getInt32Option B.recoveryIVL
  436. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_SNDBUF>.
  437. sendBuffer :: Socket a -> IO Int
  438. sendBuffer = getInt32Option B.sendBuf
  439. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_MULTICAST_HOPS>.
  440. mcastHops :: Socket a -> IO Int
  441. mcastHops = getInt32Option B.mcastHops
  442. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_RCVHWM>.
  443. receiveHighWM :: Socket a -> IO Int
  444. receiveHighWM = getInt32Option B.receiveHighWM
  445. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_RCVTIMEO>.
  446. receiveTimeout :: Socket a -> IO Int
  447. receiveTimeout = getInt32Option B.receiveTimeout
  448. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_SNDTIMEO>.
  449. sendTimeout :: Socket a -> IO Int
  450. sendTimeout = getInt32Option B.sendTimeout
  451. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_SNDHWM>.
  452. sendHighWM :: Socket a -> IO Int
  453. sendHighWM = getInt32Option B.sendHighWM
  454. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_TCP_KEEPALIVE>.
  455. tcpKeepAlive :: Socket a -> IO Switch
  456. tcpKeepAlive = fmap (toSwitch "Invalid ZMQ_TCP_KEEPALIVE")
  457. . getInt32Option B.tcpKeepAlive
  458. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_TCP_KEEPALIVE_CNT>.
  459. tcpKeepAliveCount :: Socket a -> IO Int
  460. tcpKeepAliveCount = getInt32Option B.tcpKeepAliveCount
  461. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_TCP_KEEPALIVE_IDLE>.
  462. tcpKeepAliveIdle :: Socket a -> IO Int
  463. tcpKeepAliveIdle = getInt32Option B.tcpKeepAliveIdle
  464. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_TCP_KEEPALIVE_INTVL>.
  465. tcpKeepAliveInterval :: Socket a -> IO Int
  466. tcpKeepAliveInterval = getInt32Option B.tcpKeepAliveInterval
  467. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_MECHANISM>.
  468. mechanism :: Socket a -> IO SecurityMechanism
  469. mechanism = fmap (fromMechanism "Invalid ZMQ_MECHANISM")
  470. . getInt32Option B.mechanism
  471. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_PLAIN_SERVER>.
  472. plainServer :: Socket a -> IO Bool
  473. plainServer = fmap (== 1) . getInt32Option B.plainServer
  474. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_PLAIN_USERNAME>.
  475. plainUserName :: Socket a -> IO SB.ByteString
  476. plainUserName s = getByteStringOpt s B.plainUserName
  477. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_PLAIN_PASSWORD>.
  478. plainPassword :: Socket a -> IO SB.ByteString
  479. plainPassword s = getByteStringOpt s B.plainPassword
  480. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_ZAP_DOMAIN>.
  481. zapDomain :: Socket a -> IO SB.ByteString
  482. zapDomain s = getByteStringOpt s B.zapDomain
  483. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_CURVE_PUBLICKEY>.
  484. curvePublicKey :: KeyFormat f -> Socket a -> IO SB.ByteString
  485. curvePublicKey f s = getKey f s B.curvePublicKey
  486. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_CURVE_SERVERKEY>.
  487. curveServerKey :: KeyFormat f -> Socket a -> IO SB.ByteString
  488. curveServerKey f s = getKey f s B.curveServerKey
  489. -- | <http://api.zeromq.org/4-0:zmq-getsockopt zmq_getsockopt ZMQ_CURVE_SECRETKEY>.
  490. curveSecretKey :: KeyFormat f -> Socket a -> IO SB.ByteString
  491. curveSecretKey f s = getKey f s B.curveSecretKey
  492. -- Write
  493. -- | <http://api.zeromq.org/4-0:zmq-ctx-set zmq_ctx_get ZMQ_IO_THREADS>.
  494. setIoThreads :: Word -> Context -> IO ()
  495. setIoThreads n = setCtxIntOption "ioThreads" _ioThreads n
  496. -- | <http://api.zeromq.org/4-0:zmq-ctx-set zmq_ctx_get ZMQ_MAX_SOCKETS>.
  497. setMaxSockets :: Word -> Context -> IO ()
  498. setMaxSockets n = setCtxIntOption "maxSockets" _maxSockets n
  499. -- | Restrict the outgoing and incoming socket buffers to a single message.
  500. setConflate :: Conflatable a => Bool -> Socket a -> IO ()
  501. setConflate x s = setIntOpt s B.conflate (bool2cint x)
  502. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_IMMEDIATE>.
  503. setImmediate :: Bool -> Socket a -> IO ()
  504. setImmediate x s = setIntOpt s B.immediate (bool2cint x)
  505. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_IDENTITY>.
  506. setIdentity :: Restricted (N1, N254) SB.ByteString -> Socket a -> IO ()
  507. setIdentity x s = setByteStringOpt s B.identity (rvalue x)
  508. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_AFFINITY>.
  509. setAffinity :: Word64 -> Socket a -> IO ()
  510. setAffinity x s = setIntOpt s B.affinity x
  511. setDelayAttachOnConnect :: Bool -> Socket a -> IO ()
  512. setDelayAttachOnConnect x s = setIntOpt s B.delayAttachOnConnect (bool2cint x)
  513. {-# DEPRECATED setDelayAttachOnConnect "Use setImmediate" #-}
  514. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_MAXMSGSIZE>.
  515. setMaxMessageSize :: Integral i => Restricted (Nneg1, Int64) i -> Socket a -> IO ()
  516. setMaxMessageSize x s = setIntOpt s B.maxMessageSize ((fromIntegral . rvalue $ x) :: Int64)
  517. setIpv4Only :: Bool -> Socket a -> IO ()
  518. setIpv4Only x s = setIntOpt s B.ipv4Only (bool2cint x)
  519. {-# DEPRECATED setIpv4Only "Use setIpv6" #-}
  520. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_IPV6>.
  521. setIpv6 :: Bool -> Socket a -> IO ()
  522. setIpv6 x s = setIntOpt s B.ipv6 (bool2cint x)
  523. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_PLAIN_SERVER>.
  524. setPlainServer :: Bool -> Socket a -> IO ()
  525. setPlainServer x s = setIntOpt s B.plainServer (bool2cint x)
  526. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_CURVE_SERVER>.
  527. setCurveServer :: Bool -> Socket a -> IO ()
  528. setCurveServer x s = setIntOpt s B.curveServer (bool2cint x)
  529. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_PLAIN_USERNAME>.
  530. setPlainUserName :: Restricted (N1, N254) SB.ByteString -> Socket a -> IO ()
  531. setPlainUserName x s = setByteStringOpt s B.plainUserName (rvalue x)
  532. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_PLAIN_USERNAME>.
  533. setPlainPassword :: Restricted (N1, N254) SB.ByteString -> Socket a -> IO ()
  534. setPlainPassword x s = setByteStringOpt s B.plainPassword (rvalue x)
  535. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_LINGER>.
  536. setLinger :: Integral i => Restricted (Nneg1, Int32) i -> Socket a -> IO ()
  537. setLinger = setInt32OptFromRestricted B.linger
  538. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_RCVTIMEO>.
  539. setReceiveTimeout :: Integral i => Restricted (Nneg1, Int32) i -> Socket a -> IO ()
  540. setReceiveTimeout = setInt32OptFromRestricted B.receiveTimeout
  541. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_ROUTER_MANDATORY>.
  542. setRouterMandatory :: Bool -> Socket Router -> IO ()
  543. setRouterMandatory x s = setIntOpt s B.routerMandatory (bool2cint x)
  544. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_SNDTIMEO>.
  545. setSendTimeout :: Integral i => Restricted (Nneg1, Int32) i -> Socket a -> IO ()
  546. setSendTimeout = setInt32OptFromRestricted B.sendTimeout
  547. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_RATE>.
  548. setRate :: Integral i => Restricted (N1, Int32) i -> Socket a -> IO ()
  549. setRate = setInt32OptFromRestricted B.rate
  550. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_MULTICAST_HOPS>.
  551. setMcastHops :: Integral i => Restricted (N1, Int32) i -> Socket a -> IO ()
  552. setMcastHops = setInt32OptFromRestricted B.mcastHops
  553. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_BACKLOG>.
  554. setBacklog :: Integral i => Restricted (N0, Int32) i -> Socket a -> IO ()
  555. setBacklog = setInt32OptFromRestricted B.backlog
  556. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_CURVE_PUBLICKEY>.
  557. setCurvePublicKey :: KeyFormat f -> Restricted f SB.ByteString -> Socket a -> IO ()
  558. setCurvePublicKey _ k s = setByteStringOpt s B.curvePublicKey (rvalue k)
  559. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_CURVE_SECRETKEY>.
  560. setCurveSecretKey :: KeyFormat f -> Restricted f SB.ByteString -> Socket a -> IO ()
  561. setCurveSecretKey _ k s = setByteStringOpt s B.curveSecretKey (rvalue k)
  562. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_CURVE_SERVERKEY>.
  563. setCurveServerKey :: KeyFormat f -> Restricted f SB.ByteString -> Socket a -> IO ()
  564. setCurveServerKey _ k s = setByteStringOpt s B.curveServerKey (rvalue k)
  565. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_PROBE_ROUTER>.
  566. setProbeRouter :: SendProbe a => Bool -> Socket a -> IO ()
  567. setProbeRouter x s = setIntOpt s B.probeRouter (bool2cint x)
  568. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_RCVBUF>.
  569. setReceiveBuffer :: Integral i => Restricted (N0, Int32) i -> Socket a -> IO ()
  570. setReceiveBuffer = setInt32OptFromRestricted B.receiveBuf
  571. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_RECONNECT_IVL>.
  572. setReconnectInterval :: Integral i => Restricted (N0, Int32) i -> Socket a -> IO ()
  573. setReconnectInterval = setInt32OptFromRestricted B.reconnectIVL
  574. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_RECONNECT_IVL_MAX>.
  575. setReconnectIntervalMax :: Integral i => Restricted (N0, Int32) i -> Socket a -> IO ()
  576. setReconnectIntervalMax = setInt32OptFromRestricted B.reconnectIVLMax
  577. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_REQ_CORRELATE>.
  578. setReqCorrelate :: Bool -> Socket Req -> IO ()
  579. setReqCorrelate x s = setIntOpt s B.reqCorrelate (bool2cint x)
  580. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_REQ_RELAXED>.
  581. setReqRelaxed :: Bool -> Socket Req -> IO ()
  582. setReqRelaxed x s = setIntOpt s B.reqRelaxed (bool2cint x)
  583. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_SNDBUF>.
  584. setSendBuffer :: Integral i => Restricted (N0, Int32) i -> Socket a -> IO ()
  585. setSendBuffer = setInt32OptFromRestricted B.sendBuf
  586. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_RECOVERY_IVL>.
  587. setRecoveryInterval :: Integral i => Restricted (N0, Int32) i -> Socket a -> IO ()
  588. setRecoveryInterval = setInt32OptFromRestricted B.recoveryIVL
  589. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_RCVHWM>.
  590. setReceiveHighWM :: Integral i => Restricted (N0, Int32) i -> Socket a -> IO ()
  591. setReceiveHighWM = setInt32OptFromRestricted B.receiveHighWM
  592. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_SNDHWM>.
  593. setSendHighWM :: Integral i => Restricted (N0, Int32) i -> Socket a -> IO ()
  594. setSendHighWM = setInt32OptFromRestricted B.sendHighWM
  595. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_TCP_ACCEPT_FILTER>.
  596. setTcpAcceptFilter :: Maybe SB.ByteString -> Socket a -> IO ()
  597. setTcpAcceptFilter Nothing sock = onSocket "setTcpAcceptFilter" sock $ \s ->
  598. throwIfMinus1Retry_ "setStrOpt" $
  599. c_zmq_setsockopt s (optVal tcpAcceptFilter) nullPtr 0
  600. setTcpAcceptFilter (Just dat) sock = setByteStringOpt sock tcpAcceptFilter dat
  601. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_TCP_KEEPALIVE>.
  602. setTcpKeepAlive :: Switch -> Socket a -> IO ()
  603. setTcpKeepAlive x s = setIntOpt s B.tcpKeepAlive (fromSwitch x :: CInt)
  604. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_TCP_KEEPALIVE_CNT>.
  605. setTcpKeepAliveCount :: Integral i => Restricted (Nneg1, Int32) i -> Socket a -> IO ()
  606. setTcpKeepAliveCount = setInt32OptFromRestricted B.tcpKeepAliveCount
  607. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_TCP_KEEPALIVE_IDLE>.
  608. setTcpKeepAliveIdle :: Integral i => Restricted (Nneg1, Int32) i -> Socket a -> IO ()
  609. setTcpKeepAliveIdle = setInt32OptFromRestricted B.tcpKeepAliveIdle
  610. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_TCP_KEEPALIVE_INTVL>.
  611. setTcpKeepAliveInterval :: Integral i => Restricted (Nneg1, Int32) i -> Socket a -> IO ()
  612. setTcpKeepAliveInterval = setInt32OptFromRestricted B.tcpKeepAliveInterval
  613. -- | <http://api.zeromq.org/4-0:zmq-setsockopt zmq_setsockopt ZMQ_XPUB_VERBOSE>.
  614. setXPubVerbose :: Bool -> Socket XPub -> IO ()
  615. setXPubVerbose x s = setIntOpt s B.xpubVerbose (bool2cint x)
  616. -- | Bind the socket to the given address
  617. -- (cf. <http://api.zeromq.org/4-0:zmq-bind zmq_bind>).
  618. bind :: Socket a -> String -> IO ()
  619. bind sock str = onSocket "bind" sock $
  620. throwIfMinus1Retry_ "bind" . withCString str . c_zmq_bind
  621. -- | Unbind the socket from the given address
  622. -- (cf. <http://api.zeromq.org/4-0:zmq-unbind zmq_unbind>).
  623. unbind :: Socket a -> String -> IO ()
  624. unbind sock str = onSocket "unbind" sock $
  625. throwIfMinus1Retry_ "unbind" . withCString str . c_zmq_unbind
  626. -- | Connect the socket to the given address
  627. -- (cf. <http://api.zeromq.org/4-0:zmq-connect zmq_connect>).
  628. connect :: Socket a -> String -> IO ()
  629. connect sock str = onSocket "connect" sock $
  630. throwIfMinus1Retry_ "connect" . withCString str . c_zmq_connect
  631. -- | Disconnect the socket from the given endpoint
  632. -- (cf. <http://api.zeromq.org/4-0:zmq-disconnect zmq_disconnect>).
  633. disconnect :: Socket a -> String -> IO ()
  634. disconnect sock str = onSocket "disconnect" sock $
  635. throwIfMinus1Retry_ "disconnect" . withCString str . c_zmq_disconnect
  636. -- | Send the given 'SB.ByteString' over the socket
  637. -- (cf. <http://api.zeromq.org/4-0:zmq-sendmsg zmq_sendmsg>).
  638. --
  639. -- /Note/: This function always calls @zmq_sendmsg@ in a non-blocking way,
  640. -- i.e. there is no need to provide the @ZMQ_DONTWAIT@ flag as this is used
  641. -- by default. Still 'send' is blocking the thread as long as the message
  642. -- can not be queued on the socket using GHC's 'threadWaitWrite'.
  643. send :: Sender a => Socket a -> [Flag] -> SB.ByteString -> IO ()
  644. send sock fls val = bracketOnError (messageOf val) messageClose $ \m -> do
  645. onSocket "send" sock $ \s ->
  646. retry "send" (waitWrite sock) $
  647. #ifdef mingw32_HOST_OS
  648. c_zmq_sendmsg s (msgPtr m) (combineFlags fls)
  649. #else
  650. c_zmq_sendmsg s (msgPtr m) (combineFlags (DontWait : fls))
  651. #endif
  652. messageFree m
  653. -- | Send the given 'LB.ByteString' over the socket
  654. -- (cf. <http://api.zeromq.org/4-0:zmq-sendmsg zmq_sendmsg>).
  655. --
  656. -- This is operationally identical to @send socket (Strict.concat
  657. -- (Lazy.toChunks lbs)) flags@ but may be more efficient.
  658. --
  659. -- /Note/: This function always calls @zmq_sendmsg@ in a non-blocking way,
  660. -- i.e. there is no need to provide the @ZMQ_DONTWAIT@ flag as this is used
  661. -- by default. Still 'send'' is blocking the thread as long as the message
  662. -- can not be queued on the socket using GHC's 'threadWaitWrite'.
  663. send' :: Sender a => Socket a -> [Flag] -> LB.ByteString -> IO ()
  664. send' sock fls val = bracketOnError (messageOfLazy val) messageClose $ \m -> do
  665. onSocket "send'" sock $ \s ->
  666. retry "send'" (waitWrite sock) $
  667. #ifdef mingw32_HOST_OS
  668. c_zmq_sendmsg s (msgPtr m) (combineFlags fls)
  669. #else
  670. c_zmq_sendmsg s (msgPtr m) (combineFlags (DontWait : fls))
  671. #endif
  672. messageFree m
  673. -- | Send a multi-part message.
  674. -- This function applies the 'SendMore' 'Flag' between all message parts.
  675. -- 0MQ guarantees atomic delivery of a multi-part message
  676. -- (cf. <http://api.zeromq.org/4-0:zmq-sendmsg zmq_sendmsg>).
  677. sendMulti :: Sender a => Socket a -> NonEmpty SB.ByteString -> IO ()
  678. sendMulti sock msgs = do
  679. mapM_ (send sock [SendMore]) (S.init msgs)
  680. send sock [] (S.last msgs)
  681. -- | Receive a 'ByteString' from socket
  682. -- (cf. <http://api.zeromq.org/4-0:zmq-recvmsg zmq_recvmsg>).
  683. --
  684. -- /Note/: This function always calls @zmq_recvmsg@ in a non-blocking way,
  685. -- i.e. there is no need to provide the @ZMQ_DONTWAIT@ flag as this is used
  686. -- by default. Still 'receive' is blocking the thread as long as no data
  687. -- is available using GHC's 'threadWaitRead'.
  688. receive :: Receiver a => Socket a -> IO (SB.ByteString)
  689. receive sock = bracket messageInit messageClose $ \m ->
  690. onSocket "receive" sock $ \s -> do
  691. retry "receive" (waitRead sock) $
  692. #ifdef mingw32_HOST_OS
  693. c_zmq_recvmsg s (msgPtr m) 0
  694. #else
  695. c_zmq_recvmsg s (msgPtr m) (flagVal dontWait)
  696. #endif
  697. data_ptr <- c_zmq_msg_data (msgPtr m)
  698. size <- c_zmq_msg_size (msgPtr m)
  699. SB.packCStringLen (data_ptr, fromIntegral size)
  700. -- | Receive a multi-part message.
  701. -- This function collects all message parts send via 'sendMulti'.
  702. receiveMulti :: Receiver a => Socket a -> IO [SB.ByteString]
  703. receiveMulti sock = recvall []
  704. where
  705. recvall acc = do
  706. msg <- receive sock
  707. moreToReceive sock >>= next (msg:acc)
  708. next acc True = recvall acc
  709. next acc False = return (reverse acc)
  710. -- | Setup socket monitoring, i.e. a 'Pair' socket which
  711. -- sends monitoring events about the given 'Socket' to the
  712. -- given address.
  713. socketMonitor :: [EventType] -> String -> Socket a -> IO ()
  714. socketMonitor es addr soc = onSocket "socketMonitor" soc $ \s ->
  715. withCString addr $ \a ->
  716. throwIfMinus1_ "zmq_socket_monitor" $
  717. c_zmq_socket_monitor s a (events2cint es)
  718. -- | Monitor socket events
  719. -- (cf. <http://api.zeromq.org/4-0:zmq-socket-monitor zmq_socket_monitor>).
  720. --
  721. -- This function returns a function which can be invoked to retrieve
  722. -- the next socket event, potentially blocking until the next one becomes
  723. -- available. When applied to 'False', monitoring will terminate, i.e.
  724. -- internal monitoring resources will be disposed. Consequently after
  725. -- 'monitor' has been invoked, the returned function must be applied
  726. -- /once/ to 'False'.
  727. monitor :: [EventType] -> Context -> Socket a -> IO (Bool -> IO (Maybe EventMsg))
  728. monitor es ctx sock = do
  729. let addr = "inproc://" ++ show (_socket . _socketRepr $ sock)
  730. s <- socket ctx Pair
  731. socketMonitor es addr sock
  732. connect s addr
  733. next s <$> messageInit
  734. where
  735. next soc m False = messageClose m `finally` close soc >> return Nothing
  736. next soc m True = onSocket "recv" soc $ \s -> do
  737. retry "recv" (waitRead soc) $
  738. #ifdef mingw32_HOST_OS
  739. c_zmq_recvmsg s (msgPtr m) 0
  740. #else
  741. c_zmq_recvmsg s (msgPtr m) (flagVal dontWait)
  742. #endif
  743. evt <- peekZMQEvent (msgPtr m)
  744. str <- receive soc
  745. return . Just $ eventMessage str evt
  746. -- | Polls for events on the given 'Poll' descriptors. Returns a list of
  747. -- events per descriptor which have occured.
  748. -- (cf. <http://api.zeromq.org/4-0:zmq-poll zmq_poll>)
  749. poll :: (SocketLike s, MonadIO m) => Timeout -> [Poll s m] -> m [[Event]]
  750. poll _ [] = return []
  751. poll to desc = do
  752. let len = length desc
  753. let ps = map toZMQPoll desc
  754. ps' <- liftIO $ withArray ps $ \ptr -> do
  755. throwIfMinus1Retry_ "poll" $
  756. c_zmq_poll ptr (fromIntegral len) (fromIntegral to)
  757. peekArray len ptr
  758. mapM fromZMQPoll (zip desc ps')
  759. where
  760. toZMQPoll :: (SocketLike s, MonadIO m) => Poll s m -> ZMQPoll
  761. toZMQPoll (Sock s e _) =
  762. ZMQPoll (_socket . _socketRepr . toSocket $ s) 0 (combine (map fromEvent e)) 0
  763. toZMQPoll (File (Fd s) e _) =
  764. ZMQPoll nullPtr (fromIntegral s) (combine (map fromEvent e)) 0
  765. fromZMQPoll :: (SocketLike s, MonadIO m) => (Poll s m, ZMQPoll) -> m [Event]
  766. fromZMQPoll (p, zp) = do
  767. let e = toEvents . fromIntegral . pRevents $ zp
  768. let (e', f) = case p of
  769. (Sock _ x g) -> (x, g)
  770. (File _ x g) -> (x, g)
  771. forM f (unless (P.null (e `intersect` e')) . ($ e)) >> return e
  772. fromEvent :: Event -> CShort
  773. fromEvent In = fromIntegral . pollVal $ pollIn
  774. fromEvent Out = fromIntegral . pollVal $ pollOut
  775. fromEvent Err = fromIntegral . pollVal $ pollerr
  776. -- Convert bit-masked word into Event list.
  777. toEvents :: Word32 -> [Event]
  778. toEvents e = foldl' (\es f -> f e es) [] tests
  779. where
  780. tests =
  781. [ \i xs -> if i .&. (fromIntegral . pollVal $ pollIn) /= 0 then In:xs else xs
  782. , \i xs -> if i .&. (fromIntegral . pollVal $ pollOut) /= 0 then Out:xs else xs
  783. , \i xs -> if i .&. (fromIntegral . pollVal $ pollerr) /= 0 then Err:xs else xs
  784. ]
  785. retry :: String -> IO () -> IO CInt -> IO ()
  786. retry msg wait act = throwIfMinus1RetryMayBlock_ msg act wait
  787. wait' :: ZMQPollEvent -> Socket a -> IO ()
  788. #ifdef mingw32_HOST_OS
  789. wait' _ _ = return ()
  790. #else
  791. wait' p s = do
  792. e <- getInt32Option B.events s
  793. unless (testev e) $ do
  794. fd <- getIntOpt s B.filedesc 0
  795. threadWaitRead (Fd fd)
  796. wait' p s
  797. where
  798. testev e = e .&. fromIntegral (pollVal p) /= 0
  799. #endif
  800. -- | Wait until data is available for reading from the given Socket.
  801. -- After this function returns, a call to 'receive' will essentially be
  802. -- non-blocking.
  803. waitRead :: Socket a -> IO ()
  804. waitRead = wait' pollIn
  805. -- | Wait until data can be written to the given Socket.
  806. -- After this function returns, a call to 'send' will essentially be
  807. -- non-blocking.
  808. waitWrite :: Socket a -> IO ()
  809. waitWrite = wait' pollOut
  810. -- | Starts built-in 0MQ proxy
  811. -- (cf. <http://api.zeromq.org/4-0:zmq-proxy zmq_proxy>)
  812. --
  813. -- Proxy connects front to back socket
  814. --
  815. -- Before calling proxy all sockets should be bound
  816. --
  817. -- If the capture socket is not Nothing, the proxy shall send all
  818. -- messages, received on both frontend and backend, to the capture socket.
  819. proxy :: Socket a -> Socket b -> Maybe (Socket c) -> IO ()
  820. proxy front back capture =
  821. onSocket "proxy-front" front $ \f ->
  822. onSocket "proxy-back" back $ \b ->
  823. throwIfMinus1Retry_ "c_zmq_proxy" $ c_zmq_proxy f b c
  824. where
  825. c = maybe nullPtr (_socket . _socketRepr) capture
  826. -- | Generate a new curve key pair.
  827. -- (cf. <http://api.zeromq.org/4-0:zmq-curve-keypair zmq_curve_keypair>)
  828. curveKeyPair :: MonadIO m => m (Restricted Div5 SB.ByteString, Restricted Div5 SB.ByteString)
  829. curveKeyPair = liftIO $
  830. allocaBytes 41 $ \cstr1 ->
  831. allocaBytes 41 $ \cstr2 -> do
  832. throwIfMinus1_ "c_zmq_curve_keypair" $ c_zmq_curve_keypair cstr1 cstr2
  833. public <- toRestricted <$> SB.packCString cstr1
  834. private <- toRestricted <$> SB.packCString cstr2
  835. maybe (fail errmsg) return ((,) <$> public <*> private)
  836. where
  837. errmsg = "curveKeyPair: invalid key-lengths produced"