Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 448 lines (399 sloc) 14.168 kb
baa8345 Yurii Rashkovskii Renamed ezmq to erlzmq2
yrashk authored
1 -module(erlzmq).
2 %% @headerfile "erlzmq.hrl"
3 -include_lib("erlzmq.hrl").
4 -export([context/0, context/1, socket/2, bind/2, connect/2, send/2, send/3,
5 brecv/1, brecv/2, recv/1, recv/2, setsockopt/3, getsockopt/2,
6 close/1, term/1, term/2]).
7 -export_type([erlzmq_socket/0, erlzmq_context/0]).
8
9 %% @equiv context(1)
10 %% @spec context() -> {ok, erlzmq_context()} | erlzmq_error()
11 -spec context() -> {ok, erlzmq_context()} | erlzmq_error().
12 context() ->
13 context(1).
14
15 %% @doc Create a new erlzmq context with the specified number of io threads.
16 %% <br />
17 %% If the context can be created an 'ok' tuple containing an
18 %% {@type erlzmq_context()} handle to the created context is returned;
19 %% if not, it returns an 'error' tuple with an {@type erlzmq_type_error()}
20 %% describing the error.
21 %% <br />
22 %% The context must be later cleaned up calling {@link erlzmq:term/1. term/1}
23 %% <br />
24 %% <i>For more information see
25 %% <a href="http://api.zeromq.org/master:zmq-init">zmq_init</a></i>
26 %% @end
27 %% @spec context(pos_integer()) -> {ok, erlzmq_context()} | erlzmq_error()
28 -spec context(Threads :: pos_integer()) -> {ok, erlzmq_context()} | erlzmq_error().
29
30 context(Threads) when is_integer(Threads) ->
31 erlzmq_nif:context(Threads).
32
33
34 %% @doc Create a socket.
35 %% <br />
36 %% This functions creates a socket of the given
37 %% {@link erlzmq_socket_type(). type} and associates it with the given
38 %% {@link erlzmq_context(). context}.
39 %% <br />
40 %% If the socket can be created an 'ok' tuple containing a
41 %% {@type erlzmq_socket()} handle to the created socket is returned;
42 %% if not, it returns an {@type erlzmq_error()} describing the error.<br />
43 %% <i>For more information see
44 %% <a href="http://api.zeromq.org/master:zmq_socket">zmq_socket</a>.</i>
45 %% @end
46 %% @spec socket(erlzmq_context(), erlzmq_socket_type()) -> {ok, erlzmq_socket()} | erlzmq_error()
47 -spec socket(Context :: erlzmq_context(), Type :: erlzmq_socket_type()) -> {ok, erlzmq_socket()} | erlzmq_error().
48
49 socket(Context, Type) ->
50 erlzmq_nif:socket(Context, socket_type(Type)).
51
52 %% @doc Accept connections on a socket.
53 %% <br />
54 %% <i>For more information see
55 %% <a href="http://api.zeromq.org/master:zmq_bind">zmq_bind</a>.</i>
56 %% @end
57 %% @spec bind(erlzmq_socket(), erlzmq_endpoint()) -> ok | erlzmq_error()
58 -spec bind(Socket :: erlzmq_socket(), Endpoint :: erlzmq_endpoint()) -> ok | erlzmq_error().
59
60 bind(Socket, Endpoint) ->
61 erlzmq_result(erlzmq_nif:bind(Socket, Endpoint)).
62
63 %% @doc Connect a socket.
64 %% <br />
65 %% <i>For more information see
66 %% <a href="http://api.zeromq.org/master:zmq_connect">zmq_connect</a>.</i>
67 %% @end
68 %% @spec connect(erlzmq_socket(), erlzmq_endpoint()) -> ok | erlzmq_error()
69 -spec connect(Socket :: erlzmq_socket(), Endpoint :: erlzmq_endpoint()) -> ok | erlzmq_error().
70
71 connect(Socket, Endpoint) ->
72 erlzmq_result(erlzmq_nif:connect(Socket, Endpoint)).
73
74 %% @equiv send(Socket, Msg, [])
75 %% @spec send(erlzmq_socket(), erlzmq_data()) -> ok | erlzmq_error()
76 -spec send(Socket :: erlzmq_socket(), Data :: erlzmq_data()) -> ok | erlzmq_error().
77
78 send(Socket, Binary) ->
79 send(Socket, Binary, []).
80
81 %% @doc Send a message on a socket.
82 %% <br />
83 %% <i>For more information see
84 %% <a href="http://api.zeromq.org/master:zmq_send">zmq_send</a>.</i>
85 %% @end
86 %% @spec send(ezma_socket(), erlzmq_data(), erlzmq_send_recv_flags()) -> ok | erlzmq_error()
87 -spec send(Socket :: erlzmq_socket(), Data :: erlzmq_data(), Flags :: erlzmq_send_recv_flags()) -> ok | erlzmq_error().
88
89 send(Socket, Binary, Flags) when is_list(Flags) ->
90 erlzmq_result(erlzmq_nif:send(Socket, Binary, sendrecv_flags(Flags))).
91
92 %% @equiv brecv(Socket, 0)
93 %% @spec brecv(erlzmq_socket()) -> {ok, erlzmq_data()} | erlzmq_error()
94 -spec brecv(Socket :: erlzmq_socket()) -> {ok, erlzmq_data()} | erlzmq_error().
95
96 brecv(Socket) ->
97 erlzmq_result(brecv(Socket, [])).
98
99 %% @doc Receive a message from a socket in a blocking way.
100 %% This function can block the current VM scheduler. <b>DO NOT USE IT UNLESS YOU REALLY KNOW WHAT YOU ARE DOING</b>.
101 %% @end
102 %% @spec brecv(erlzmq_socket(), erlzmq_send_recv_flags()) -> {ok, erlzmq_data()} | erlzmq_error()
103 -spec brecv(Socket :: erlzmq_socket(), Flags :: erlzmq_send_recv_flags()) -> {ok, erlzmq_data()} | erlzmq_error().
104
105 brecv(Socket, Flags) when is_list(Flags) ->
106 erlzmq_result( erlzmq_nif:brecv(Socket, sendrecv_flags(Flags))).
107
108
109 %% @equiv recv(Socket, 0)
110 %% @spec recv(erlzmq_socket()) -> {ok, erlzmq_data()} | erlzmq_error()
111 -spec recv(Socket :: erlzmq_socket()) -> {ok, erlzmq_data()} | erlzmq_error().
112
113 recv(Socket) ->
114 recv(Socket, []).
115
116 %% @doc Receive a message from a socket.
117 %% <br />
118 %% <i>For more information see
119 %% <a href="http://api.zeromq.org/master:zmq_recv">zmq_recv</a>.</i>
120 %% @end
121 %% @spec recv(erlzmq_socket(), erlzmq_send_recv_flags()) -> {ok, erlzmq_data()} | erlzmq_error()
122 -spec recv(Socket :: erlzmq_socket(), Flags :: erlzmq_send_recv_flags()) -> {ok, erlzmq_data()} | erlzmq_error() | {error, timeout, reference()}.
123
124 recv(Socket, Flags) when is_list(Flags) ->
125 case erlzmq_nif:recv(Socket, sendrecv_flags(Flags)) of
126 Ref when is_reference(Ref) ->
127 Timeout = proplists:get_value(timeout, Flags, infinity),
128 receive
129 {Ref, Result} ->
130 {ok, Result}
131 after Timeout ->
132 {error, timeout, Ref}
133 end;
134 Result ->
135 erlzmq_result(Result)
136 end.
137
138 %% @doc Set an {@link erlzmq_sockopt(). option} associated with a socket.
139 %% <br />
140 %% <i>For more information see
141 %% <a href="http://api.zeromq.org/master:zmq_setsockopt">zmq_setsockopt</a>.</i>
142 %% @end
143 %% @spec setsockopt(erlzmq_socket(), erlzmq_sockopt(), erlzmq_sockopt_value()) -> ok | erlzmq_error()
144 -spec setsockopt(Socket :: erlzmq_socket(), Name :: erlzmq_sockopt(), erlzmq_sockopt_value()) -> ok | erlzmq_error().
145
146 setsockopt(Socket, Name, Value) ->
147 erlzmq_result(erlzmq_nif:setsockopt(Socket, option_name(Name), Value)).
148
149 %% @doc Get an {@link erlzmq_sockopt(). option} associated with a socket.
150 %% <br />
151 %% <i>For more information see
152 %% <a href="http://api.zeromq.org/master:zmq_getsockopt">zmq_getsockopt</a>.</i>
153 %% @end
154 %% @spec getsockopt(erlzmq_socket(), erlzmq_sockopt()) -> {ok, erlzmq_sockopt_value()} | erlzmq_error()
155 -spec getsockopt(Socket :: erlzmq_socket(), Name :: erlzmq_sockopt()) -> {ok, erlzmq_sockopt_value()} | erlzmq_error().
156
157 getsockopt(Socket, Name) ->
158 erlzmq_result(erlzmq_nif:getsockopt(Socket, option_name(Name))).
159
160
161 %% @doc Close the given socket.
162 %% <br />
163 %% <i>For more information see
164 %% <a href="http://api.zeromq.org/master:zmq_close">zmq_close</a>.</i>
165 %% @end
166 %% @spec close(erlzmq_socket()) -> ok | erlzmq_error()
167 -spec close(Socket :: erlzmq_socket()) -> ok | erlzmq_error().
168
169 close(Socket) ->
170 erlzmq_result(erlzmq_nif:close(Socket)).
171
172 %% @equiv term(Context, infinity)
173 %% @spec term(erlzmq_context()) -> ok | erlzmq_error()
174 -spec term(Context :: erlzmq_context()) -> ok | erlzmq_error().
175
176 term(Context) ->
177 term(Context, infinity).
178
179
180 %% @doc Terminate the given context waiting up to Timeout ms.
181 %% <br />
182 %% This function should be called after all sockets associated with
183 %% the given context have been closed.<br />
184 %% If not it will block the given Timeout amount of time.
185 %% <i>For more information see
186 %% <a href="http://api.zeromq.org/master:zmq_term">zmq_term</a>.</i>
187 %% @end
188 %% @spec term(erlzmq_context(), timeout()) -> ok | erlzmq_error()
189 -spec term(Context :: erlzmq_context(), Timeout :: timeout()) -> ok | erlzmq_error() | {error, timeout, reference()}.
190
191 term(Context, Timeout) ->
192 case erlzmq_nif:term(Context) of
193 Ref when is_reference(Ref) ->
194 receive
195 {Ref, Result} ->
196 Result
197 after Timeout ->
198 {error, timeout, Ref}
199 end;
200 Result ->
201 erlzmq_result(Result)
202 end.
203
204
205 %% Private
206
207 -spec socket_type(Type :: erlzmq_socket_type()) -> integer().
208
209 socket_type(pair) ->
210 ?'ZMQ_PAIR';
211 socket_type(pub) ->
212 ?'ZMQ_PUB';
213 socket_type(sub) ->
214 ?'ZMQ_SUB';
215 socket_type(req) ->
216 ?'ZMQ_REQ';
217 socket_type(rep) ->
218 ?'ZMQ_REP';
219 socket_type(xreq) ->
220 ?'ZMQ_XREQ';
221 socket_type(xrep) ->
222 ?'ZMQ_XREP';
223 socket_type(pull) ->
224 ?'ZMQ_PULL';
225 socket_type(push) ->
226 ?'ZMQ_PUSH';
227 socket_type(xpub) ->
228 ?'ZMQ_XPUB';
229 socket_type(xsub) ->
230 ?'ZMQ_XSUB'.
231
232 -spec sendrecv_flags(Flags :: erlzmq_send_recv_flags()) -> integer().
233
234 sendrecv_flags([]) ->
235 0;
236 sendrecv_flags([{timeout,_}]) ->
237 0;
238 sendrecv_flags([noblock|Rest]) ->
239 ?'ZMQ_NOBLOCK' bor sendrecv_flags(Rest);
240 sendrecv_flags([sndmore|Rest]) ->
241 ?'ZMQ_SNDMORE' bor sendrecv_flags(Rest).
242
243 -spec option_name(Name :: erlzmq_sockopt()) -> integer().
244
245 option_name(hwm) ->
246 ?'ZMQ_HWM';
247 option_name(swap) ->
248 ?'ZMQ_SWAP';
249 option_name(affinity) ->
250 ?'ZMQ_AFFINITY';
251 option_name(identity) ->
252 ?'ZMQ_IDENTITY';
253 option_name(subscribe) ->
254 ?'ZMQ_SUBSCRIBE';
255 option_name(unsubscribe) ->
256 ?'ZMQ_UNSUBSCRIBE';
257 option_name(rate) ->
258 ?'ZMQ_RATE';
259 option_name(recovery_ivl) ->
260 ?'ZMQ_RECOVERY_IVL';
261 option_name(mcast_loop) ->
262 ?'ZMQ_MCAST_LOOP';
263 option_name(sndbuf) ->
264 ?'ZMQ_SNDBUF';
265 option_name(rcvbuf) ->
266 ?'ZMQ_RCVBUF';
267 option_name(rcvmore) ->
268 ?'ZMQ_RCVMORE';
269 option_name(fd) ->
270 ?'ZMQ_FD';
271 option_name(events) ->
272 ?'ZMQ_EVENTS';
273 option_name(linger) ->
274 ?'ZMQ_LINGER';
275 option_name(reconnect_ivl) ->
276 ?'ZMQ_RECONNECT_IVL';
277 option_name(backlog) ->
278 ?'ZMQ_BACKLOG';
279 option_name(recovery_ivl_msec) ->
280 ?'ZMQ_RECOVERY_IVL_MSEC';
281 option_name(reconnect_ivl_max) ->
282 ?'ZMQ_RECONNECT_IVL_MAX'.
283
284
285 -spec erlzmq_result(ok) -> ok;
286 ({ok, Value :: term()}) -> Value :: term();
287 ({error, Value :: atom()}) -> Value :: atom();
288 ({error, integer()}) -> {error, erlzmq_error_type()};
289 ({error, erlzmq, integer()}) -> {error, erlzmq_error_type()}.
290
291 erlzmq_result(ok) ->
292 ok;
293 erlzmq_result({ok, _} = Result) ->
294 Result;
295 erlzmq_result({error, Code} = Error) when is_atom(Code) ->
296 Error;
297 erlzmq_result({error, Code}) when is_integer(Code) andalso Code > 156384712 ->
298 erlzmq_result({error, erlzmq, Code - 156384712});
299 erlzmq_result({error, erlzmq, 1}) ->
300 {error, enotsup};
301 erlzmq_result({error, erlzmq, 2}) ->
302 {error, eprotonosupport};
303 erlzmq_result({error, erlzmq, 3}) ->
304 {error, enobufs};
305 erlzmq_result({error, erlzmq, 4}) ->
306 {error, enetdown};
307 erlzmq_result({error, erlzmq, 5}) ->
308 {error, eaddrinuse};
309 erlzmq_result({error, erlzmq, 6}) ->
310 {error, eaddrnotavail};
311 erlzmq_result({error, erlzmq, 7}) ->
312 {error, econnrefused};
313 erlzmq_result({error, erlzmq, 8}) ->
314 {error, einprogress};
315 erlzmq_result({error, erlzmq, 51}) ->
316 {error, efsm};
317 erlzmq_result({error, erlzmq, 52}) ->
318 {error, enocompatproto};
319 erlzmq_result({error, erlzmq, 53}) ->
320 {error, eterm};
321 erlzmq_result({error, erlzmq, 54}) ->
322 {error, emthread};
323
324 %% errno
325 erlzmq_result({error, 1}) ->
326 {error, eperm};
327 erlzmq_result({error, 2}) ->
328 {error, enoent};
329 erlzmq_result({error, 3}) ->
330 {error, esrch};
331 erlzmq_result({error, 4}) ->
332 {error, eintr};
333 erlzmq_result({error, 5}) ->
334 {error, eio};
335 erlzmq_result({error, 7}) ->
336 {error, enxio};
337 erlzmq_result({error, 8}) ->
338 {error, eperm};
339 erlzmq_result({error, 9}) ->
340 {error, ebadf};
341 erlzmq_result({error, 10}) ->
342 {error, echild};
343 erlzmq_result({error, 11}) ->
344 {error, edeadlk};
345 erlzmq_result({error, 12}) ->
346 {error, enomem};
347 erlzmq_result({error, 13}) ->
348 {error, eacces};
349 erlzmq_result({error, 14}) ->
350 {error, efault};
351 erlzmq_result({error, 15}) ->
352 {error, enotblk};
353 erlzmq_result({error, 16}) ->
354 {error, ebusy};
355 erlzmq_result({error, 17}) ->
356 {error, eexist};
357 erlzmq_result({error, 18}) ->
358 {error, exdev};
359 erlzmq_result({error, 19}) ->
360 {error, enodev};
361 erlzmq_result({error, 20}) ->
362 {error, enotdir};
363 erlzmq_result({error, 21}) ->
364 {error, eisdir};
365 erlzmq_result({error, 22}) ->
366 {error, einval};
367 erlzmq_result({error, 23}) ->
368 {error, enfile};
369 erlzmq_result({error, 24}) ->
370 {error, emfile};
371 erlzmq_result({error, 25}) ->
372 {error, enotty};
373 erlzmq_result({error, 26}) ->
374 {error, etxtbsy};
375 erlzmq_result({error, 27}) ->
376 {error, efbig};
377 erlzmq_result({error, 28}) ->
378 {error, enospc};
379 erlzmq_result({error, 29}) ->
380 {error, espipe};
381 erlzmq_result({error, 30}) ->
382 {error, erofs};
383 erlzmq_result({error, 31}) ->
384 {error, emlink};
385 erlzmq_result({error, 32}) ->
386 {error, epipe};
387 erlzmq_result({error, 35}) ->
388 {error, eagain};
389 erlzmq_result({error, 36}) ->
390 {error, einprogress};
391 erlzmq_result({error, 37}) ->
392 {error, ealready};
393 erlzmq_result({error, 38}) ->
394 {error, enotsock};
395 erlzmq_result({error, 39}) ->
396 {error, edestaddrreq};
397 erlzmq_result({error, 40}) ->
398 {error, emsgsize};
399 erlzmq_result({error, 41}) ->
400 {error, eprototype};
401 erlzmq_result({error, 42}) ->
402 {error, enoprotoopt};
403 erlzmq_result({error, 43}) ->
404 {error, eprotonosupport};
405 erlzmq_result({error, 44}) ->
406 {error, esocktnosupport};
407 erlzmq_result({error, 45}) ->
408 {error, enotsup};
409 erlzmq_result({error, 46}) ->
410 {error, epfnosupport};
411 erlzmq_result({error, 47}) ->
412 {error, eafnosupport};
413 erlzmq_result({error, 48}) ->
414 {error, eaddrinuse};
415 erlzmq_result({error, 49}) ->
416 {error, eaddrnotavail};
417 erlzmq_result({error, 50}) ->
418 {error, enetdown};
419 erlzmq_result({error, 51}) ->
420 {error, enetunreach};
421 erlzmq_result({error, 52}) ->
422 {error, enetreset};
423 erlzmq_result({error, 53}) ->
424 {error, econnaborted};
425 erlzmq_result({error, 54}) ->
426 {error, econnreset};
427 erlzmq_result({error, 55}) ->
428 {error, enobufs};
429 erlzmq_result({error, 56}) ->
430 {error, eisconn};
431 erlzmq_result({error, 57}) ->
432 {error, enotconn};
433 erlzmq_result({error, 58}) ->
434 {error, eshutdown};
435 erlzmq_result({error, 59}) ->
436 {error, etoomanyrefs};
437 erlzmq_result({error, 60}) ->
438 {error, etimedout};
439 erlzmq_result({error, 61}) ->
440 {error, econnrefused};
441 erlzmq_result({error, 62}) ->
442 {error, eloop};
443 erlzmq_result({error, 63}) ->
444 {error, enametoolong};
445
446 erlzmq_result({error, N}) ->
447 {error, {unknown, N}}.
Something went wrong with that request. Please try again.