%% This Source Code Form is subject to the terms of the Mozilla Public %% License, v. 2.0. If a copy of the MPL was not distributed with this %% file, You can obtain one at http://mozilla.org/MPL/2.0/. %% @doc Erlang bindings for ZeroMQ. %% %% see ZeroMQ 3.1 RFC in http://rfc.zeromq.org/spec:37 -module(chumak). -include("chumak.hrl"). -behaviour(application). -export([start/2, stop/1]). -export([socket/1, socket/2, connect/4, connect/5, bind/4, send/2, recv/1, send_multipart/2, recv_multipart/1, set_socket_option/3, cancel/2, subscribe/2, resource/0, attach_resource/3, version/0]). -define(SUPERVISOR, chumak_sup). -type version()::{Major::integer(), Minor::integer(), Patch::integer()}. -export_type([security_mechanism/0]). %% %% OTP/Application behaviour %% %% @hidden start(_StartType, _StartArgs) -> ?SUPERVISOR:start_link(). %% @hidden stop(_State) -> ok. %% @doc start a new socket -spec socket(Type::socket_type(), Identity::string()) -> {ok, SocketPid::pid()} | {error, Reason::atom()}. socket(Type, Identity) when is_atom(Type), is_list(Identity) -> ?SUPERVISOR:start_socket(Type, Identity). socket(Type) when is_atom(Type) -> ?SUPERVISOR:start_socket(Type). %% @doc set socket option. %% In case of a problem an error is returned and the socket remains unchanged. %% %% Valid options are: %%
%%
curve_server
%%
- Set CURVE server role
%%
- type: boolean()
%%
Defines whether the socket will act as server for CURVE security. A %% value of true means the socket will act as CURVE server. A value of false %% means the socket will not act as CURVE server. When you set this you must %% also set the server's secret key using the curve_secretkey option. A server %% socket does not need to know its own public key.
%% %%
curve_serverkey
%%
- Set CURVE server key
%%
- type: binary() or string()
%%
Sets the socket's long term server key. You must set this on CURVE %% client sockets. You can provide the key as 32 binary bytes, or as a %% 40-character string encoded in the Z85 encoding format. This key must have %% been generated together with the server's secret key.
%% %%
curve_secretkey
%%
- Set CURVE secret key
%%
- type: binary() or string()
%%
Sets the socket's long term secret key. You must set this on both %% CURVE client and server sockets. You can provide the key as 32 binary %% bytes, or as a 40-character string encoded in the Z85 encoding format.
%% %%
curve_publickey
%%
- Set CURVE public key
%%
- type: binary() or string()
%%
Sets the socket's long term public key. You must set this on CURVE %% client sockets. You can provide the key as 32 binary bytes, or as a %% 40-character string encoded in the Z85 encoding format. The public key %% must always be used with the matching secret key.
%% %%
curve_clientkeys
%%
- Provide public keys of authorised clients
%%
- type: list of string() or integer() , or 'any'
%%
Determines which clients are authorised to connect to the server. You %% may set this on CURVE server sockets. If it is not set explictly, if %% defaults to 'any', which means that all clients have access (provided that %% they know the CURVE secret key). If a list of keys is provided, only %% clients with those public keys can connect to the server. You can provide %% the keys as 32-byte binaries or as 40-character strings.
%%
-spec set_socket_option(SocketPid::pid(), Option::socket_option(), Value::term()) -> ok | {error, Reason::atom()}. set_socket_option(SocketPid, Option, Value) when is_pid(SocketPid), is_atom(Option) -> gen_server:call(SocketPid, {set_option, Option, Value}). %% @doc socket to a peer -spec connect(SocketPid::pid(), Transport::transport(), Host::string(), Port::integer(), Resource::term()) -> {ok, PeerPid::pid()} | {error, Reason::atom()}. connect(SocketPid, Transport, Host, Port, Resource) when is_pid(SocketPid), is_atom(Transport), is_list(Host), is_number(Port), is_list(Resource)-> gen_server:call(SocketPid, {connect, Transport, Host, Port, Resource}). connect(SocketPid, Transport, Host, Port) -> connect(SocketPid, Transport, Host, Port, ""). %% @doc bind in a host and port -spec bind(SocketPid::pid(), Transport::transport(), Host::string(), Port::integer()) -> ok. bind(SocketPid, Transport, Host, Port) when is_pid(SocketPid), is_atom(Transport), is_list(Host), is_number(Port)-> gen_server:call(SocketPid, {bind, Transport, Host, Port}). %% @doc send a message for peers -spec send(SocketPid::pid(), Data::binary()) -> ok. send(SocketPid, Data) when is_pid(SocketPid), is_binary(Data) -> gen_server:call(SocketPid, {send, Data}, infinity); send(SocketPid, Data) when is_pid(SocketPid), is_list(Data) -> send(SocketPid, list_to_binary(Data)). %% @doc send a message for peers using a list of binaries -spec send_multipart(SocketPid::pid(), [Data::binary()]) -> ok. send_multipart(SocketPid, Multipart) when is_pid(SocketPid), is_list(Multipart) -> gen_server:call(SocketPid, {send_multipart, Multipart}, infinity). %% @doc recv a message for peers -spec recv(SocketPid::pid()) -> {ok, Data::binary()} | {error, Reason::atom()}. recv(SocketPid) when is_pid(SocketPid) -> gen_server:call(SocketPid, recv, infinity). %% @doc recv a message for peers by a list of binaries -spec recv_multipart(SocketPid::pid()) -> {ok, [Data::binary]} | {error, Reason::atom()}. recv_multipart(SocketPid) when is_pid(SocketPid) -> gen_server:call(SocketPid, recv_multipart, infinity). %% @doc subscribe a topic, only supported in SUB and XSUB patterns. -spec subscribe(SocketPid::pid(), Topic::binary()) -> ok. subscribe(SocketPid, Topic) when is_pid(SocketPid), is_binary(Topic) -> gen_server:cast(SocketPid, {subscribe, Topic}); subscribe(SocketPid, Topic) when is_pid(SocketPid), is_list(Topic) -> subscribe(SocketPid, list_to_binary(Topic)). %% @doc cancel a subscription for a topic, only supported in SUB and XSUB patterns. -spec cancel(SocketPid::pid(), Topic::binary()) -> ok. cancel(SocketPid, Topic) when is_pid(SocketPid), is_binary(Topic) -> gen_server:cast(SocketPid, {cancel, Topic}); cancel(SocketPid, Topic) when is_pid(SocketPid), is_list(Topic) -> cancel(SocketPid, list_to_binary(Topic)). %% @doc start a new resource server. -spec resource() -> {ok, ResourcePid::pid()} | {error, Reason::atom()}. resource() -> ?SUPERVISOR:start_resource(). %% @doc attach a new socket as a resource into resource server. -spec attach_resource(ResourcePid::pid(), Resource::binary(), SocketPid::pid()) -> ok. attach_resource(ResourcePid, Resource, SocketPid) -> gen_server:cast(ResourcePid, {attach, Resource, SocketPid}). -spec version() -> {ok, Version::version()} | {error, Reason::atom()}. version() -> case application:get_application(chumak) of {ok, chumak} -> {ok, return_version()}; undefined -> {error, application_not_started} end. return_version() -> {ok, Version} = application:get_key(chumak, vsn), [X, Y, Z] = string:tokens(Version, "."), Major = list_to_integer(X), Minor = list_to_integer(Y), Patch = list_to_integer(Z), {Major, Minor, Patch}.